forked from reversebias/mitosis
-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.c
294 lines (243 loc) · 9.52 KB
/
main.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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
//#define COMPILE_RIGHT
#define COMPILE_LEFT
#include "mitosis.h"
#include "nrf_drv_config.h"
#include "nrf_gzll.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_rtc.h"
#include "rgb_modes.h"
/*****************************************************************************/
/** Configuration */
/*****************************************************************************/
const nrf_drv_rtc_t rtc_maint = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC0. */
const nrf_drv_rtc_t rtc_deb = NRF_DRV_RTC_INSTANCE(1); /**< Declaring an instance of nrf_drv_rtc for RTC1. */
// Define payload length
#define TX_PAYLOAD_LENGTH 3 ///< 3 byte payload length when transmitting
// Data and acknowledgement payloads
static uint8_t data_payload[TX_PAYLOAD_LENGTH]; ///< Payload to send to Host.
static uint8_t ack_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; ///< Placeholder for received ACK payloads from Host.
// Debounce time (dependent on tick frequency)
#define DEBOUNCE 5
#define ACTIVITY 500
// Key buffers
static uint32_t keys, keys_snapshot;
static uint32_t debounce_ticks, activity_ticks;
static volatile bool debouncing = false;
// Debug helper variables
static volatile bool init_ok, enable_ok, push_ok, pop_ok, tx_success;
// Setup switch pins with pullups
static void gpio_config(void)
{
nrf_gpio_cfg_sense_input(S01, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S02, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S03, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S04, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S05, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S06, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S07, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S08, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S09, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S10, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S11, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S12, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S13, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S14, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S15, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S16, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S17, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S18, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S19, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S20, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S21, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S22, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(S23, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
}
// Return the key states, masked with valid key pins
static uint32_t read_keys(void)
{
return ~NRF_GPIO->IN & INPUT_MASK;
}
// Assemble packet and send to receiver
static void send_data(void)
{
data_payload[0] = ((keys & 1<<S01) ? 1:0) << 7 | \
((keys & 1<<S02) ? 1:0) << 6 | \
((keys & 1<<S03) ? 1:0) << 5 | \
((keys & 1<<S04) ? 1:0) << 4 | \
((keys & 1<<S05) ? 1:0) << 3 | \
((keys & 1<<S06) ? 1:0) << 2 | \
((keys & 1<<S07) ? 1:0) << 1 | \
((keys & 1<<S08) ? 1:0) << 0;
data_payload[1] = ((keys & 1<<S09) ? 1:0) << 7 | \
((keys & 1<<S10) ? 1:0) << 6 | \
((keys & 1<<S11) ? 1:0) << 5 | \
((keys & 1<<S12) ? 1:0) << 4 | \
((keys & 1<<S13) ? 1:0) << 3 | \
((keys & 1<<S14) ? 1:0) << 2 | \
((keys & 1<<S15) ? 1:0) << 1 | \
((keys & 1<<S16) ? 1:0) << 0;
data_payload[2] = ((keys & 1<<S17) ? 1:0) << 7 | \
((keys & 1<<S18) ? 1:0) << 6 | \
((keys & 1<<S19) ? 1:0) << 5 | \
((keys & 1<<S20) ? 1:0) << 4 | \
((keys & 1<<S21) ? 1:0) << 3 | \
((keys & 1<<S22) ? 1:0) << 2 | \
((keys & 1<<S23) ? 1:0) << 1 | \
0 << 0;
nrf_gzll_add_packet_to_tx_fifo(PIPE_NUMBER, data_payload, TX_PAYLOAD_LENGTH);
}
// 8Hz held key maintenance, keeping the reciever keystates valid
static void handler_maintenance(nrf_drv_rtc_int_type_t int_type)
{
send_data();
}
int hw_keys() {
return (keys & (1<<S16)) && (keys & (1<<S17)) && (keys & (1<<S18)); //thumb keys
}
int hw_last = 0;
void hw_keys_handler() {
if (hw_keys() && !hw_last) {
rgb_mode = (rgb_mode + 1) % rgb_num_modes();
hw_last = 1;
}
if (!hw_keys()) {
hw_last = 0;
}
}
// 1000Hz deboudfnce sampling
static void handler_debounce(nrf_drv_rtc_int_type_t int_type)
{
// debouncing, waits until there have been no transitions in 5ms (assuming five 1ms ticks)
if (debouncing)
{
// if debouncing, check if current keystates equal to the snapshot
if (keys_snapshot == read_keys())
{
// DEBOUNCE ticks of stable sampling needed before sending data
debounce_ticks++;
if (debounce_ticks == DEBOUNCE)
{
keys = keys_snapshot;
hw_keys_handler();
send_data();
}
}
else
{
// if keys change, start period again
debouncing = false;
}
}
else
{
// if the keystate is different from the last data
// sent to the receiver, start debouncing
if (keys != read_keys())
{
keys_snapshot = read_keys();
debouncing = true;
debounce_ticks = 0;
}
}
// looking for 500 ticks of no keys pressed, to go back to deep sleep
if (read_keys() == 0)
{
activity_ticks++;
if (activity_ticks > ACTIVITY)
{
nrf_drv_rtc_disable(&rtc_maint);
nrf_drv_rtc_disable(&rtc_deb);
}
}
else
{
activity_ticks = 0;
}
}
// Low frequency clock configuration
static void lfclk_config(void)
{
nrf_drv_clock_init();
nrf_drv_clock_lfclk_request(NULL);
}
// RTC peripheral configuration
static void rtc_config(void)
{
//Initialize RTC instance
nrf_drv_rtc_init(&rtc_maint, NULL, handler_maintenance);
nrf_drv_rtc_init(&rtc_deb, NULL, handler_debounce);
//Enable tick event & interrupt
nrf_drv_rtc_tick_enable(&rtc_maint,true);
nrf_drv_rtc_tick_enable(&rtc_deb,true);
//Power on RTC instance
//nrf_drv_rtc_enable(&rtc_maint);
//nrf_drv_rtc_enable(&rtc_deb);
}
int main()
{
// Initialize Gazell
nrf_gzll_init(NRF_GZLL_MODE_DEVICE);
// Attempt sending every packet up to 100 times
nrf_gzll_set_max_tx_attempts(100);
// Addressing
nrf_gzll_set_base_address_0(0x01020304);
nrf_gzll_set_base_address_1(0x05060708);
// Enable Gazell to start sending over the air
nrf_gzll_enable();
// Configure 32kHz xtal oscillator
lfclk_config();
// Configure RTC peripherals with ticks
rtc_config();
// Configure all keys as inputs with pullups
gpio_config();
// Set the GPIOTE PORT event as interrupt source, and enable interrupts for GPIOTE
NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
NVIC_EnableIRQ(GPIOTE_IRQn);
rgb_init();
// Main loop, constantly sleep, waiting for RTC and gpio IRQs
while(1)
{
__SEV();
__WFE();
__WFE();
rgb_task();
}
}
// This handler will be run after wakeup from system ON (GPIO wakeup)
void GPIOTE_IRQHandler(void)
{
if(NRF_GPIOTE->EVENTS_PORT)
{
//clear wakeup event
NRF_GPIOTE->EVENTS_PORT = 0;
//enable rtc interupt triggers
nrf_drv_rtc_enable(&rtc_maint);
nrf_drv_rtc_enable(&rtc_deb);
debouncing = false;
debounce_ticks = 0;
activity_ticks = 0;
}
}
/*****************************************************************************/
/** Gazell callback function definitions */
/*****************************************************************************/
void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
{
uint32_t ack_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
if (tx_info.payload_received_in_ack)
{
// Pop packet and write first byte of the payload to the GPIO port.
nrf_gzll_fetch_packet_from_rx_fifo(pipe, ack_payload, &ack_payload_length);
}
}
// no action is taken when a packet fails to send, this might need to change
void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
{
}
// Callbacks not needed
void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
{}
void nrf_gzll_disabled()
{}