#include <Arduino.h>
// filepath: /c:/IHC Linnaleiri 29A1/IHCNANO/src/main.cpp
#define MODULE_PIN 2 // Define the pin connected to the relay module
#define CONTROL_PORT PORTD // Define the port of the control pin
// Define delay values in microseconds
#define DELAY_START_HIGH 4100*2
#define DELAY_START_LOW 300*2
#define DELAY_D150 150*2
#define DELAY_D300 300*2
#define DELAY_D600 600*2
#define SET_PORT_BIT(port, bit, value) \
if (value) { \
port |= (1 << bit); \
} else { \
port &= ~(1 << bit); \
}
enum State {
START_HIGH,
START_LOW,
D150,
D300,
D600
};
volatile State currentState = START_HIGH;
volatile uint16_t data = 0x1234; // Example data to send
volatile int bitIndex = 0;
void setup() {
pinMode(MODULE_PIN, OUTPUT);
SET_PORT_BIT(CONTROL_PORT,MODULE_PIN, HIGH); // Ensure relay is HIGH during START_HIGH state
// Configure Timer1
cli(); // Disable interrupts
TCCR1A = 0; // Clear Timer1 control register A
TCCR1B = 0; // Clear Timer1 control register B
TCNT1 = 0; // Initialize counter value to 0
// Set up Timer1 for 1us resolution
cli(); // Disable interrupts
// Set Timer1 to CTC mode
TCCR1B |= (1 << WGM12);
// Set the prescaler to 8
TCCR1B |= (1 << CS11);
// Enable Timer1 compare match A interrupt
TIMSK1 |= (1 << OCIE1A);
// Set initial compare value for the first interval (S4100)
OCR1A = DELAY_START_HIGH; // Set compare match register for 4.1 ms
sei(); // Enable interrupts
}
ISR(TIMER1_COMPA_vect) {
static uint8_t parity = 0;
static uint8_t bitNumber = 0;
bool bit = 0;
switch (currentState) {
case START_HIGH:
// Transition to START_LOW state
SET_PORT_BIT(CONTROL_PORT,MODULE_PIN, LOW); // Set output LOW when exiting START_HIGH
currentState = START_LOW;
OCR1A = DELAY_START_LOW; // Set compare match register for 300 us
break;
case START_LOW:
// Transition to D150 or D300 state
SET_PORT_BIT(CONTROL_PORT,MODULE_PIN, HIGH); // Set output HIGH when exiting START_LOW
currentState = D150;
OCR1A = DELAY_D150; // Set compare match register for 150 us
break;
case D150:
// Transition to D600 state
if (bitNumber < 16) {
bit = (data >> bitNumber) & 1;
parity ^= bit;
}
else {
bit = parity;
}
SET_PORT_BIT(CONTROL_PORT,MODULE_PIN, !bit);
currentState = D300;
OCR1A = DELAY_D300 - DELAY_D150; // Set compare match register for 150 us
break;
case D300:
// Transition to D600 state
SET_PORT_BIT(CONTROL_PORT,MODULE_PIN, LOW); // Set output LOW when exiting D300
currentState = D600;
OCR1A = DELAY_D600 - DELAY_D300; // Set compare match register for 300 us
break;
case D600:
// Transition to D150 or D300 state, or START_HIGH if all bits processed
bitNumber++;
SET_PORT_BIT(CONTROL_PORT,MODULE_PIN, HIGH); // Set output HIGH when exiting D600
if (bitNumber < 17) {
currentState = D150;
OCR1A = DELAY_D150; // Set compare match register for 150 us
} else {
currentState = START_HIGH;
OCR1A = DELAY_START_HIGH; // Set compare match register for 4.1 ms
bitNumber = 0;
parity = 0;
}
break;
}
}
void loop() {
// Main loop does nothing, all work is done in ISR
}