-
Notifications
You must be signed in to change notification settings - Fork 0
/
rda1846.c
219 lines (174 loc) · 6.67 KB
/
rda1846.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// RDA1846 Radio interface for the TM4C123
// with packet radio transmission capability
//
// Based on work by InductiveTwig / HamShield
//
// Allen Snook
// 2 March 2020
#include "rda1846.h"
#include "pwm-i2c.h"
#define RDA1846_CLK_MODE_R 0x04
#define RDA1846_GPIO_MODE_R 0x1F
#define RDA1846_FREQ_HI_R 0x29
#define RDA1846_FREQ_LO_R 0x2A
#define RDA1846_CTL_R 0x30
#define RDA1846_TX_VOICE_R 0x3A
#define RDA1846_RX_VOLUME_R 0x44
#define RDA1846_SQ_THRESH_R 0x49
// Private methods
void _RDA1846_Set_Narrow_Band() {
// Set up for 12.5 kHz channel width
PWM_I2C_Queue_Command( 0x11, 0x3D37, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x12, 0x0100, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x15, 0x1100, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x32, 0x4495, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x34, 0x2B8E, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x3A, 0x40C3, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x3C, 0x0F1E, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x3F, 0x28D0, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x48, 0x20BE, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x60, 0x1BB7, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x62, 0x0A10, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x65, 0x2494, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x66, 0xEB2E, 0xFFFF, 0 );
// AGC table
PWM_I2C_Queue_Command( 0x7F, 0x0001, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x05, 0x000C, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x06, 0x020C, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x07, 0x030C, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x08, 0x0324, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x09, 0x1344, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x0A, 0x3F44, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x0B, 0x3F44, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x0C, 0x3F44, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x0D, 0x3F44, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x0E, 0x3F44, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x0F, 0x3F44, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x12, 0xE0ED, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x13, 0xF2FE, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x14, 0x0A16, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x15, 0x2424, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x16, 0x2424, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x17, 0x2424, 0xFFFF, 0 );
// Last command ends the AGC table and needs a 100 ms delay
PWM_I2C_Queue_Command( 0x7F, 0x0, 0xFFFF, 100 );
}
void _RDA1846_Soft_Reset() {
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0x1, 0xFFFF, 100 );
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0x4, 0xFFFF, 0 );
}
void _RDA1846_Set_Clock_Mode( uint8_t mode ) {
if ( 0 == mode ) {
PWM_I2C_Queue_Command( RDA1846_CLK_MODE_R, 0x0FD0, 0xFFFF, 0 );
} else {
PWM_I2C_Queue_Command( RDA1846_CLK_MODE_R, 0x0FD1, 0xFFFF, 0 );
}
}
void RDA1846_Set_TX() {
// TODO: Add 70cm support
// Disable RX (Clear b:5)
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0, 0xFFDF, 0 );
// Set GPIO 5 (Set b:11)
PWM_I2C_Queue_Command( RDA1846_GPIO_MODE_R, 0x0800, 0xF7FF, 0 );
// Set GPIO 4 (b:9) Low, sleep 50 ms
PWM_I2C_Queue_Command( RDA1846_GPIO_MODE_R, 0, 0xFDFF, 50 );
// Enable TX (Set b:6)
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0x0040, 0xFFBF, 0 );
}
void RDA1846_Set_RX() {
// Disable TX (Clear b:6)
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0, 0xFFBF, 0 );
// Set GPIO 5 (b:11) Low
PWM_I2C_Queue_Command( RDA1846_GPIO_MODE_R, 0, 0xF7FF, 0 );
// Set GPIO 4 (b:9) Low, sleep 50 ms
PWM_I2C_Queue_Command( RDA1846_GPIO_MODE_R, 0, 0xFDFF, 50);
// Enable RX (Set b:5)
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0x0020, 0xFFDF, 0 );
}
void _RDA1846_Set_Transmit_Source_PWM_Mic() {
PWM_I2C_Queue_Command( RDA1846_TX_VOICE_R, 0x4, 0xFFFF, 0 );
}
void RDA1846_Set_Squelch( uint8_t on ) {
if ( 0 != on ) {
// Turn squelch on (Set b: 3)
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0x0008, 0xFFF7, 0 );
} else {
// Turn squelch off (Clear b: 3)
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0x0, 0xFFF7, 0 );
}
}
void _RDA1846_Set_Squelch_Threshholds( int16_t openThreshhold, int16_t shutThreshhold ) {
// Open: bits 13:7
// Shut: bits 6:0
openThreshhold += 137;
shutThreshhold += 137;
uint16_t threshhold = ( openThreshhold << 7 ) | ( shutThreshhold & 0x3F );
PWM_I2C_Queue_Command( RDA1846_SQ_THRESH_R, threshhold, 0xFFFF, 0 );
}
void _RDA1846_Get_RSSI() {
// TODO
}
// Public methods
void RDA1846_Wait_For_Channel( /* callback */ ) {
}
void RDA1846_Set_Frequency_KHz( uint32_t freqKHZ ) {
uint32_t freqRaw = freqKHZ << 4;
// Turn off RX and TX
PWM_I2C_Queue_Command( RDA1846_CTL_R, 0, 0xFF9F, 0 );
PWM_I2C_Queue_Command( 0x05, 0x8763, 0xFFFF, 0 );
// Send top half to high register, bottom half to low
PWM_I2C_Queue_Command( RDA1846_FREQ_HI_R, ( 0x3FFF & (freqRaw >> 16 ) ), 0xFFFF, 0 );
PWM_I2C_Queue_Command( RDA1846_FREQ_LO_R, ( freqRaw & 0xFFFF ), 0xFFFF, 0 );
RDA1846_Set_RX();
}
/*
* volume 1: 0-15
* volume 2: 0-15
*/
void RDA1846_Set_Volume( uint16_t volume1, uint16_t volume2 ) {
uint16_t rawVolume = ( volume1 & 0x000F ) << 4;
rawVolume |= volume2 & 0x000F;
PWM_I2C_Queue_Command( RDA1846_RX_VOLUME_R, rawVolume, 0xFFFF, 0);
}
void RDA1846_Set_Power( uint8_t power ) {
}
void RDA1846_Test_Connection( /* callback */ ) {
}
void RDA1846_Send_Packet( char *data ) {
}
void _RDA1846_Init_Complete_Callback() {
PWM_I2C_Set_Callback( 0 );
// Finish setting up the radio
RDA1846_Set_Frequency_KHz( 144390 );
RDA1846_Set_RX();
RDA1846_Set_Volume( 12, 12 );
RDA1846_Set_Squelch( 0 ); // off
}
void RDA1846_Init() {
PWM_I2C_Init();
PWM_I2C_Set_Callback( _RDA1846_Init_Complete_Callback );
_RDA1846_Soft_Reset();
PWM_I2C_Queue_Command( 0x09, 0x03AC, 0xFFFF, 0 ); // Set GPIO voltage for 3.3V
PWM_I2C_Queue_Command( 0x0A, 0x47E0, 0xFFFF, 0 ); // Set PGA Gain
PWM_I2C_Queue_Command( 0x13, 0xA100, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x1F, 0x5001, 0xFFFF, 0 ); // GPIO7->VOX, GPIO0->CTC/DCS
PWM_I2C_Queue_Command( 0x31, 0x0031, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x33, 0x0AF2, 0xFFFF, 0 ); // AGC
PWM_I2C_Queue_Command( 0x41, 0x067F, 0xFFFF, 0 ); // Voice gain
PWM_I2C_Queue_Command( 0x44, 0x02FF, 0xFFFF, 0 ); // TX gain
PWM_I2C_Queue_Command( 0x47, 0x7F2F, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x4F, 0x2C62, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x53, 0x0094, 0xFFFF, 0 ); // Compressor update time
PWM_I2C_Queue_Command( 0x54, 0x2A18, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x55, 0x0081, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x56, 0x0B22, 0xFFFF, 0 ); // Squelch detection time
PWM_I2C_Queue_Command( 0x57, 0x1C00, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x58, 0x800D, 0xFFFF, 0 );
PWM_I2C_Queue_Command( 0x5A, 0x0EDB, 0xFFFF, 0 ); // Noise detection time
PWM_I2C_Queue_Command( 0x63, 0x3FFF, 0xFFFF, 0 ); // Pre-emphasis bypass
// Calibration - wait 100 ms after each command
PWM_I2C_Queue_Command( 0x30, 0x00A4, 0xFFFF, 100 );
PWM_I2C_Queue_Command( 0x30, 0x00A6, 0xFFFF, 100 );
PWM_I2C_Queue_Command( 0x30, 0x0006, 0xFFFF, 100 );
_RDA1846_Set_Narrow_Band();
}