Various one-line waveform/pulse generators using the millis timer

In an idle moment I have been playing around with "one line" waveform generation function (led blink etc.) such as:

void loop() {

 . . . 
 const uint32_t mask =   0x1000 | 0x3FF  ;
 digitalWrite( LED1, ( ( ( millis() & 0x1FFF ) | 0x3FF ) == mask  ? HIGH : LOW ) ) ;
 
 digitalWrite( LED2, millis() % 4000 < 1500 ? HIGH : LOW ) ;
 digitalWrite( LED3, millis() % 4096 < 1500 ? HIGH : LOW ) ;  // %power of 2
 digitalWrite( LED4, millis() & 0x200 ? HIGH : LOW ) ;
 . . .

}

to see how these perform. There may be other and better ones which I have not seen/thought of. The initial conclusion is that the one with the modulus arithmetic is the easiest but quite inefficient unless the divisor is a power of 2.

If anyone is interested in playing with it, it is here: https://wokwi.com/projects/455336479619627009

and the code:

Click here to see the code
/*

 Testing various methods of using the millis() timer in the loop() in this example format:

   void loop() {

     . . . 
     const uint32_t mask =   0x1000 | 0x3FF  ;
     digitalWrite( LED1, ( ( ( millis() & 0x1FFF ) | 0x3FF ) == mask  ? HIGH : LOW ) ) ;
     
     digitalWrite( LED2, millis() % 4000 < 1500 ? HIGH : LOW ) ;
     digitalWrite( LED3, millis() % 4096 < 1500 ? HIGH : LOW ) ;  // %power of 2
     digitalWrite( LED4, millis() & 0x200 ? HIGH : LOW ) ;
     . . .

   }


  // calculation for test 1
  0000'0000'0000'0000'0000'0000'0000'0000    // 0
  0000'0000'0000'0000'0001'0000'0000'0000    // 0x1000  (4096)  ~4 seconds  (power of 2)
  0000'0000'0000'0000'0001'1111'1111'1111    // 0x1FFF
  0000'0000'0000'0000'0000'0000'0011'1111    // 0x3F    (31)    63ms

  0000'0000'0000'0000'0000'0010'0000'0000    // 0x200  (512)   (power of 2)

*/



void setup() {
  Serial.begin(115200);
  Serial.println("Starting. . . ") ;

  pinMode( LED_BUILTIN, OUTPUT ) ;
  uint32_t start ;
  uint16_t microTimer ;
  uint16_t microTimerElapsed ;
  volatile bool singleExecution ;

  cli() ;
  TCCR1A = 0x00;
  TCCR1B = (1 << CS10);   // No prescaler 
  TCNT1 = 0x0000;
  sei() ;


  Serial.println("Test 1: period = ~4 seconds, On time = 63ms") ;
  start = millis() ;
  const uint32_t mask =   0x1000 | 0x3FF  ;
  while ( millis() - start < 10000  )  {
    digitalWrite( LED_BUILTIN, ( ( ( millis() & 0x1FFF ) | 0x3FF ) == mask  ? HIGH : LOW ) ) ;
  }
  // time of single execution
  microTimer = TCNT1 ;
  singleExecution = ( ( ( millis() & 0x1FFF ) | 0x3FF ) == mask  ? HIGH : LOW ) ;
  microTimerElapsed = TCNT1 - microTimer ;
  Serial.print( "calculation time single execution (ticks 62.5ns ) = " ) ;
  Serial.println( microTimerElapsed ) ;
  Serial.println() ;



  Serial.println("Test 2: period = 4 seconds , On time = 1.5s") ;
  start = millis() ;
  while ( millis() - start < 10000  )  {
    digitalWrite( LED_BUILTIN, millis() % 4000 < 1500 ? HIGH : LOW ) ;
  }
  // time of single execution
  microTimer = TCNT1 ;
  singleExecution = millis() % 4000 < 1500 ? HIGH : LOW ;
  microTimerElapsed = TCNT1 - microTimer ;
  Serial.print( "calculation time single execution (ticks 62.5ns ) = " ) ;
  Serial.println( microTimerElapsed ) ;
  Serial.println() ;


  Serial.println("Test 3: period = ~4 seconds (% power of 2) , On time = 1.5s") ;
  start = millis() ;
  while ( millis() - start < 10000  )  {
    digitalWrite( LED_BUILTIN, millis() % 4096 < 1500 ? HIGH : LOW ) ;
  }
  // time of single execution
  microTimer = TCNT1 ;
  singleExecution = millis() % 4096 < 1500 ? HIGH : LOW ;
  microTimerElapsed = TCNT1 - microTimer ;
  Serial.print( "calculation time single execution (ticks 62.5ns ) = " ) ;
  Serial.println( microTimerElapsed ) ;
  Serial.println() ;



  Serial.println("Test 4: period = 1024ms, On time = 512ms") ;
  start = millis() ;
  while ( millis() - start < 10000  )  {
    digitalWrite( LED_BUILTIN, millis() & 0x200 ? HIGH : LOW ) ;
  }
  // time of single execution
  microTimer = TCNT1 ;
  singleExecution = millis() & 0x200 ? HIGH : LOW ;
  microTimerElapsed = TCNT1 - microTimer ;
  Serial.print( "calculation time single execution (ticks 62.5ns ) = " ) ;
  Serial.println( microTimerElapsed ) ;
  Serial.println() ;



  Serial.println("End of test") ;
}

void loop() {

}

1 Like