ESP8266 Interrupters timer

Howdy all,
I'm trying to understand how to use the interrupters on an ESP8266. I've written the following code to blink the built-in led on for 1s and then off for 10s. The interrupter timer is set as a single shot so that I can enter the new time after it is called. The timers however seem to be stuck in a 10s loop. Any ideas of why this is happening.
Thanks in advance,
Tuck


bool led_state = true; 
unsigned long cycle_time = 1; 
unsigned long Output     = 10; 

void blink_led()
{
  noInterrupts();
  if (led_state) 
  {
    timer1_detachInterrupt();
    timer1_disable(); 
    timer1_attachInterrupt(blink_led);
    timer1_isr_init();
    timer1_enable(TIM_DIV256, TIM_EDGE, TIM_SINGLE);
    T1L = ((F_CPU * cycle_time) & 0x7FFFFF); 
    if ((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable
    //timer1_write(F_CPU * (cycle_time));
  }
  else 
  {
    timer1_detachInterrupt();
    timer1_disable(); 
    timer1_attachInterrupt(blink_led);
    timer1_isr_init();
    timer1_enable(TIM_DIV256, TIM_EDGE, TIM_SINGLE);
    timer1_write(F_CPU * (Output));
  }

  
  digitalWrite(LED_BUILTIN, led_state);   
  led_state = !led_state; 
  interrupts(); 
}

void setup() {
 pinMode(LED_BUILTIN, OUTPUT);
 blink_led(); 
}

void loop() { ; }

It doesn't make sense to use an interrupt for a 10 second time frame.

Use millis() and the loop() to turn LEDs on or off in the second time range.

I'm not sure I understand why not to use interrupt. Can you explain?
Thanks,

Not really, they are detached, disabled. attached, initialized, and enabled, (and the interval is re-set)
All of that from within it's own callback.
The original interval is the default (don't know what that one btw) but the second time around you set it to the interval you want.

Oh yeah, you are actually using the callback to initialize, but i don't think you need to detach and re-attach and disable etc.
The first time round you make sure

  noInterrupts();

you attach, init, write and then enable, and after that all you really need to do is enable, the rest remains the same.

Agreed. i wouldn't also for any other purpose than education.
Also the timers on an ESP are used by the wifi a lot, i recommend switching to the ticker library.

I when back to an earlier version of the code where I initialized everything in the setup(). The craziness around detached, disabled, attached, and all of that was something I was trying to make it work.

After going down a binary rabbit hole what I found is the timer seems to be a 24-bit number. I had read on the help sites that the number was either 32 or 64 bit. This does not seem to be true. So the biggest value that timer1_write will work with is 1111 1111 1111 1111 1111 1111. Since F_CPU is 0100 1100 0100 1011 0100 0000 0000 this was never going to work. The register was overflowing no matter what was entered. Also at least what I read the point of using F_CPU was because the timer incremented 1 for every clock cycle. This also seems not to be true. Whatever the number entered into timer1_write is there seems to be 312600 per 1000ms. Although I suspect this might vary based on how long the interrupter code takes to run. The corrected working code is below.

bool led_state = true; 
unsigned long cycle_time = 1; 
unsigned long Output     = 10; 
unsigned long last       = millis(); 
unsigned long numPsec        = 312600; 

void blink_led()
{
  noInterrupts();
  Serial.println( millis() - last);

  last = millis(); 

  if(led_state)
    timer1_write(numPsec*Output);
  else 
    timer1_write(numPsec*cycle_time);
  
  digitalWrite(LED_BUILTIN, led_state);   
  led_state = !led_state; 
  interrupts(); 
}

void setup() {
  Serial.begin(115200); 

  pinMode(LED_BUILTIN, OUTPUT);
  timer1_attachInterrupt(blink_led);
  timer1_isr_init();
  timer1_enable(TIM_DIV256, TIM_EDGE, TIM_SINGLE);
  blink_led(); 
}

void loop() { ; }

Well i somehow anyway think that initializing / enabling the timer by calling it's callback is not the proper procedure.
and there is no need to do so. That way you can get rid of the noInterrupts(), because the callback will now be considered to be an ISR, in which interrupts are always enabled.
Of course normally it is not recommended to write to the UART from within an ISR, but with the size of the ESP's fifo, you are getting away with it.

Maybe if you should read the Callback from RAM using e ICACHE_RAM_ATTR.
Anyway, the timers on an ESP are poorly documented, and my experience is that using them in combination with using wifi, doesn't work, unless i use the ticker library.

Ok,
I want to document this madness for anyone that tries to venture down this same path. After some more playing with the timers, it looks like I made a mistake assuming that the timer had overflowed. It was my unsigned long that had overflowed. As I have heard it said if you assume something, you'll make yourself look like the first three letters of assume.

Anyway, the code I used to test this is below but it looks like the timer1 is at least 8 bytes. My uint64_t overflow there also, and I get an error with uint128_t. So I can't go any bigger. I suppose there is a way to go bigger but I'm not aware of how. If anyone knows I would be interested.

uint64_t cycle_time = 0; 
int last_bytte = -1; 

void cycle_I()
{
  noInterrupts();

  int bytte = 0; 
  uint64_t current_cycle = cycle_time; 
  cycle_time = cycle_time << 8;    // Shift one byte over
  cycle_time += B11111111;         // Add one more byte

  while (current_cycle != 0)
  {
    bytte++; 
    current_cycle = current_cycle >> 8;
  }

  if (bytte == last_bytte)
  {
    Serial.print("The timer has stopped incressing at "); 
    Serial.print(last_bytte); 
    Serial.println(" bytes."); 
  }
  
  timer1_write(cycle_time);

  Serial.print("Trying "); Serial.print(bytte); Serial.println(" bytes."); 
  last_bytte = bytte; 

  interrupts(); 
}

void setup() {
  Serial.begin(115200); 
  while(!Serial); 
  delay(5*1000); 
  
  Serial.print("Size of varible being used is "); 
  Serial.println(sizeof(cycle_time)); 

  timer1_attachInterrupt(cycle_I);
  timer1_isr_init();
  
  //TIM_DIV1 = 0,   //80MHz (80 ticks/us - 104857.588 us max)
  //TIM_DIV16 = 1,  //5MHz (5 ticks/us - 1677721.4 us max)
  //TIM_DIV256 = 3 //312.5Khz (1 tick = 3.2us - 26843542.4 us max)
  
  timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
  
  cycle_I(); 
}

void loop() { ; }