#include <avr/interrupt.h>
volatile unsigned int delayValue = 20; // Default delay in µs. Must be at least 10 on a 16MHz Arduino
uint8_t last_CH1_state = 0;
const int PinDiac = 3;
const int interruptLatencyCycles = 20; // 20 clock cycles between ZeroCrossSignal and PinDiac signal
enum { LedOn = HIGH, LedOff = LOW };
void setup() {
Serial.begin(9600);
// Enable Pin Change Interrupt for D8
PCICR |= (1 << PCIE0);
PCMSK0 |= (1 << PCINT0);
// Set up Timer1 for interrupt
noInterrupts(); // Disable interrupts temporarily
TCCR1A = 0; // Reset Timer1 control registers
TCCR1B = 0;
TCNT1 = 0; // Reset Timer1 counter
// Turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// Calculate and set the compare match register for the new delay in microseconds
OCR1A = (F_CPU / 8 / 1000000) * delayValue - interruptLatencyCycles;
// Set D2 as output
// DDRD |= (1 << DDD2); // Set D2 as output
pinMode(2, OUTPUT);
interrupts(); // Enable interrupts
pinMode(PinDiac, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(PinDiac, HIGH);
digitalWrite(LED_BUILTIN, LedOff);
}
void loop() {
if (Serial.available()) {
char rec = Serial.read();
switch (rec) {
case 181:
digitalWrite(LED_BUILTIN, LedOff);
break;
case 182:
digitalWrite(LED_BUILTIN, LedOn);
break;
default:
delayValue = map(rec, 0, 180, 10, 6700);
Serial.print(" delayValue ");
Serial.println(delayValue);
// Calculate and set the compare match register for the new delay in microseconds
OCR1A = (F_CPU / 8 / 1000000) * delayValue - interruptLatencyCycles ;
break;
}
}
}
// Timer1 interrupt service routine
ISR(TIMER1_COMPA_vect) {
digitalWrite(PinDiac, HIGH);
// Disable Timer1 compare interrupt
TIMSK1 &= ~(1 << OCIE1A);
delayMicroseconds(100);
digitalWrite(PinDiac, LOW);
}
// Pin Change Interrupt Service Routine
ISR(PCINT0_vect) {
// Set D2 HIGH using SBI instruction
// asm volatile ("sbi %0, %1" :: "I" (_SFR_IO_ADDR(PORTD)), "I" (PORTD2));
uint8_t currentState = PINB & B00000001;
if (currentState != last_CH1_state) {
last_CH1_state = currentState;
// Reset Timer1 counter
TCNT1 = 0;
// Enable Timer1 compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
// Set D2 LOW using CBI instruction
// asm volatile ("cbi %0, %1" :: "I" (_SFR_IO_ADDR(PORTD)), "I" (PORTD2));
}