This repository has been archived by the owner on Jan 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
afsk_tx.c
150 lines (109 loc) · 3.18 KB
/
afsk_tx.c
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
142
143
144
145
146
147
148
149
150
/*
* AFSK modulation for transmitter.
*
* Adapted from Polaric Tracker code.
* By LA7ECA, [email protected] and LA3T.
*/
#include "ch.h"
#include "hal.h"
#include "radio.h"
#include "afsk.h"
#include "defines.h"
#define CLOCK_FREQ 1200
static uint8_t _buf[AFSK_TX_QUEUE_SIZE];
static output_queue_t oq;
static bool transmit = false;
output_queue_t* afsk_tx_init()
{
oqObjectInit(&oq, _buf, AFSK_TX_QUEUE_SIZE, NULL, NULL);
return &oq;
}
/*********************************************************************
* Turn on/off transmitter and tone generator
*********************************************************************/
void afsk_PTT(bool on) {
transmit = on;
radio_PTT(on);
if (on)
tone_start();
else
tone_stop();
}
/**************************************************************************
* Get next bit from stream
* Note: see also get_bit() in hdlc_decoder.c
* Note: The next_byte must ALWAYS be called before get_bit is called
* to get new bytes from stream.
*************************************************************************/
static uint8_t bits;
static uint8_t bit_count = 0;
static uint8_t get_bit(void)
{
if (bit_count == 0)
return 0;
uint8_t bit = bits & 0x01;
bits >>= 1;
bit_count--;
return bit;
}
static void next_byte(void)
{
if (bit_count == 0)
{
/* Turn off TX if queue is empty (have reached end of frame) */
if (oqIsEmptyI(&oq)) {
afsk_PTT(false);
return;
}
bits = oqGetI(&oq);
bit_count = 8;
}
}
/*******************************************************************************
* If transmitting, this function should be called periodically,
* at same rate as wanted baud rate.
*
* It is responsible for transmitting frames by toggling the frequency of
* the tone generated by the timer handler below.
*******************************************************************************/
static void afsk_txBitClock(GPTDriver *gptp) {
(void)gptp;
if (!transmit) {
if (oqIsEmptyI(&oq))
return;
else {
/* If bytes in queue, start transmitting */
next_byte();
afsk_PTT(true);
}
}
if ( ! get_bit() )
/* Toggle TX frequency */
tone_toggle();
/* Update byte from stream if necessary. We do this
* separately, after the get_bit, to make the timing more precise
*/
next_byte();
}
/*
* We may either set the main system tick frequency to 1200 (or a multiple) or
* set up a separate GPT timer.
*/
static const GPTConfig bitclock_cfg = {
CLOCK_FREQ,
afsk_txBitClock /* Timer callback.*/
};
/***********************************************************
* Start transmitter.
***********************************************************/
void afsk_tx_start() {
gptStart(&AFSK_TX_GPT, &bitclock_cfg);
gptStartContinuous(&AFSK_TX_GPT, 1);
}
/***********************************************************
* Stop transmitter.
***********************************************************/
void afsk_tx_stop() {
gptStopTimer(&AFSK_TX_GPT);
gptStop(&AFSK_TX_GPT);
}