SingingCat 0
application
ti1101.c
1#include "main-header.h"
2#include "ti1101-settings.h"
3#include "led.h"
4#include "ti1101-pinconfig.h"
5#include "networkif.h"
6#include "ti1101.h"
7#include "irq_router.h"
8#include "metrics/metrics.h"
9
10#define ENDMARK (0)
15#define TI1101_BURST 0x40
16#define TI1101_READ 0x80
17
18static long forwardto = 0;
19static struct network_context *nctx;
20static byte ti1101_enabled = 1;
21static byte overflowed = 0;
22static byte ti1101_failed = 0;
23static byte need_reset;
24static byte ti1101_isready = 0;
25static byte laststatus;
26static byte last_irq_error = 0;
27static byte last_packet_rssi = 0;
28volatile byte ti1101_in_read_loop = 0;
29volatile byte ti1101_locked = 0;
30
31const char *decode_marcstate(int state);
32static int ti1101_reset();
34static void ti1101_select();
35static void ti1101_deselect();
36static int ti1101_read_register(byte offset);
37static int ti1101_read_status_register(byte offset);
38static void ti1101_config_init();
39static byte ti1101_debug = 0;
40
41// see page 93 cc1101 reference manual
42const char *statetable[] = {
43 "SLEEP",
44 "IDLE",
45 "XOFF",
46 "VCOON_MC",
47 "REGON_MC",
48 "MANCAL",
49 "VCOON",
50 "REGON",
51 "STARTCAL",
52 "BWBOOST",
53 "FS_LOCK",
54 "IFADCON",
55 "ENDCAL",
56 "RX",
57 "RX_END",
58 "RX_RST",
59 "TXRX_SWITCH",
60 "RXFIFO_OVERFLOW",
61 "FSTXON",
62 "TX",
63 "TX_END",
64 "RXTX_SWITCH",
65 "TXFIFO_UNDERFLOW",
66 NULL
67};
68
69static int config_entries;
70static byte current_config[102];
71
72#define CHECK_TI1101_FAILURE if (ti1101_failed) { ti1101_failure(); return; }
73#define CHECK_TI1101_FAILURE_S if (ti1101_failed) { ti1101_failure(); printf("TI1101 failed\r\n"); return; }
74#define CHECK_TI1101_FAILURE_V if (ti1101_failed) { ti1101_failure(); return 0; }
75void ti1101_failure() {
76 ;
77}
78void ti1101_set_debug(byte b) {
79 ti1101_debug = b;
80 printf("TI1101: debug enabled\r\n");
81}
82static void lock_failure() {
83 printf("TI1101 lock() timeout!!\r\n");
84}
85
86static byte tx = 0;
87static int ti1101_write_and_read(int data) {
88 if (!ti1101_enabled) {
89 return 0;
90 }
91 tx = 1;
92 uint16_t res;
93
94 mculib_spi_write_and_read(nctx->mculib_handle, ti1101_spiport(), data, &res); // ti1101-spi port
95 tx = 0;
96 return res;
97}
98static int spi_is_transmitting() {
99 return tx;
100}
101
102static int ti1101_write(byte data) {
103 if (!ti1101_enabled) {
104 return 0;
105 }
106 tx = 1;
107 if (mculib_spi_write_only(nctx->mculib_handle, ti1101_spiport(), data) != 0) {
108 tx = 0;
109 return -1;
110 }
111 tx = 0;
112 return 0;
113}
114
115
120 long started = mculib_get_seconds_since_boot();
121
122 while (ti1101_in_read_loop) {
123 if ((mculib_get_seconds_since_boot() - started) > 5) {
124 // more than 5 seconds passed when trying to lock it!
125 lock_failure();
126 return 0;
127 }
128 // wait
129 //mculib_pin_toggle(LED_YELLOW);
130 }
131 ti1101_locked = 1;
132 return 1;
133}
134void ti1101_unlock() {
135 ti1101_locked = 0;
136}
137
138/*
139 * \brief high-level function to reset the ti1101
140 *
141 * configures all the registers.
142 * returns 0 if ok, otherwise an errorcode
143 */
144int internal_ti1101_init(struct network_context *onctx) {
145 int r;
146
147 nctx = onctx;
148 ti1101_config_init();
149 if ((r = mculib_spi_master_enable(nctx->mculib_handle, ti1101_spiport(), 1, SPI_DIR_RW))) {
150 printf("Could not enable spi: %i\r\n", r);
151 return 2;
152 }
153 if ((r = mculib_pin_out(nctx->mculib_handle, ti1101_cssns(), HAL_PIN_SLOWEST))) {
154 printf("Could not enable CSSNS pin: %i\r\n", r);
155 return 2;
156 }
157
158
159 int er = 0;
160
161 mculib_pin_set(nctx->mculib_handle, ti1101_cssns(), 1);
162 ti1101_failed = 0;
163 need_reset = 1;
164 if (!ti1101_lock()) {
165 printf("Failed to lock ti1101 (init) - exit");
166 ti1101_failed = 1;
167 need_reset = 1;
168 return 12;
169 }
170 ti1101_in_read_loop = 0;
171 ti1101_isready = 0;
172 IPLOG("ti1101_on...");
173 ti1101_deselect(); // disable it (re-enable when reading/writing)
174 ti1101_on();
175 IPLOG("OK.");
176 //ti1101_compare_config();
177 er = ti1101_reset();
178 ti1101_unlock();
179 if ((er) || (ti1101_failed)) {
180 printf("ti1101 failed on spi %i, cssns pin %i\r\n", ti1101_spiport(), ti1101_cssns());
181 return 1;
182 }
183 return 0;
184}
185
186// switch the CSn/NSS for the CC1101 off
187void ti1101_select() {
188 mculib_pin_set(nctx->mculib_handle, ti1101_cssns(), 0);
189 /* see page29 of cc1101 reference manual:
190 * "When CSn is pulled low, the MCU must wait
191 * until CC1101 SO pin goes low before starting to
192 * transfer the header byte."
193 */
194 //Delay(10); // wait for S0 to go low. do i really need another pin for that???
195}
196
197// switch the CSn/NSS for the CC1101 on
198void ti1101_deselect() {
199 CHECK_TI1101_FAILURE
200
201 // always wait for transmission to end before we deselect our chip
202 long secs = mculib_get_seconds_since_boot();
203
204 while (spi_is_transmitting()) {
205 if ((mculib_get_seconds_since_boot() - secs) > 2) {
206 ti1101_failed = 1;
207 break;
208 }
209 }
210 mculib_pin_set(nctx->mculib_handle, ti1101_cssns(), 1);
211}
212
213int ti1101_tx() {
214 CHECK_TI1101_FAILURE_V
215 return ti1101_write(0x35); // strobe STX
216}
217void ti1101_rx() {
218 CHECK_TI1101_FAILURE
219 ti1101_write(0x3a); // strobe flush RX
220 ti1101_write(0x36); // strobe SIDLE
221 ti1101_write(0x34); // strobe SRX
222}
223
224/*
225 * \brief low-level function to reset the ti1101
226 *
227 * configures all the registers.
228 * Note that we check the configuration afterwards.
229 * if all registers are 0, we consider this an error,
230 * because usually it means there's nothing connected
231 * returns 0 if ok, otherwise an errorcode
232 */
233static int ti1101_reset() {
234 if (config_get_ti1101disable()) {
235 return 0;
236 }
237 if (!ti1101_enabled) {
238 return 0;
239 }
240 ti1101_disable_irq(nctx);
241
242 ti1101_failed = 0;
243 if (!ti1101_lock()) {
244 printf("Failed to lock ti1101 (reset)- exit");
245 ti1101_failed = 1;
246 return 12;
247 }
248
249 need_reset = 1;
250 overflowed = 0;
251 IPLOG("Resetting ti1101...\r\n");
252 int i = 0;
253
254 ti1101_select();
255 i = mculib_spi_write_only(nctx->mculib_handle, ti1101_spiport(), 0x30); // strobe reset
256 if (i != 0) {
257 printf("Failed to write to spi: %i\r\n", i);
258 ti1101_failed = 1;
259 return 16;
260 }
261 Delay(20);
262 mculib_pin_set(nctx->mculib_handle, ti1101_cssns(), 1);
263 printf("Strobe reset done\r\n");
264 // ti1101_deselect(); // hangs because it keeps transmitting?? weird.
265 Delay(10); // no ti select/deselect reset wait .1s
266 ti1101_select();
267 byte fail = 0;
268
269 CNWDEBUG("ti1101 selected()");
270 i = 0;
271 for (;;) {
272 byte offset = current_config[i++];
273 byte value = current_config[i++];
274 if ((offset == ENDMARK) && (value == ENDMARK)) {
275 break;
276 }
277 //IPLOG("Register %x: %x\r\n", (int)offset, (int)value);
278 if (ti1101_write(offset) == -1) {
279 fail++;
280 }
281 if (ti1101_write(value) == -1) {
282 fail++;
283 }
284 if (fail > 10) {
285 ti1101_failed = 1;
286 break;
287 }
288 }
289
290 ti1101_rx();
291 ti1101_deselect();
292
293 CNWDEBUG("ti1101 deselected()");
294
295 ti1101_isready = 1;
296
297 if (ti1101_failed) {
298 ti1101_unlock();
299 printf("TI1101 failed to reset\r\n");
300 return 1;
301 }
302 int er = ti1101_compare_config();
303
304 ti1101_unlock();
305 if (er) {
306 printf("TI1101 failed config check after reset\r\n");
307 return 2;
308 }
309 ti1101_enable_irq();
310 need_reset = 0;
311 printf("TI1101 was reset (%i)\r\n", ti1101_failed);
312
313 return 0;
314}
315
316
317
318// read all registers, print out those that do not match configuration
319void ti1101_print_config() {
320 CHECK_TI1101_FAILURE_S
321 int i = 0;
322
323 for (i = 0; i < 0x30; i++) {
324 int v = ti1101_read_register(i);
325 IPLOG("Register %x == %x\r\n", i, v);
326 v++; // in case iplog is a noop
327 }
328}
336 CHECK_TI1101_FAILURE_V
337 int i = 0;
338
339 IPLOG("Checking config...\r\n");
340 long start = mculib_get_seconds_since_boot();
341 int nonzero = 0;
342 int okvalues = 0;
343 int failvalues = 0;
344
345 for (;;) {
346 if ((mculib_get_seconds_since_boot() - start) > 3) {
347 return 1;
348 }
349 byte offset = current_config[i++];
350 byte value = (int)current_config[i++];
351 if ((offset == ENDMARK) && (value == ENDMARK)) {
352 break;
353 }
354 //printf("Reading %i ",offset);
355 int v2 = (int)value;
356 int v = ti1101_read_register(offset);
357 //printf(" == %i\r\n",v);
358 if (v != 0) {
359 nonzero++;
360 }
361 if (v != v2) {
362 failvalues++;
363 // IPLOG("Register %x should be %x and is %x \r\n", (int)offset, v2, v);
364 } else {
365 okvalues++;
366 }
367 }
368 IPLOG("cc1101: Config check done (%i, ok=%i,fail=%i)\r\n", nonzero, okvalues, failvalues);
369 if (failvalues > okvalues) {
370 return 1;
371 }
372 if (nonzero) {
373 return 0;
374 }
375 return 1;
376}
381static int ti1101_send(int num_bytes, const byte *data) {
382 if ((!ti1101_enabled) || (config_get_ti1101disable())) {
383 IPLOG("Not sending via radio - radio is not enabled\r\n");
384 return 1;
385 }
386 CHECK_TI1101_FAILURE_V
387 if (need_reset) {
388 return 2;
389 }
390 if (num_bytes == 0) {
391 IPLOG("Reject request to send 0 bytes\r\n");
392 return 3;
393 }
394 if (!ti1101_lock()) {
395 printf("Failed to lock ti1101 (sending) - exit");
396 ti1101_failed = 1;
397 return 4;
398 }
399
400 IPLOG("Sending %i bytes via cc1101\r\n", num_bytes);
401 ti1101_select();
402 ti1101_write(0x36); // strobe SIDLE
403 ti1101_write(0x3b); // strobe FLUSH TX FIFO
404 int i = 0;
405
406 ti1101_write(TI1101_BURST | 0x3f);
407 ti1101_write((byte)num_bytes);
408 for (i = 0; i < num_bytes; i++) {
409 int r = ti1101_write(data[i]);
410 //IPLOG("i=%i,state=0x%x\r\n",i,r);
411 if ((r & 0x0F) < 4) {
412 break;
413 }
414 }
415 ti1101_deselect(); // end burst
416 ti1101_select(); // and start
417 ti1101_tx(); // transmission
418
419 //are there more bytes to send? (than fit into txfifo)
420 for (i++; i < num_bytes; i++) {
421 ti1101_write(0x3f); // send the data (no burst though)
422 int r = ti1101_write(data[i]);
423 int txf;
424 // if less than 4 bytes reported by
425 // chip status byte, we force the readloop of the
426 // txbytes register until more bytes are available
427 txf = ((r & 0x0F) < 4) ? 70 : 50;
428
429 while (txf > 60) {
430 // TODO: add timeout/error handling here
431 txf = ti1101_read_status_register(0x3A); // bytes in txfifo
432 //IPLOG("i=%i,txf=%i,state=0x%x\r\n",i,txf,r);
433 }
434 }
435
436 int marcstate;
437
438 reset_delay_counter(DELAY_TI1101);
439 while (
440 ((marcstate = ti1101_read_status_register(0x35)) != 0)
441 && (marcstate != 13)
442 && (marcstate != 1)
443 && (marcstate != 22)
444 ) {
445 if (get_delay_counter(DELAY_TI1101) > 500) {
446 IPLOG("Timeout in TX, marcstate= %s (%i) - ti1101 reset triggered\r\n", decode_marcstate(marcstate), marcstate);
447 need_reset = 1;
448 ti1101_select();
449 break;
450 }
451 // in this case we remain in this loop as long as the chip has not transitioned to an after-tx state
452 }
453
454 ti1101_deselect(); // exit from burst or tx mode
455 Delay(1); // give it a chance to see it
456 ti1101_select();
457 ti1101_rx();
458 ti1101_deselect();
459 IPLOG("Sending done (marcstate=%s).\r\n", decode_marcstate(marcstate));
460 ti1101_unlock();
461 ti1101_print_status();
462 IncMetric_PKTS_RADIO_CTR_OUT;
463 return 0;
464}
465
466
467// read register, add burst-read, return value or -1 if error
468int ti1101_read_status_register(byte offset) {
469 int i;
470
471 if ((offset < 0x30) || (offset > 0x3F)) {
472 IPLOG("Warning! %x register is not a valid status register read\r\n", offset);
473 }
474 byte reg = TI1101_BURST | TI1101_READ | offset;
475
476 laststatus = ti1101_write_and_read(reg);
477 i = ti1101_write_and_read(0);
478 return i;
479}
480
481// read register, return value or -1 if error
482int ti1101_read_register(byte offset) {
483 CHECK_TI1101_FAILURE_V
484 if (offset >= 0x30) {
485 IPLOG("Warning! register access to %x - it is a strobe/statusregister\r\n", offset);
486 }
487 ti1101_select();
488 byte reg = TI1101_READ | offset;
489 int i;
490
491 ti1101_write_and_read(reg);
492 i = ti1101_write_and_read(0);
493 ti1101_deselect();
494 return i;
495}
496void ti1101_print_status() {
497 CHECK_TI1101_FAILURE_S
498 const char *ms;
499 const char *o = "";
500
501 if (!ti1101_lock()) {
502 printf("Failed to lock ti1101 (print_status) - exit");
503 ti1101_failed = 1;
504 need_reset = 1;
505 }
506 ti1101_select();
507 int marcstate = ti1101_read_status_register(0x35);
508 int rxbytes = ti1101_read_status_register(0x3b);
509 int packetstate = ti1101_read_status_register(0x38);
510
511 ti1101_deselect();
512 if (rxbytes & 0x80) {
513 o = "(OVERFLOW)";
514 rxbytes = rxbytes & 0x7F;
515 }
516 ms = decode_marcstate(marcstate);
517 IPLOG("[%i]RXbytes: %i%s, marcstate=0x%x (%s), laststatus=0x%x, packetstate=0x%x \r\n",
518 ti1101_isready, rxbytes, o,
519 marcstate, ms, laststatus, packetstate);
520 packetstate++; // in case iplog is a noop
521 ms++; // in case iplog is a noop
522 o++; // in case iplog is a noop
523 ti1101_unlock();
524}
525
526// this gets called from the cc1101-gd0-IRQ
527// printf should not be used in here since it might destroy
528// a buffer which is initialised otherwise
529// void ti1101_receive_loop() __attribute__ ((interrupt ("IRQ")));
530void ti1101_receive_loop() {
531 //led_flash(LED_MACHINE, 0xFFFF00, 10);
532 if (!ti1101_enabled) {
533 return;
534 }
535 CHECK_TI1101_FAILURE
536 if (!ti1101_isready) {
537 //IPLOG("Warning: receive_loop called but ti1101 is not ready!\r\n");
538 return;
539 }
540 if (ti1101_locked) {
541 return; // sending? resetting?
542 }
543 if (ti1101_in_read_loop) {
544 return; // avoid double-IRQ (not a race-condition on single-core cpus)
545 }
546 ti1101_in_read_loop = 1;
547 if (ti1101_debug) {
548 printf("ti1101_loop()\r\n");
549 }
550 if (packet_isvalid(PACKETBUFFER_CC1101)) {
551 // error - cannot receive whilst packet is still being processed.
552 //IPLOG("CC1101 PACKET buffer not ready!\r\n");
553 ti1101_in_read_loop = 0;
554 return;
555 }
556
557 int i;
558 int rxbytes;
559
560 ti1101_select();
561
562 int total_bytes = 0;
563
564 //int marcstate = ti1101_read_status_register(0x35);
565 rxbytes = 1;
566 reset_delay_counter(DELAY_TI1101);
567 long started = mculib_get_seconds_since_boot();
568 byte needlen = 0;
569
570 while (rxbytes) {
571 if ((mculib_get_seconds_since_boot() - started) > 3) {
572 need_reset = 1;
573 ti1101_isready = 0;
574 ti1101_failed = 1;
575 last_irq_error = 13;
576 // very broken!!
577 break;
578 }
579
580 // the the number of byes currently in RXFIFO
581 rxbytes = ti1101_read_status_register(0x3b); // field RXBYTES (rxfifo_overflow & num_rxbytes)
582 if (rxbytes == 0) {
583 break;
584 }
585 // was there an rx overflow?
586 if (rxbytes & 0x80) {
587 overflowed = 1;
588 break;
589 }
590 total_bytes = total_bytes + rxbytes;
591 // get & print bytes
592 for (i = 0; i < rxbytes; i++) {
593 // tell chip we want a single byte from rxfifo
594 laststatus = ti1101_write_and_read(TI1101_READ | 0x3f); //3f==RXFIFO, TI1101_READ=="Single Byte"
595 // now read the byte
596 int v = ti1101_write_and_read(0);
597 if (packet_put_byte(PACKETBUFFER_CC1101, (byte)v) < 0) {
598 packet_getbuf(PACKETBUFFER_CC1101)[0] = 0;
599 break; // error adding byte, so there's nothing we can do anymore
600 }
601 }
602
603 needlen = packet_getbuf(PACKETBUFFER_CC1101)[0];
604 needlen++; // including the length byte!
605 if (packet_getbytesinbuf(PACKETBUFFER_CC1101) >= needlen) {
606 packet_mark_valid(PACKETBUFFER_CC1101);
607 }
608 }
609 ti1101_in_read_loop = 0;
610
611 // for the fun of it, get the RSSI of (presumably) most recent packet
612 int res = ti1101_read_status_register(0x34); //34==RSSI, TI1101_READ=="Single Byte"
613
614 last_packet_rssi = (byte)(res & 0xFF);
615 //ti1101_rx();
616
617 // ti1101_deselect();
618}
619
630 IPLOG("ti1101 off\r\n");
631 int res = ti1101_enabled ? 1 : 0;
632
633 ti1101_enabled = 0;
634 return res;
635}
636/*
637 * \brief disable ti1101 (power it off)
638 */
639void ti1101_disable() {
640 IPLOG("ti1101 disable\r\n");
641 ti1101_enabled = 0;
642 mculib_spi_write_only(nctx->mculib_handle, ti1101_spiport(), 0x39); // SLEEP when CSN is high
643 mculib_pin_set(nctx->mculib_handle, ti1101_cssns(), 1);
644}
650void ti1101_on() {
651 IPLOG("ti1101_enable\r\n");
652 ti1101_enabled = 1;
653 mculib_pin_set(nctx->mculib_handle, ti1101_cssns(), 0);
654 need_reset = 1;
655}
656int ti1101_is_enabled() {
657 return ti1101_enabled;
658}
659byte ti1101_read_byte() {
660 return 1;
661}
662
663
664
665int ti1101_read_version() {
666 CHECK_TI1101_FAILURE_V
667 int v;
668
669 ti1101_select();
670
671 v = ti1101_read_status_register(0x31);
672 ti1101_deselect();
673 return v;
674}
675
676const char *decode_marcstate(int state) {
677 int i = 0;
678 const char *tstate;
679
680 while ((tstate = statetable[i]) != NULL) {
681 if (i == state) {
682 return tstate;
683 }
684 i++;
685 }
686 ;
687 return (const char *)"UNDEF";
688}
689
696 byte res = last_irq_error;
697
698 last_irq_error = 0;
699 return res;
700}
701static void forwardPacketBuffer(byte *bs, int len) {
702 if (forwardto == 0) {
703 return;
704 }
705 send_command_one_arg(40, forwardto, bs, ((len >= MAX_SINGLE_ARG_SIZE) ? MAX_SINGLE_ARG_SIZE : len));
706}
707static void printPacketBuffer(byte *bs, int len) {
708 printf("Contents of TI1101 packetbuffer\r\n");
709 int i;
710 int j = 0;
711 int l;
712
713 for (i = 0; i < len; i++) {
714 printf("%x ", bs[i]);
715 if (j > 10) {
716 for (l = 0; l < j; l++) {
717 byte b = bs[i - j + l];
718 if ((b == '\n') || (b == '\r')) {
719 printf(".");
720 } else {
721 printf("%c", b);
722 }
723 }
724 printf("\r\n");
725 j = 0;
726 }
727 j++;
728 }
729 printf("\r\nNote: command parsing starts at start+1!\r\n");
730 printf("END OF BUF LISTING\r\n");
731}
732
733static void ti_got_new_packet(struct command *com) {
734 int sig_ind = last_packet_rssi;
735
736 if (sig_ind >= 128) {
737 sig_ind = (sig_ind - 256) / 2 - 74;
738 } else {
739 sig_ind = sig_ind / 2 - 74;
740 }
741 sig_ind = sig_ind + 128;
742
743 printf("TI packet at: %p from %N (RSSI=%i,sig_ind=%i)\r\n", com, com->sender, last_packet_rssi, sig_ind);
744 IncMetric_PKTS_RADIO_CTR_IN;
745
746 got_new_packet(com, (uint8_t)(sig_ind & 0xFF));
747 printf("TI packet processed\r\n");
748}
749
750void ti1101_event_loop_locked() {
751 /*
752 * here we check the input on the radio - perhaps
753 * there's a command in the ringbuffer
754 * if so, we execute it
755 */
756 struct command *com;
757 int i;
758
759 byte b = ti1101_get_last_irq_error();
760
761 if (b != 0) {
762 printf("TI1101 IRQ Error: %i\r\n", (int)b);
763 }
764 if (overflowed) {
765 printf("RXFIFO overflowed\r\n");
766 ti1101_reset();
767 }
768 if (need_reset) {
769 ti1101_reset();
770 }
771 com = NULL;
772 if (packet_isvalid(PACKETBUFFER_CC1101)) {
773 byte *bs = packet_getbuf(PACKETBUFFER_CC1101);
774 i = packet_getbytesinbuf(PACKETBUFFER_CC1101);
775 if (i > 0) {
776 if (ti1101_debug) {
777 printf("TI1101: %i bytes in buf\r\n", i);
778 }
779 com = command_parse(bs + 1, i - 1);
780 }
781 if (com == NULL) {
782 IncMetric_PKTS_RADIO_INVALID;
783 IPLOG("\r\n*** Invalid command from radio (bufsize=%i)***\r\n",
784 packet_getbytesinbuf(PACKETBUFFER_CC1101));
785 printPacketBuffer(bs, i);
786 forwardPacketBuffer(bs, i);
787 packet_buf_init(PACKETBUFFER_CC1101);
788 need_reset = 1;
789 IPLOG("Packet buf cleared\r\n");
790 } else {
791 com->sourcedev = SOURCE_RADIO;
792 //command_print(com);
793 ti_got_new_packet(com);
794 packet_buf_init(PACKETBUFFER_CC1101);
795 }
796 }
797}
801int ti1101_loop(struct network_context *ctx) {
802 if (!ti1101_enabled) {
803 return 1;
804 }
805 ti1101_lock();
806 ti1101_event_loop_locked();
807 ti1101_unlock();
808 return 0;
809}
810
811
812void ti1101_disable_irq(struct network_context *ctx) {
813 mculib_pin_release(ctx->mculib_handle, ti1101_irqpin());
814 int r = mculib_pin_out(ctx->mculib_handle, ti1101_irqpin(), HAL_PIN_SLOWEST);
815
816 if (r != 0) {
817 printf("Failed to disable irq for ti1101 (%i)\r\n", r);
818 }
819}
820void ti1101_enable_irq() {
821 mculib_pin_release(nctx->mculib_handle, ti1101_irqpin());
822 int r = mculib_pin_in(nctx->mculib_handle, ti1101_irqpin(), HAL_PIN_SLOWEST, HAL_PUSHPULL_DOWN);
823
824 if (r != 0) {
825 printf("Failed to enable irq for ti1101 (%i)\r\n", r);
826 }
827 if (register_softirq(nctx->mculib_handle, ti1101_irqpin(), &ti1101_receive_loop, NULL) != 0) {
828 printf("failed to register softirq for ti1101\r\n");
829 }
830}
831
832/**************************************************
833*** TI 1101 Configuration management
834**************************************************/
838static void ti1101_config_init() {
839 /* copy the config from flash to ram */
840 int i = 0;
841 int t = 0;
842
843 config_entries = 0;
844 for (;;) {
845 int val = RFSETTINGS[i++];
846 int off = RFSETTINGS[i++];
847 current_config[t++] = val;
848 current_config[t++] = off;
849 config_entries++;
850 if ((val == ENDMARK) && (off == ENDMARK)) {
851 break;
852 }
853 }
854}
855
861 struct command *dcom;
862
863 dcom = alloc_command();
864 if (dcom == NULL) {
865 return 1;
866 }
867 command_init(dcom);
868 dcom->target = com->sender;
869 dcom->connid = com->connid;
870 dcom->com = com->com;
871 dcom->flags = COMFLAGS_DATA | COMFLAGS_SUCCESS;
872 command_add_binary_arg(dcom, config_entries * 2, current_config);
873 deliver_command(dcom, NULL);
874 return 0;
875}
879static void set_reg_config(int reg, int value) {
880 int i;
881
882 for (i = 0; i < config_entries; i++) {
883 if (current_config[i * 2] == reg) {
884 int oldv = current_config[i * 2 + 1];
885 if (oldv == value) {
886 return;
887 }
888 current_config[i * 2 + 1] = value;
889 printf("Changed TI1101 register %x from %x to %x\r\n", reg, oldv, value);
890 return;
891 }
892 }
893 current_config[config_entries * 2] = reg;
894 current_config[config_entries * 2 + 1] = value;
895 printf("Set TI1101 register %x to %x\r\n", reg, value);
896 config_entries++;
897 current_config[config_entries * 2] = ENDMARK;
898 current_config[config_entries * 2 + 1] = ENDMARK;
899}
900
906 const char *b;
907
908 b = get_arg(com, 0);
909 int size = get_arg_size(com, 0);
910 int i = 0;
911
912 for (;;) {
913 int reg = b[i++];
914 int val = b[i++];
915 set_reg_config(reg, val);
916 if (i >= size) {
917 break;
918 }
919 }
920 ti1101_reset();
921 return 0;
922}
928void ti1101_forward_radio(long node) {
929 printf("Forwarding all packets to %N\r\n", node);
930 forwardto = node;
931}
932
933int ti1101_transmit(struct network_context *nctx, const byte *data, uint16_t num_bytes) {
934 return ti1101_send((int)num_bytes, data);
935}
int received_radio_set_config(struct command *com)
called when we received radio_set_config command modified the current radio config
Definition: ti1101.c:905
int deliver_command(struct command *com, pkt_callback)
deliver a command to a module
Definition: queue.c:651
void ti1101_forward_radio(long node)
forward all radio packets to this node mostly useful to debug and decode and sniff 3rd party protocol...
Definition: ti1101.c:928
int start(int MCULIBHANDLE, struct sc_firmware_api *api)
this is called when the board powers up
Definition: userhooks.c:31
int ti1101_compare_config()
check the config against the values in flash
Definition: ti1101.c:335
int received_radio_get_config(struct command *com)
called when we received radio_get_config command sends back an answer with the current radio config
Definition: ti1101.c:860
int packet_put_byte(const int num, const byte b)
add a byte to a buffer
Definition: packetbuffer.c:78
void command_init(struct command *com)
initialize a command structure with default values
void ti1101_on()
enable processing of radio
Definition: ti1101.c:650
void packet_mark_valid(const int num)
mark this buffer as containing a valid packet
Definition: packetbuffer.c:108
byte got_new_packet(struct command *com, uint8_t signal_indicator)
stack received a new packet (signal indicator is a 0-255 byte value, interface specific)
Definition: routing.c:111
int packet_getbytesinbuf(const int num)
count bytes in the buffer
Definition: packetbuffer.c:158
int ti1101_loop(struct network_context *ctx)
this is called in the main thread periodically
Definition: ti1101.c:801
int send_command_one_arg(int command, long target, const byte *arg1, int arg1len)
helper function to quickly and easily send a command somewhere return 0 if ok, else errorcode
Definition: routing.c:567
struct command * alloc_command()
allocate a free command
Definition: queue.c:173
byte ti1101_get_last_irq_error()
if we throw an error in the irq we cannot print it directly. save it and return it here....
Definition: ti1101.c:695
byte * packet_getbuf(const int num)
get pointer to the contents of the buffer
Definition: packetbuffer.c:143
int command_add_binary_arg(struct command *com, const int len, const byte *srcbuf)
adds a binary parameter to command returns 0 if ok otherwise errorcode
int ti1101_lock()
lock, return 1 if ok, otherwise it is an error
Definition: ti1101.c:119
const char * get_arg(const struct command *com, int index)
given an argument by index[0..n], will return a pointer to the bytearray (excluding the fieldtype) th...
int get_arg_size(const struct command *com, int index)
given an argument by index [0..n], will returns the size of the value in bytes. for a string/array it...
int packet_isvalid(const int num)
initialize (reset, clear) a given buffer
Definition: packetbuffer.c:125
int ti1101_off()
diable processing of ti1101 commands
Definition: ti1101.c:629
void ti1101_set_debug(byte b)
set debug mode of ti1101
Definition: ti1101.c:78
void packet_buf_init(const int num)
initialize (reset, clear) a given buffer
Definition: packetbuffer.c:37
int com
Definition: command.h:22
long target
Definition: command.h:16
uint8_t connid
Definition: command.h:18
uint8_t flags
Definition: command.h:23
long sender
Definition: command.h:14