00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #define DEBUG 0 //Making this 1 will slightly alter command timings
00057 #if DEBUG
00058 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00059 #else
00060 #define PRINTF(...)
00061 #endif
00062 #define DEBUGSERIAL 0 //Making this 1 will significantly alter command timings
00063
00064 #include "contiki.h"
00065 #include "contiki-lib.h"
00066 #include "contiki-net.h"
00067
00068 #if WEBSERVER
00069 #include "webserver-nogui.h"
00070 #include "httpd-cgi.h"
00071 #endif
00072
00073 #include "raven-lcd.h"
00074
00075 #include <string.h>
00076 #include <stdio.h>
00077 #include <avr/pgmspace.h>
00078 #include <avr/eeprom.h>
00079 #include <avr/sleep.h>
00080 #include <dev/watchdog.h>
00081
00082 static u8_t count = 0;
00083 static u8_t seqno;
00084 uip_ipaddr_t dest_addr;
00085
00086 #define MAX_CMD_LEN 20
00087 static struct{
00088 u8_t frame[MAX_CMD_LEN];
00089 u8_t ndx;
00090 u8_t len;
00091 u8_t cmd;
00092 u8_t done;
00093 } cmd;
00094
00095 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
00096 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
00097 #define PING6_DATALEN 16
00098
00099 void rs232_send(uint8_t port, unsigned char c);
00100
00101
00102
00103
00104 void
00105 raven_ping6(void)
00106 {
00107 #define PING_GOOGLE 0
00108
00109 UIP_IP_BUF->vtc = 0x60;
00110 UIP_IP_BUF->tcflow = 1;
00111 UIP_IP_BUF->flow = 0;
00112 UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
00113 UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
00114 #if PING_GOOGLE
00115 if (seqno==1) {
00116 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose());
00117 } else if (seqno==2) {
00118 uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x4860,0x800f,0x0000,0x0000,0x0000,0x0000,0x0093);
00119 } else if (seqno==3) {
00120 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose());
00121 } else {
00122
00123 uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x0000,0x0010,0x0250,0x8bff,0xfee8,0xf800);
00124 }
00125 #else
00126 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose());
00127 #endif
00128
00129 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
00130 UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST;
00131 UIP_ICMP_BUF->icode = 0;
00132
00133 memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4);
00134
00135 memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN,
00136 count, PING6_DATALEN);
00137
00138
00139 uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN;
00140 UIP_IP_BUF->len[0] = (u8_t)((uip_len - 40) >> 8);
00141 UIP_IP_BUF->len[1] = (u8_t)((uip_len - 40) & 0x00FF);
00142
00143 UIP_ICMP_BUF->icmpchksum = 0;
00144 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
00145
00146
00147 tcpip_ipv6_output();
00148 }
00149
00150
00151
00152 static void
00153 send_frame(uint8_t cmd, uint8_t len, uint8_t *payload)
00154 {
00155 uint8_t i;
00156
00157 rs232_send(0, SOF_CHAR);
00158 rs232_send(0, len);
00159 rs232_send(0, cmd);
00160 for (i=0;i<len;i++)
00161 rs232_send(0,*payload++);
00162 rs232_send(0, EOF_CHAR);
00163 }
00164 char serial_char_received;
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void micro_sleep(uint8_t howlong)
00178 {
00179 uint8_t saved_sreg = SREG, saved_howlong = howlong;
00180 #if AVR_CONF_USE32KCRYSTAL
00181
00182 uint8_t savedTCNT2=TCNT2, savedTCCR2A=TCCR2A, savedTCCR2B = TCCR2B, savedOCR2A = OCR2A;
00183 #endif
00184
00185
00186
00187
00188 set_sleep_mode(SLEEP_MODE_PWR_SAVE);
00189 if (howlong==0) howlong=3;
00190 cli();
00191 ASSR |= (1 << AS2);
00192 TCCR2A =(1<<WGM21);
00193 TCCR2B =((1<<CS22)|(1<<CS21)|(1<<CS20));
00194
00195 OCR2A = howlong*32;
00196
00197 SREG = saved_sreg;
00198
00199
00200
00201
00202
00203
00204
00205
00206 TCNT2 = 0;
00207 watchdog_stop();
00208 while(ASSR & (1 << TCN2UB));
00209 TIMSK2 |= (1 << OCIE2A);
00210 SMCR |= (1 << SE);
00211 while (1) {
00212
00213
00214 serial_char_received=0;
00215 sleep_mode();
00216
00217
00218 extern void clock_adjust_seconds(uint8_t howmany);
00219 clock_adjust_seconds(howlong);
00220
00221
00222 PRINTF(".");
00223 if (saved_howlong) break;
00224
00225 if (serial_char_received) break;
00226 }
00227
00228 SMCR &= ~(1 << SE);
00229
00230 #if AVR_CONF_USE32KCRYSTAL
00231
00232
00233 cli();
00234 TCCR2A = savedTCCR2A;
00235 TCCR2B = savedTCCR2B;
00236 OCR2A = savedOCR2A;
00237 TCNT2 = savedTCNT2;
00238 sei();
00239 #else
00240 TIMSK2 &= ~(1 << OCIE2A);
00241 #endif
00242
00243 watchdog_start();
00244 }
00245 #if !AVR_CONF_USE32KCRYSTAL
00246
00247
00248
00249 ISR(TIMER2_COMPA_vect)
00250 {
00251
00252 }
00253 #endif
00254
00255 #if DEBUGSERIAL
00256 u8_t serialcount;
00257 char dbuf[30];
00258 #endif
00259
00260
00261 static u8_t
00262 raven_gui_loop(process_event_t ev, process_data_t data)
00263 {
00264 uint8_t i,activeconnections,radio_state;
00265
00266
00267 #if DEBUGSERIAL
00268 printf_P(PSTR("Buffer [%d]="),serialcount);
00269 serialcount=0;
00270 for (i=0;i<30;i++) {
00271 printf_P(PSTR(" %d"),dbuf[i]);
00272 dbuf[i]=0;
00273 }
00274 #endif
00275 if(ev == tcpip_icmp6_event) switch(*((uint8_t *)data)) {
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 case ICMP6_ECHO_REQUEST:
00286
00287 send_frame(REPORT_PING_BEEP, 0, 0);
00288 break;
00289 case ICMP6_ECHO_REPLY:
00290
00291 send_frame(REPORT_PING, 1, &seqno);
00292 break;
00293
00294 } else switch (ev) {
00295 case SERIAL_CMD:
00296
00297
00298 PRINTF("\nCommand %d length %d done %d",cmd.cmd,cmd.len,cmd.done);
00299 if (cmd.done){
00300
00301 switch (cmd.cmd){
00302 case SEND_PING:
00303
00304 seqno = cmd.frame[0];
00305 raven_ping6();
00306 break;
00307 case SEND_TEMP:
00308 #if WEBSERVER
00309
00310 web_set_temp((char *)cmd.frame);
00311 #endif
00312 break;
00313 case SEND_ADC2:
00314 #if WEBSERVER
00315
00316 web_set_voltage((char *)cmd.frame);
00317 #endif
00318 break;
00319 case SEND_SLEEP:
00320
00321 if (cmd.frame[0]==0) {
00322
00323 } else {
00324
00325
00326 #if UIP_CONF_TCP
00327
00328 activeconnections=0;
00329 for(i = 0; i < UIP_CONNS; ++i) {
00330 if((uip_conns[i].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) activeconnections++;
00331 }
00332 if (activeconnections) {
00333 PRINTF("\nWaiting for %d connections",activeconnections);
00334 break;
00335 }
00336 #endif
00337 }
00338 radio_state = NETSTACK_RADIO.off();
00339 PRINTF ("\nsleep %d radio state %d...",cmd.frame[0],radio_state);
00340
00341
00342 PRINTF("\nSleeping...");
00343 micro_sleep(cmd.frame[0]);
00344
00345 radio_state = NETSTACK_RADIO.on();
00346 if (radio_state > 0) {
00347 PRINTF("Awake!");
00348 } else {
00349 PRINTF("Radio wake error %d\n",radio_state);
00350 }
00351 break;
00352 case SEND_WAKE:
00353
00354 send_frame(REPORT_WAKE, 0, 0);
00355 break;
00356 default:
00357 break;
00358 }
00359
00360 cmd.done = 0;
00361 }
00362 break;
00363 default:
00364 break;
00365 }
00366 return 0;
00367 }
00368
00369
00370
00371
00372
00373
00374 int raven_lcd_serial_input(unsigned char ch)
00375 {
00376
00377
00378 if (ch) serial_char_received++;
00379 #if DEBUGSERIAL
00380 if (serialcount<25) dbuf[serialcount]=ch;
00381 serialcount++;
00382 #endif
00383
00384
00385
00386
00387 switch (cmd.ndx){
00388 case 0:
00389
00390 if (ch == 0x01){
00391
00392 } else {
00393 #if DEBUGSERIAL
00394 dbuf[25]++;
00395 #endif
00396 return 0;
00397 }
00398 break;
00399 case 1:
00400
00401 cmd.len = ch;
00402 break;
00403 case 2:
00404
00405 cmd.cmd = ch;
00406 break;
00407 default:
00408
00409 if (cmd.ndx >= (MAX_CMD_LEN+3)) {
00410 cmd.ndx=0;
00411 #if DEBUGSERIAL
00412 dbuf[26]++;
00413 #endif
00414 return 0;
00415 }
00416 if (cmd.ndx >= cmd.len+3){
00417
00418 if (ch == 0x04){
00419 cmd.done = 1;
00420 #if DEBUGSERIAL
00421 dbuf[27]++;
00422 #endif
00423 process_post(&raven_lcd_process, SERIAL_CMD, 0);
00424 } else {
00425
00426 #if DEBUGSERIAL
00427 dbuf[28]++;
00428 #endif
00429 }
00430 cmd.ndx=0;
00431 return 0;
00432 } else {
00433
00434 cmd.frame[cmd.ndx - 3] = ch;
00435 }
00436 break;
00437 }
00438
00439 cmd.ndx++;
00440 return 0;
00441 }
00442
00443
00444 void
00445 raven_lcd_show_text(char *text) {
00446 uint8_t textlen=strlen(text)+1;
00447 if (textlen > MAX_CMD_LEN) textlen=MAX_CMD_LEN;
00448 send_frame(REPORT_TEXT_MSG, textlen, (uint8_t *) text);
00449 }
00450
00451 #if WEBSERVER
00452 static void
00453 lcd_show_servername(void) {
00454
00455
00456 extern uint8_t server_name[16];
00457
00458 char buf[sizeof(server_name)+1];
00459 eeprom_read_block (buf,server_name, sizeof(server_name));
00460 buf[sizeof(server_name)]=0;
00461 raven_lcd_show_text(buf);
00462 }
00463 #endif
00464
00465 PROCESS(raven_lcd_process, "Raven LCD interface process");
00466 PROCESS_THREAD(raven_lcd_process, ev, data)
00467 {
00468
00469 PROCESS_BEGIN();
00470
00471 #if WEBSERVER
00472 lcd_show_servername();
00473 #endif
00474
00475
00476 if(icmp6_new(NULL) == 0) {
00477
00478 while(1) {
00479 PROCESS_YIELD();
00480
00481 raven_gui_loop(ev, data);
00482 }
00483 }
00484 PROCESS_END();
00485 }
00486
00487
00488