13
13
#define GREEN_LED PIN_PA7 // GREEN LED
14
14
#define RED_LED PIN_PA6 // RED LED
15
15
16
- #define HEARTBEAT_PERIOD_DEFAULT_MS (1000 )
16
+ #define HEARTBEAT_PERIOD_DEFAULT_MS (2000 )
17
17
#define HEARTBEAT_PERIOD_ERROR_MS (60 )
18
18
19
19
#define DEBUG_MODE 0
@@ -44,7 +44,7 @@ typedef enum {
44
44
45
45
// TODO :: non-linear opacity mapping here. Lowest values show no change (0 to 10, 10 to 20), then seems solid for a
46
46
// bit, then highest values indistinguishable w/o light behind valve
47
- static const uint16_t pwm_counts_by_data_value [16 ] = {
47
+ static const uint16_t pwm_counts_by_data_index [16 ] = {
48
48
0 ,
49
49
10 ,
50
50
20 ,
@@ -77,19 +77,21 @@ static uint32_t clock_period_us;
77
77
static uint32_t clock_period_padding_us;
78
78
static uint8_t data_edges_counted;
79
79
static uint8_t clock_edges_counted;
80
+ static uint16_t edges = 0 ;
80
81
81
- static uint8_t rx_start_bits;
82
- static uint8_t rx_data_bits;
83
- static uint8_t device_addr = 0x1 ; // TODO :: eventually this is set dynamically
84
- static uint16_t current_data_value = 0x0 ;
85
- static bool up = true ; // TODO :: debug hack delete
82
+ static uint8_t rx_start_bits;
83
+ static uint8_t rx_data_bits;
84
+ static uint8_t device_addr = 0x1 ; // TODO :: eventually this is set dynamically
85
+ static uint8_t rx_data[ 16 ] = { 0x0 } ;
86
+ static uint8_t rx_data_idx = 0 ;
86
87
87
88
/* #if DEBUG_MODE */
88
89
static SoftwareSerial debug_serial (UART_RX, UART_TX);
89
90
/* #endif */
90
91
91
92
void data_pin_isr (void ) {
92
93
data_transition_flag = true ;
94
+ edges++;
93
95
}
94
96
95
97
ISR (TCA0_OVF_vect) {
@@ -102,9 +104,11 @@ ISR(TCA0_OVF_vect) {
102
104
* Set up timer to expected timeout values and enabled interrupt. Does not start timer
103
105
*/
104
106
void timeout_timer_init (void ) {
105
- // With prescaler of 16 @ 20MHz (aka 1.25MHz) this is ~6.5ms. Currently a full packet is 13 bits @ 500us/bit,
106
- // or 6.5ms total.
107
- TCA0.SINGLE .PER = 8125 - 1 ;
107
+ // With prescaler of 16 @ 20MHz (aka 1.25MHz) 2000 tick period is 1.6ms. Should be se so if in worst case there's
108
+ // one extra transition at the end of the packet,, timeout timer will still expire and reset state before next
109
+ // packet starts.
110
+ // TCA0.SINGLE.PER = 8125 - 1;
111
+ TCA0.SINGLE .PER = 2000 - 1 ;
108
112
TCA0.SINGLE .CNT = 0 ;
109
113
110
114
// Divide 20MHz down to 5MHz
@@ -189,9 +193,17 @@ void pwm_timer_sync(void) {
189
193
TCD0.CTRLE = TCD_SYNCEOC_bm;
190
194
}
191
195
196
+ void light_valve_set_opacity (uint8_t opacity_index) {
197
+ TCD0.CMPACLR = 0x000 + pwm_counts_by_data_index[opacity_index];
198
+ TCD0.CMPBSET = 0xFFF - pwm_counts_by_data_index[opacity_index];
199
+
200
+ // Values will never load into TCD buffers until re synced
201
+ pwm_timer_sync ();
202
+ }
203
+
192
204
void setup () {
193
205
timeout_timer_init ();
194
- pwm_timer_init ();
206
+ /* pwm_timer_init(); */
195
207
196
208
// - set up data pin as input and 2 light valve pins + test GPIO as output and low
197
209
// - start pwm for output valve pins at either fully clear or fully opaque (TODO :: run a fancy startup or bink to
@@ -203,24 +215,23 @@ void setup() {
203
215
// - set up light valve pins as output w/ PWM support
204
216
// - set up timer with no period, that will be set from second pair of transitions in
205
217
// ///////////////////////
206
- uint8_t bit = digitalPinToBitMask (DATA_PIN);
207
- PORTA.DIRSET = bit;
208
- bit = digitalPinToBitMask (PIN_PA4);
209
- PORTA.DIRSET = bit;
210
- /* PORTA.DIRCLR = bit; */
218
+
219
+ uint8_t bit = digitalPinToBitMask (DATA_PIN);
220
+ /* PORTA.DIRSET = bit; */
221
+ /* bit = digitalPinToBitMask(PIN_PA4); */
222
+ /* PORTA.DIRSET = bit; */
223
+ PORTA.DIRCLR = bit;
211
224
/* DATA_PIN_INT_CTRL_REG |= 0x1; // interrupt on both edges - attiny 212 DS sec. 16.5.11 */
212
- /* attachInterrupt(DATA_PIN, data_pin_isr, CHANGE); */
225
+ attachInterrupt (DATA_PIN, data_pin_isr, CHANGE);
213
226
214
227
bit = digitalPinToBitMask (RED_LED);
215
228
PORTA.DIRSET = bit;
216
229
bit = digitalPinToBitMask (GREEN_LED);
217
230
PORTA.DIRSET = bit;
218
231
PORTA.OUTCLR = 0xFF ;
219
232
220
- // TODO :: switch back to normal pindirs for PWM functionality
221
233
bit = digitalPinToBitMask (UART_TX);
222
234
PORTB.DIRSET = bit;
223
- PORTB.OUTCLR = 0xFF ;
224
235
bit = digitalPinToBitMask (UART_RX);
225
236
PORTB.DIRCLR = bit;
226
237
/* bit = digitalPinToBitMask(LIGHT_VALVE_PIN_1); */
@@ -229,27 +240,26 @@ void setup() {
229
240
/* PORTB.DIRSET = bit; */
230
241
/* PORTB.OUTCLR = 0xFF; */
231
242
243
+ // Init globals
232
244
current_state = DECODE_STATE_IDLE;
233
245
data_transition_flag = false ;
246
+ heartbeat_mode = HEARTBEAT_MODE_DEBUG;
247
+ heartbeat_period_ms = HEARTBEAT_PERIOD_DEFAULT_MS;
248
+ clock_rate_start_us = 0 ;
249
+ clock_period_us = (uint32_t )100 * 1000 ;
250
+ previous_time = millis ();
251
+ clock_edge_start = 0 ;
252
+ data_edges_counted = 0 ;
253
+ clock_edges_counted = 0 ;
254
+ rx_data_idx = 0 ;
255
+ memset (rx_data, 0 , sizeof (rx_data));
234
256
235
- // Default to toggle heartbeat ever half second. Transition to rapid blink indicates error.
236
- heartbeat_mode = HEARTBEAT_MODE_DEBUG;
237
- heartbeat_period_ms = HEARTBEAT_PERIOD_ERROR_MS;
238
- clock_rate_start_us = 0 ;
239
- clock_period_us = (uint32_t )500 * 1000 ;
240
- previous_time = millis ();
241
- clock_edge_start = 0 ;
242
- data_edges_counted = 0 ;
243
- clock_edges_counted = 0 ;
244
-
245
- /* #if DEBUG_MODE */
246
257
debug_serial.begin (9600 );
247
- debug_serial.println (" Light valve node firmware" );
248
- /* #endif */
258
+ debug_serial.println (" LVNF" );
249
259
250
260
// Globally enable interupts
251
261
sei ();
252
- pwm_timer_start ();
262
+ /* pwm_timer_start(); */
253
263
}
254
264
255
265
void loop () {
@@ -321,8 +331,13 @@ void loop() {
321
331
break ;
322
332
}
323
333
case DECODE_STATE_MEASURING_CLOCK_RATE: {
324
- clock_period_us = now_us - clock_rate_start_us;
325
- clock_period_padding_us = clock_period_us / 10 ;
334
+ clock_period_us = now_us - clock_rate_start_us;
335
+ uint8_t bit = digitalPinToBitMask (RED_LED);
336
+ PORTA.OUTTGL = bit;
337
+
338
+ // TODO :: tune this. Can be tight as /10 when clock period >= 200us, but below that need to widen
339
+ // envelop due to rise/fall time slew of signal at uC pin
340
+ clock_period_padding_us = clock_period_us / 5 ;
326
341
327
342
LOG (" clck per us: " );
328
343
LOGLN (clock_period_us);
@@ -381,9 +396,8 @@ void loop() {
381
396
382
397
current_state = DECODE_STATE_READING_DATA;
383
398
} else {
384
- debug_serial.println (" err DSRS strtbts" );
385
- debug_serial.print (" start bits: 0b" );
386
- debug_serial.println (rx_start_bits, BIN);
399
+ LOG (" err strtbts: 0b" );
400
+ LOGLN (rx_start_bits, BIN);
387
401
current_state = DECODE_STATE_ERROR;
388
402
}
389
403
}
@@ -416,8 +430,8 @@ void loop() {
416
430
break ;
417
431
}
418
432
default :
419
- debug_serial. print (" err DSRD" );
420
- debug_serial. println (data_edges_counted);
433
+ LOG (" err DSRD" );
434
+ LOGLN (data_edges_counted);
421
435
current_state = DECODE_STATE_ERROR;
422
436
break ;
423
437
}
@@ -437,11 +451,15 @@ void loop() {
437
451
timeout_timer_stop ();
438
452
uint8_t rx_addr_bits = (rx_data_bits & 0xF0 ) >> 4 ;
439
453
if (rx_addr_bits == device_addr) {
440
- debug_serial.print (" rx data: 0b" );
441
- debug_serial.println ((rx_data_bits & 0x0F ), BIN);
454
+ light_valve_set_opacity (rx_data_bits & 0x0F );
455
+
456
+ LOG (" rx data: 0b" );
457
+ LOGLN ((rx_data_bits & 0x0F ), BIN);
458
+ rx_data[rx_data_idx] = rx_data_bits & 0x0F ;
459
+ rx_data_idx++;
442
460
} else {
443
- debug_serial. print (" rx wrong addr: " );
444
- debug_serial. println (rx_addr_bits, BIN);
461
+ LOG (" rx wrong addr: " );
462
+ LOGLN (rx_addr_bits, BIN);
445
463
}
446
464
447
465
uint8_t bit = digitalPinToBitMask (RED_LED);
@@ -475,19 +493,22 @@ void loop() {
475
493
/* PORTA.OUTTGL = bit; */
476
494
}
477
495
478
- if (current_data_value == 15 ) {
479
- up = false ;
480
- } else if (current_data_value == 0 ) {
481
- up = true ;
482
- }
483
-
484
- current_data_value += up ? 1 : -1 ;
496
+ debug_serial.println (rx_data_idx, DEC);
497
+ /*
498
+ * Uncomment to print all 16 debug opacity values saved to debug buffer
499
+ *
500
+ if (rx_data_idx > 0) {
501
+ for (int i = 0; i < rx_data_idx; i++) {
502
+ debug_serial.print(rx_data[i]);
503
+ debug_serial.print(", ");
504
+ rx_data[i] = 0x0;
505
+ delay(50);
506
+ }
485
507
486
- TCD0.CMPACLR = 0x000 + pwm_counts_by_data_value[current_data_value];
487
- TCD0.CMPBSET = 0xFFF - pwm_counts_by_data_value[current_data_value];
488
- debug_serial.print (" current_data_value: " );
489
- debug_serial.println (current_data_value);
490
- pwm_timer_sync ();
508
+ rx_data_idx = 0;
509
+ }
510
+ */
511
+ rx_data_idx = 0 ;
491
512
492
513
previous_time = now;
493
514
}
0 commit comments