/* Copyright (c) 2008, Swedish Institute of Computer Science * All rights reserved. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id: raven-lcd.c,v 1.11 2010/12/22 17:09:03 dak664 Exp $ */ /** * \brief This module contains code to interface a Contiki-based * project on the AVR Raven platform's ATMega1284P chip to the LCD * driver chip (ATMega3290P) on the Raven. * * \author Blake Leverett * */ /** \addtogroup raven * @{ */ /** * \defgroup ravenserial Serial interface between Raven processors * @{ */ /** * \file * This file contains code to connect the two AVR Raven processors via a serial connection. * */ #define DEBUG 0 //Making this 1 will slightly alter command timings #if DEBUG #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) #else #define PRINTF(...) #endif #define DEBUGSERIAL 0 //Making this 1 will significantly alter command timings #include "contiki.h" #include "contiki-lib.h" #include "contiki-net.h" #if WEBSERVER #include "webserver-nogui.h" #include "httpd-cgi.h" #endif #include "raven-lcd.h" #include #include #include #include #include #include static u8_t count = 0; static u8_t seqno; uip_ipaddr_t dest_addr; #define MAX_CMD_LEN 20 static struct{ u8_t frame[MAX_CMD_LEN]; u8_t ndx; u8_t len; u8_t cmd; u8_t done; } cmd; #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define PING6_DATALEN 16 void rs232_send(uint8_t port, unsigned char c); /*---------------------------------------------------------------------------*/ /* Sends a ping packet out the radio */ /* Useful for debugging so allow external calls */ void raven_ping6(void) { #define PING_GOOGLE 0 UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; #if PING_GOOGLE if (seqno==1) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router } else if (seqno==2) { uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x4860,0x800f,0x0000,0x0000,0x0000,0x0000,0x0093); //ipv6.google.com } else if (seqno==3) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router } else { // uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x5FFF,0x007D,0x02D0,0xB7FF,0xFE23,0xE6DB); //?.cisco.com uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x0000,0x0010,0x0250,0x8bff,0xfee8,0xf800); //six.cisco.com } #else uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router #endif uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING6_DATALEN); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; UIP_IP_BUF->len[0] = (u8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (u8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); tcpip_ipv6_output(); } /*---------------------------------------------------------------------------*/ /* Send a serial command frame to the ATMega3290 Processsor on Raven via serial port */ static void send_frame(uint8_t cmd, uint8_t len, uint8_t *payload) { uint8_t i; rs232_send(0, SOF_CHAR); /* Start of Frame */ rs232_send(0, len); rs232_send(0, cmd); for (i=0;i 0) { PRINTF("Awake!"); } else { PRINTF("Radio wake error %d\n",radio_state); } break; case SEND_WAKE: /* 3290p requests return message showing awake status */ send_frame(REPORT_WAKE, 0, 0); break; default: break; } /* Reset command done flag. */ cmd.done = 0; } break; default: break; } return 0; } /*---------------------------------------------------------------------------*/ /* Process an input character from serial port. * ** This is called from an ISR!! */ int raven_lcd_serial_input(unsigned char ch) { /* Tell sleep routine if a reception occurred */ /* Random nulls occur for some reason, so ignore those */ if (ch) serial_char_received++; #if DEBUGSERIAL if (serialcount<25) dbuf[serialcount]=ch; serialcount++; #endif /* Don't overwrite an unprocessed command */ // if (cmd.done) return 0; /* Parse frame, */ switch (cmd.ndx){ case 0: /* first byte, must be 0x01 */ if (ch == 0x01){ // cmd.done = false; } else { #if DEBUGSERIAL dbuf[25]++; #endif return 0; } break; case 1: /* Second byte, length of payload */ cmd.len = ch; break; case 2: /* Third byte, command byte */ cmd.cmd = ch; break; default: /* Payload and ETX */ if (cmd.ndx >= (MAX_CMD_LEN+3)) { //buffer overflow! cmd.ndx=0; #if DEBUGSERIAL dbuf[26]++; #endif return 0; } if (cmd.ndx >= cmd.len+3){ /* all done, check ETX */ if (ch == 0x04){ cmd.done = 1; #if DEBUGSERIAL dbuf[27]++; #endif process_post(&raven_lcd_process, SERIAL_CMD, 0); } else { /* Failed ETX */ #if DEBUGSERIAL dbuf[28]++; #endif } cmd.ndx=0; //set up for next command return 0; } else { /* Just grab and store payload */ cmd.frame[cmd.ndx - 3] = ch; } break; } cmd.ndx++; return 0; } /*---------------------------------------------------------------------------*/ void raven_lcd_show_text(char *text) { uint8_t textlen=strlen(text)+1; if (textlen > MAX_CMD_LEN) textlen=MAX_CMD_LEN; send_frame(REPORT_TEXT_MSG, textlen, (uint8_t *) text); } #if WEBSERVER static void lcd_show_servername(void) { //extern uint8_t mac_address[8]; //These are defined in httpd-fsdata.c via makefsdata.h extern uint8_t server_name[16]; //extern uint8_t domain_name[30]; char buf[sizeof(server_name)+1]; eeprom_read_block (buf,server_name, sizeof(server_name)); buf[sizeof(server_name)]=0; raven_lcd_show_text(buf); //must fit in all the buffers or it will be truncated! } #endif /*---------------------------------------------------------------------------*/ PROCESS(raven_lcd_process, "Raven LCD interface process"); PROCESS_THREAD(raven_lcd_process, ev, data) { PROCESS_BEGIN(); #if WEBSERVER lcd_show_servername(); #endif /* Get ICMP6 callbacks from uip6 stack, perform 3290p action on pings, responses, etc. */ if(icmp6_new(NULL) == 0) { while(1) { PROCESS_YIELD(); // if (ev != ?) //trap frequent strobes? raven_gui_loop(ev, data); } } PROCESS_END(); } /** @} */