#include #include #include #include #include "delay.h" #include "morse.h" /* Definitions for pins */ #define PORTB_PTT (1 << 0) #define PORTB_SYNCn (1 << 2) #define PORTB_LED (1 << 4) /* Specify ID here */ static const uint8_t renard_id = 0; static const uint8_t num_renards_cycle = 4; // colon (:) represents ERROR static const char letters[] = "eish:"; static const char unique_letter = letters[renard_id]; volatile uint8_t reset_time; volatile uint8_t systick; /* Timer (100Hz increment) */ volatile uint8_t seconds; volatile uint16_t minutes; /*---------------------------------------------------------*/ /* 100Hz timer interrupt generated by OC2 */ /*---------------------------------------------------------*/ ISR(TIMER1_COMPA_vect) { systick++; if (systick == 10) { systick = 0; seconds += 1; } if (seconds == 60) { seconds = 0; minutes++; } if (reset_time) { reset_time = 0; seconds = 0; minutes = 0; } } static int inittimer(void) { /* Start 100Hz system timer (TC2.OC) */ TCCR0B |= (1 << WGM02); // Configure timer for CTC mode TIMSK |= (1 << OCIE1A); // enable overflow interrupt OCR1A = (uint8_t)(F_CPU / 64 / 1000 / 100 - 1); // Set CTC compare value to 10ms TCCR0B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64 // Enable interrupts sei(); return 0; } #define PTT_LOGIC_LOW 0 #if PTT_LOGIC_LOW void dah(void) { PORTB = PORTB_LED; // LED is non-inverted logic delay_ms(3*DIT_DURATION); PORTB = PORTB_PTT; // PTT is inverted logic delay_ms(DIT_DURATION); } void dit(void) { PORTB = PORTB_LED; // LED is non-inverted logic delay_ms(DIT_DURATION); PORTB = PORTB_PTT; // PTT is inverted logic delay_ms(DIT_DURATION); } #else void dah(void) { PORTB = PORTB_PTT | PORTB_LED; delay_ms(3*DIT_DURATION); PORTB = 0; delay_ms(DIT_DURATION); } void dit(void) { PORTB = PORTB_PTT | PORTB_LED; delay_ms(DIT_DURATION); PORTB = 0; delay_ms(DIT_DURATION); } #endif int main(void) { systick = 0; seconds = 0; minutes = 0; reset_time = 0; /* Enable PTT output on PB0 */ #if PTT_LOGIC_LOW PORTB = PORTB_PTT; #endif /* LED is never inverted */ DDRB = PORTB_PTT | PORTB_LED; /* initialise timer interrupt */ inittimer(); static char *morse_string = "MO "; morse_string[2] = unique_letter; const int permanent = (unique_letter == ':'); // In order to have all foxes transmitting all the time // before sync int sync_pending = 1; delay_ms(12*DIT_DURATION); morse("HB9HI"); delay_ms(12*DIT_DURATION); while (1) { if ((PINB & PORTB_SYNCn) == 0) { reset_time = 1; sync_pending = 0; } if (permanent || sync_pending) { morse(morse_string); delay_ms(6*DIT_DURATION); } else if (minutes >= 10) { // see README.md /* renard id 0: start at (k * num_renards_cycle) * 60, end at (k * num_renards_cycle) * 60 + 55 */ const int in_timeslot = (minutes % num_renards_cycle) == renard_id; if (in_timeslot && seconds < 55) { morse(morse_string); delay_ms(6*DIT_DURATION); } else { delay_ms(DIT_DURATION); } } else { /* renard id 0: start every 30s, with an additional 2s offset depending on renard_id */ const uint32_t second_offset = seconds % 30; if (second_offset == 2 * renard_id) { morse_char(unique_letter); delay_ms(1000); // avoid retrigger in same second } } } return 0; }