//--------------------------------------------------------
// Author: RSP / KMUTNB (Bangkok/Thailand)
// Target board: Arduino Uno or Nano
// Date: 2023-03-28
// Description:
// This is an Arduino sketch that demonstrates different ways
// to toggle an LED output pin (use the onboard LED).
//--------------------------------------------------------
#include <avr/wdt.h> // if WDT is used.
#include <TimerOne.h> // if the TimerOne library is used.
#define LED_PIN (LED_BUILTIN) // the default LED pin
#define DELAY_MS (500)
// This global variable is used by ISR.
volatile uint32_t counter = 0;
// Define a function pointer named 'func_ptr',
// which is a pointer to a function takes an integer argument
// and returns void.
typedef void (*func_ptr)(int);
func_ptr led_blink = NULL;
void setup() {
Serial.begin(115200);
pinMode( LED_PIN, OUTPUT );
digitalWrite( LED_PIN, LOW );
// Specify the function used to toggle the LED pin:
// led_blink1, led_blink2, ..., led_blink7.
led_blink = led_blink7;
}
void loop() {
if (led_blink != NULL) {
led_blink(LED_PIN);
}
}
inline void led_toggle() {
// Toggle the default LED pin
digitalWrite( LED_PIN, !digitalRead(LED_PIN) );
}
inline void led_toggle(int pin=LED_PIN) {
// Toggle the specify pin
digitalWrite( pin, !digitalRead(pin) );
}
//--------------------------------------------------------
void led_blink1(int pin) {
// Output HIGH to the LED pin
digitalWrite( pin, HIGH );
delay( DELAY_MS );
// Output LOW to the LED pin
digitalWrite( pin, LOW );
delay( DELAY_MS );
}
//--------------------------------------------------------
void led_blink2(int pin) {
static uint8_t state = 0;
// Toggle the LED pin
digitalWrite( pin, state ^= 1 );
delay( DELAY_MS );
}
//--------------------------------------------------------
void led_blink3(int pin) {
// Toggle the LED pin
led_toggle(pin);
delay( DELAY_MS );
}
//--------------------------------------------------------
void led_blink4(int pin) {
static uint32_t last_update_time = 0;
uint32_t now = millis();
if ( now - last_update_time >= DELAY_MS ) {
// Save the last update time
last_update_time = now;
// Toggle the LED pin
led_toggle(pin);
}
}
//--------------------------------------------------------
void led_blink5(int pin) {
static uint8_t timer1_initialized = 0;
static uint32_t last_counter = 0;
if (timer1_initialized == 0) {
// Mark timer1 as initialized
timer1_initialized = 1;
// Initialize Timer1
init_timer1();
}
else if ( last_counter != counter ) {
// Save the last counter value
last_counter = counter;
// Toggle the LED pin
led_toggle(pin);
}
}
void init_timer1() {
// Set Timer1 to CTC (Clear Timer on Compare) mode
TCCR1A = 0;
TCCR1B = (1 << WGM12);
// Set the timer compare value to generate an interrupt every 500 msec
OCR1A = (31250-1); // (16MHz /256 /2) - 1
// Enable Timer1 compare interrupt
TIMSK1 = (1 << OCIE1A);
// Set Timer1 prescaler to 256 and start the timer
TCCR1B |= (1 << CS12);
// Enable interrupts
sei();
}
ISR(TIMER1_COMPA_vect) {
counter++;
}
//--------------------------------------------------------
void led_blink6(int pin) {
static uint8_t timer1_initialized = 0;
if (timer1_initialized == 0) {
// Mark timer1 as initialized
timer1_initialized = 1;
// Set period in microseconds
Timer1.initialize(500000);
// Attach a callback function
Timer1.attachInterrupt(led_toggle);
}
}
//--------------------------------------------------------
void led_blink7(int pin) {
static uint8_t wdt_initialized = 0;
static uint32_t last_counter = 0;
if (wdt_initialized == 0) {
// Maker WDT as initialized
wdt_initialized = 1;
// Initialize WDT
init_wdt();
}
else if ( last_counter != counter ) {
// Save the last counter value
last_counter = counter;
// Toggle the LED pin
led_toggle(pin);
}
}
void init_wdt() {
// Make sure the WDT is disabled before changing the settings
wdt_reset();
// Set up WDT with 500ms timeout (approximately).
wdt_enable(WDTO_500MS);
// Enable WDT interrupt.
WDTCSR |= (1<<WDIE);
// Reset the WDT
wdt_reset();
// Enable interrupts
sei();
}
ISR(WDT_vect) {
counter++;
}
//--------------------------------------------------------