Contiki 3.x
protobuf-handler.c
1 
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include "contiki.h"
6 #include "contiki-conf.h"
7 
8 #include "dev/protobuf-handler.h"
9 
10 
11 //#define PROTOBUF_HANDLER_DEBUG
12 #ifdef PROTOBUF_HANDLER_DEBUG
13  #define PRINTF(...) printf(__VA_ARGS__)
14 #else
15  #define PRINTF(...)
16 #endif
17 static void (*writebyte)(unsigned char c);
18 
19 static process_event_t callback_event;
20 static struct process *callback_process;
21 static uint8_t processed_data[PROTBUF_MAX_MESSAGE_LENGTH -4]; //doesn't have src/dst or crc
22 static protobuf_data_t callback_data;
23 
24 
25 static uint16_t crc16_up(uint16_t crc, uint8_t a);
26 
27 /*
28  * The exact crc function used in the AVR & python
29  * There is a contiki CRC function but not sure it'll
30  * behave in the same way.
31  */
32 uint16_t
33 crc16_up(uint16_t crc, uint8_t a)
34 {
35 // PRINTF("Starting CRC with 0x%04x\n", crc);
36  uint8_t i;
37 // PRINTF("Processing CRC for 0x%04x\n", a);
38  crc ^= (uint16_t)a;
39 // PRINTF("After XOR = 0x%04x\n", crc);
40  for (i = 0; i < 8; ++i){
41  if (crc & 1){
42  crc = (crc >> 1) ^ 0xA001;
43  }else{
44  crc = (crc >> 1);
45  }
46 // PRINTF("CRC r%d = 0x%04x\n",i, crc);
47  }
48 // PRINTF("CRC RET = 0x%04x\n", crc);
49  return crc;
50 }
51 
52 void
53 protobuf_init(void)
54 {
55  writebyte = NULL;
56  callback_event = (int)NULL;
57  callback_process = NULL;
58 
59 
60 }
61 
62 
63 void
64 protobuf_process_message(uint8_t *buf, uint8_t bytes)
65 {
66  uint16_t rec_crc, cal_crc;
67  uint8_t processed_data_length;
68  uint8_t i;
69  i = 0;
70  cal_crc = 0xFFFF;
71  if(bytes == 0){
72  PRINTF("Spurious interrupt, ignoring\n");
73  return;
74  }else if(bytes < 4){
75  PRINTF("TOO small for valid protocol buffer: %d\n", bytes);
76  return;
77  }
78 
79 #ifdef PROTOBUF_HANDLER_DEBUG
80  printf("Bytes recieved: %i\n", bytes);
81  while (i < bytes){
82  printf("%i,", (int)buf[i++]);
83  }
84  printf("\n");
85 #endif
86 
87  if(buf[1] != PROTBUF_OPCODE_RESPONSE){
88  PRINTF("not a response packet so ignoring\n");
89  }else if(buf[0] != PROTBUF_MASTER_ADDR){
90  printf("not for me: ignoring");
91  }else{
92  rec_crc = ((uint16_t)buf[bytes - 1] << 8) | buf[bytes-2];
93  PRINTF("Recieved CRC: %d\n", rec_crc);
94  for(i=0; i < bytes-2; i++){
95  cal_crc = crc16_up(cal_crc, buf[i]);
96  }
97  PRINTF("Calculated CRC: %d\n", cal_crc);
98  if (rec_crc == cal_crc){
99  PRINTF("CRCs match\n");
100  processed_data_length = bytes -4;
101  PRINTF("Raw data: %d processed data: %d\n", bytes, processed_data_length);
102  memcpy(&processed_data, buf+2, processed_data_length);
103  //first 2 and last 2 bytes are not wanted for storage
104 #ifdef PROTOBUF_HANDLER_DEBUG
105  printf("Callback_data\n");
106  for(i=0; i<processed_data_length; i++){
107  printf("%d:",processed_data[i]);
108  }
109  printf("\n");
110 #endif
111  callback_data.length = processed_data_length;
112  callback_data.data = processed_data;
113  if(callback_process != NULL){
114  process_post(callback_process, callback_event, &callback_data);
115  PRINTF("Process posted\n");
116  }else{
117  printf("No callback registered\n");
118  }
119  }else{
120  printf("CRCs do not match: Ignoring\n");
121  return;
122  }
123  }
124 
125 
126 }
127 
128 
129 
130 
131 void protobuf_send_message(uint8_t addr, uint8_t opcode, uint8_t *payload,
132  int8_t payload_length){
133  PRINTF("protobuf_send_message\n");
134  uint8_t buf[PROTBUF_MAX_MESSAGE_LENGTH];
135  uint8_t buf_length = 0;
136  uint16_t crc = 0xFFFF;
137  uint8_t i=0;
138 #ifdef PROTOBUF_HANDLER_DEBUG
139  printf("Dest: %02x\n", addr);
140  printf("Optcode: %02x\n", opcode);
141  printf("Payload length: %i\n", payload_length);
142 #endif
143 
144 
145  if (payload_length +4 > PROTBUF_MAX_MESSAGE_LENGTH){
146  //allow bytes for crc, dst and opcode
147  //Message too long for avr at other end to handle...
148  printf("Message too long to be sent\n");
149  return;
150  }
151  buf[buf_length++] = addr;
152  buf[buf_length++] = opcode;
153 
154  if (payload_length == 0){
155  //No need to worry about including the payload in the CRC
156  }else{
157  PRINTF("DATA:\n");
158  for(i=0; i < payload_length; i++){
159  PRINTF("payload:%i,", payload[i]);
160  buf[buf_length++] = payload[i];
161  PRINTF("buf:%i\n", buf[buf_length-1]);
162  }
163  }
164  for(i=0; i < buf_length; i++){
165  crc = crc16_up(crc, buf[i]);
166  }
167  buf[buf_length++] = crc & 0xFF; //Get the low order bits
168  buf[buf_length++] = (crc >> 8) & 0xFF;
169  PRINTF("CRC: %04x\n", crc);
170  PRINTF("CRC low: %02x\n", crc & 0xFF);
171  PRINTF("CRC high: %02x\n", (crc >>8) & 0xFF);
172  //ready to send
173 
174  if(writebyte != NULL){
175 // PRINTF("Writing to serial port\n");
176  for(i=0; i < buf_length; i++){
177  writebyte(buf[i]);
178 // PRINTF("\t%d\n", buf[i]);
179  }
180  PRINTF("Finsihed\n");
181  }else{
182  printf("No writebyte specified\n");
183  }
184 }
185 
186 void protobuf_handler_set_writeb(void (*wb)(unsigned char c)){
187  writebyte = wb;
188 }
189 
190 
191 void protobuf_register_process_callback(struct process *p, process_event_t ev){
192  PRINTF("Protobuf callback registered\n");
193  callback_event =ev;
194  callback_process=p;
195 
196 }
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
Definition: process.c:322
#define NULL
The null pointer.