blob: 4afbbca33617e569ed90f1fcfb353976b8809c2e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#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, zero-indexed (E=0, I=1, ...) */
static const uint8_t renard_id = 4;
static const uint8_t num_renards_cycle = 4;
// colon (:) represents ERROR
static const char letters[] = "EISH:";
static const char unique_letter = letters[renard_id];
static char *morse_string = "M O ";
volatile uint8_t reset_time;
volatile uint8_t systick; /* Timer (100Hz increment) */
volatile uint32_t seconds;
/* 200Hz timer interrupt */
ISR(TIM0_COMPA_vect)
{
systick++;
if (systick == 20) {
systick = 0;
seconds += 1;
}
if (reset_time) {
reset_time = 0;
seconds = 0;
}
}
static int inittimer(void)
{
/* Start 200Hz system timer */
TCCR0B |= (1 << WGM01); // Configure timer for CTC mode
TIMSK |= (1 << OCIE0A); // enable compare match A interrupt
OCR0A = (uint8_t)(F_CPU / 64 / 50); // Set CTC compare value to 50ms
TCCR0B |= ((1 << CS00) | (1 << CS01)); // Start timer at Fcpu/64
// Enable interrupts
sei();
return 0;
}
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);
}
int main(void)
{
systick = 0;
seconds = 0;
reset_time = 0;
/* Enable PTT output on PB0 */
DDRB = PORTB_PTT | PORTB_LED;
/* initialise timer interrupt */
inittimer();
morse_string[4] = 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) {
const uint32_t second = seconds % 60uL;
const uint32_t minute = seconds / 60uL;
if ((PINB & PORTB_SYNCn) == 0) {
reset_time = 1;
sync_pending = 0;
morse("Y");
delay_ms(6*DIT_DURATION);
}
else if (permanent || sync_pending) {
morse(morse_string);
delay_ms(6*DIT_DURATION);
}
else if (minute >= 25) { // 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 = (minute % (uint32_t)num_renards_cycle) == renard_id;
if (in_timeslot && second < 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 = second % 30uL;
if (second_offset == 2 * renard_id) {
morse_char(unique_letter);
delay_ms(1000); // avoid retrigger in same second
}
else {
delay_ms(50);
}
}
}
return 0;
}
|