/*-------------------------------------------------------------------------*/ int main(void) { initialize(); while(1) { process_run(); #if DEBUG if (rf230_interrupt_flag) { if (rf230_interrupt_flag!=11) { PRINTF("*****Radio interrupt %u\n",rf230_interrupt_flag); rf230_interrupt_flag=0; } } #endif #if PINGS if (pingtimer1++==10000) { pingtimer1=0; if (pingtimer2++==1000) { PRINTF("-------Ping\n"); pingtimer2=0; raven_ping6(); } } #endif } return 0; }
/*------------------------------------------------------------------*/ static u8_t raven_gui_loop(process_event_t ev, process_data_t data) { if(ev == tcpip_icmp6_event) { switch(*((uint8_t *)data)){ case ICMP6_ECHO_REQUEST: /* We have received a ping request over the air. Send frame back to 3290 */ send_frame(PING_REQUEST, 0, 0); break; case ICMP6_ECHO_REPLY: /* We have received a ping reply over the air. Send frame back to 3290 */ send_frame(PING_REPLY, 1, &seqno); break; } } else { switch(ev){ case SERIAL_CMD: /* Check for command from serial port, execute it. */ if (cmd.done){ /* Execute the waiting command */ switch (cmd.cmd){ case CMD_PING: /* Send ping request over the air */ seqno = cmd.frame[0]; raven_ping6(); break; case CMD_TEMP: /* Set temperature string in web server */ sprintf(udp_data, "T%s\r\n", (char *)cmd.frame); uip_udp_packet_send(udp_conn, udp_data, data_len); break; default: break; } /* Reset command done flag. */ cmd.done = false; } break; default: break; } } return 0; }
/*---------------------------------------------------------------------------*/ static u8_t raven_gui_loop(process_event_t ev, process_data_t data) { switch (ev){ case ICMP6_ECHO_REQUEST: /* We have received a ping request over the air. Send frame back to 3290 */ send_frame(PING_REQUEST, 0, 0); break; case ICMP6_ECHO_REPLY: /* We have received a ping reply over the air. Send frame back to 3290 */ send_frame(PING_REPLY, 1, &seqno); break; case SERIAL_CMD: /* Check for command from serial port, execute it. */ if (cmd.done){ /* Execute the waiting command */ switch (cmd.cmd){ case CMD_PING: /* Send ping request over the air */ seqno = cmd.frame[0]; raven_ping6(); break; case CMD_TEMP: /* Set temperature string in web server */ web_set_temp((char *)cmd.frame); break; default: break; } /* Reset command done flag. */ cmd.done = 0; } break; default: break; } return 0; }
/*------------------------------------------------------------------*/ static u8_t raven_gui_loop(process_event_t ev, process_data_t data) { uint8_t *ptr; int len = 0; if(ev == tcpip_event) { PRINTF("[APP] TCPIP event lport %u rport %u raddress\n",uip_udp_conn->lport, uip_udp_conn->rport); if(uip_udp_conn == node_conn) { PRINTF("[APP] UDP packet\n"); if(uip_newdata()) { ptr = (uint8_t *)uip_appdata; /* Make sure the data is terminated */ ptr[uip_datalen()] = 0; /* Command to this node */ switch(*ptr) { case 'T': send_frame(TEMP_REQUEST, 0, 0); len = snprintf(udp_data, DATA_LEN, "%c%s\r\n", *ptr, last_temp); if(len > 0) { reply_packet(udp_data, len); } break; case 'A': if(ptr[1] > 32) { invert_led = ptr[1] == '1'; send_frame(LED_REQUEST, 1, &invert_led); } len = sprintf(udp_data, "A%u\r\n", invert_led ? 1 : 0); if(len > 0) { reply_packet(udp_data, len); } break; case 'P': PRINTF("[APP] Request for periodic sending of temperatures\n"); if(sscanf((char *)ptr+1,"%d", &periodic_interval)) { PRINTF("[APP] Period %d\n", periodic_interval); if(periodic_interval == 0) { etimer_stop(&periodic_timer); } else { etimer_set(&periodic_timer, periodic_interval * CLOCK_SECOND); } len = snprintf(udp_data, DATA_LEN, "P%d\r\n", periodic_interval); if(len > 0) { reply_packet(udp_data, len); } } break; case 'C': PRINTF("[APP] Command %c\n",ptr[1]); if(sscanf((char *)ptr+2, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %d", &addr[0],&addr[1],&addr[2],&addr[3],&addr[4], &addr[5],&addr[6],&addr[7],&len) >= 8) { uip_ip6addr(&locaddr, addr[0], addr[1],addr[2], addr[3],addr[4],addr[5],addr[6],addr[7]); if(ptr[1] == 'E') { PRINTF("[APP] Send ping to"); PRINT6ADDR(&locaddr); PRINTF("len %d\n", len); raven_ping6(&locaddr, len); } else if (ptr[1] == 'T') { PRINTF("[APP] Send temperature to"); PRINT6ADDR(&locaddr); PRINTF("\n"); len = snprintf(udp_data, DATA_LEN, "%c\r\n", ptr[1]); if(len > 0) { send_packet(&locaddr, HTONS(0xF0B0), udp_data, len); } } else { PRINTF("[APP] Command unknown\n"); } } break; default: break; } } } } else { switch (ev) { case ICMP6_ECHO_REQUEST: /* We have received a ping request over the air. Send frame back to 3290 */ send_frame(PING_REQUEST, 0, 0); break; case ICMP6_ECHO_REPLY: /* We have received a ping reply over the air. Send frame back to 3290 */ send_frame(PING_REPLY, 1, &seqno); break; case PROCESS_EVENT_TIMER: if(data == &periodic_timer) { PRINTF("[APP] Periodic Timer\n"); /* Send to server if time to send */ len = sprintf(udp_data, "T%s\r\n", last_temp); if(len > 0) { send_packet(&server_addr, SERVER_PORT, udp_data, len); } etimer_reset(&periodic_timer); send_frame(TEMP_REQUEST, 0, 0); } break; case PROCESS_EVENT_POLL: /* Check for command from serial port, execute it. */ if (cmd.done) { /* Execute the waiting command */ switch (cmd.cmd) { case CMD_PING: /* Send ping request over the air */ seqno = cmd.frame[0]; raven_ping6(&server_addr, 0); break; case CMD_TEMP: /* Copy sensor data until white space or end of string. The ATMega3290 sends temperature with both value and type (25 C) */ copy_value(cmd.frame, last_temp, sizeof(last_temp)); PRINTF("[APP] New temp value %s\n", last_temp); break; default: break; } /* Reset command done flag. */ cmd.done = 0; } break; default: break; } } return 0; }
/*---------------------------------Main Routine----------------------------*/ int main(void) { /* GCC depends on register r1 set to 0 (?) */ asm volatile ("clr r1"); /* Initialize in a subroutine to maximize stack space */ initialize(); #if DEBUG {struct process *p; for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) { PRINTA("Process=%p Thread=%p Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p)); } } #endif while(1) { process_run(); watchdog_periodic(); /* Print rssi of all received packets, useful for range testing */ #ifdef RF230_MIN_RX_POWER uint8_t lastprint; if (rf230_last_rssi != lastprint) { //can be set in halbb.c interrupt routine PRINTA("%u ",rf230_last_rssi); lastprint=rf230_last_rssi; } #endif #if 0 /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. * This can show when that happens. */ extern uint8_t rf230_calibrated; if (rf230_calibrated) { PRINTA("\nRF230 calibrated!\n"); rf230_calibrated=0; } #endif #if TESTRTIMER /* Timeout can be increased up to 8 seconds maximum. * A one second cycle is convenient for triggering the various debug printouts. * The triggers are staggered to avoid printing everything at once. * My Jackdaw is 4% slow. */ if (rtimerflag) { rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimerflag=0; #if STAMPS if ((rtime%STAMPS)==0) { PRINTA("%us ",rtime); if (rtime%STAMPS*10) PRINTA("\n"); } #endif rtime+=1; #if PINGS && UIP_CONF_IPV6_RPL extern void raven_ping6(void); if ((rtime%PINGS)==1) { PRINTA("**Ping\n"); raven_ping6(); } #endif #if ROUTES && UIP_CONF_IPV6_RPL if ((rtime%ROUTES)==2) { extern uip_ds6_netif_t uip_ds6_if; uint8_t i,j; uip_ds6_nbr_t *nbr; PRINTA("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); for (i=0;i<UIP_DS6_ADDR_NB;i++) { if (uip_ds6_if.addr_list[i].isused) { uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); PRINTA("\n"); } } PRINTA("\nNeighbors [%u max]\n",NBR_TABLE_MAX_NEIGHBORS); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { uip_debug_ipaddr_print(&nbr->ipaddr); PRINTA("\n"); j=0; } if (j) PRINTA(" <none>"); PRINTA("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); uip_ds6_route_t *r; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(r->isused) { uip_debug_ipaddr_print(&r->ipaddr); PRINTA("/%u (via ", r->length); uip_debug_ipaddr_print(uip_ds6_route_nexthop(r)); // if(r->state.lifetime < 600) { PRINTA(") %lus\n", r->state.lifetime); // } else { // PRINTA(")\n"); // } j=0; } } if (j) PRINTA(" <none>"); PRINTA("\n---------\n"); } #endif #if STACKMONITOR && CONFIG_STACK_MONITOR if ((rtime%STACKMONITOR)==3) { extern uint16_t __bss_end; uint16_t p=(uint16_t)&__bss_end; do { if (*(uint16_t *)p != 0x4242) { PRINTA("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); break; } p+=100; } while (p<RAMEND-10); } #endif } #endif /* TESTRTIMER */ //Use with RF230BB DEBUGFLOW to show path through driver #if RF230BB&&0 extern uint8_t debugflowsize,debugflow[]; //in rf230bb.c if (debugflowsize) { debugflow[debugflowsize]=0; PRINTA("%s",debugflow); debugflowsize=0; } #endif } return 0; }
/*---------------------------------------------------------------------------*/ static uint8_t raven_gui_loop(process_event_t ev, process_data_t data) { uint8_t i,activeconnections,radio_state; // PRINTF("\nevent %d ",ev); #if DEBUGSERIAL printf_P(PSTR("Buffer [%d]="),serialcount); serialcount=0; for (i=0;i<30;i++) { printf_P(PSTR(" %d"),dbuf[i]); dbuf[i]=0; } #endif if(ev == tcpip_icmp6_event) switch(*((uint8_t *)data)) { // case ICMP6_NS: /*Tell the 3290 we are being solicited. */ // send_frame(REPORT_NS,...); // break; //fall through for beep // case ICMP6_RA: /*Tell the 3290 we have a router. */ // send_frame(REPORT_NA,...); // break; //fall through for beep case ICMP6_ECHO_REQUEST: /* We have received a ping request over the air. Tell the 3290 */ send_frame(REPORT_PING_BEEP, 0, 0); break; case ICMP6_ECHO_REPLY: /* We have received a ping reply over the air. Send frame back to 3290 */ send_frame(REPORT_PING, 1, &seqno); break; } else switch (ev) { case SERIAL_CMD: /* Check for command from serial port, execute it. */ /* Note cmd frame is written in an interrupt - delays here can cause overwriting by next command */ PRINTF("\nCommand %d length %d done %d",cmd.cmd,cmd.len,cmd.done); if (cmd.done){ /* Execute the waiting command */ switch (cmd.cmd){ case SEND_PING: /* Send ping request over the air */ seqno = cmd.frame[0]; raven_ping6(); break; case SEND_TEMP: #if AVR_WEBSERVER /* Set temperature string in web server */ web_set_temp((char *)cmd.frame); #endif break; case SEND_ADC2: #if AVR_WEBSERVER /* Set ext voltage string in web server */ web_set_voltage((char *)cmd.frame); #endif break; case SEND_SLEEP: /* Sleep radio and 1284p. */ if (cmd.frame[0]==0) { //Time to sleep in seconds /* Unconditional sleep. Don't wake until a serial interrupt. */ } else { /* Sleep specified number of seconds (3290p "DOZE" mode) */ /* It sleeps a bit longer so we will be always be awake for the next sleep command. */ #if UIP_CONF_TCP /* Only sleep this cycle if no active TCP/IP connections, for fast browser responsed */ activeconnections=0; for(i = 0; i < UIP_CONNS; ++i) { if((uip_conns[i].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) activeconnections++; } if (activeconnections) { PRINTF("\nWaiting for %d connections",activeconnections); break; } #endif } radio_state = NETSTACK_RADIO.off(); PRINTF ("\nsleep %d radio state %d...",cmd.frame[0],radio_state); /*Sleep for specified time*/ PRINTF("\nSleeping..."); micro_sleep(cmd.frame[0]); radio_state = NETSTACK_RADIO.on(); if (radio_state > 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; }
/*-------------------------------------------------------------------------*/ int main(void) { initialize(); #ifdef LOWPOWER rf2xx_set_txpower(0xf); #endif while(1) { process_run(); watchdog_periodic(); #if 0 /* Various entry points for debugging in the AVR Studio simulator. * Set as next statement and step into the routine. */ NETSTACK_RADIO.send(packetbuf_hdrptr(), 42); process_poll(&rf230_process); packetbuf_clear(); len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE); packetbuf_set_datalen(42); NETSTACK_RDC.input(); #endif #if 0 /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. * This can show when that happens. */ extern uint8_t rf230_calibrated; if (rf230_calibrated) { PRINTD("\nRF230 calibrated!\n"); rf230_calibrated=0; } #endif /* Set DEBUGFLOWSIZE in contiki-conf.h to track path through MAC, RDC, and RADIO */ #if DEBUGFLOWSIZE if (debugflowsize) { debugflow[debugflowsize]=0; PRINTF("%s",debugflow); debugflowsize=0; } #endif #if PERIODICPRINTS #if TESTRTIMER /* Timeout can be increased up to 8 seconds maximum. * A one second cycle is convenient for triggering the various debug printouts. * The triggers are staggered to avoid printing everything at once. * My raven is 6% slow. */ if (rtimerflag) { rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimerflag=0; #else if (clocktime!=clock_seconds()) { clocktime=clock_seconds(); #endif #if STAMPS if ((clocktime%STAMPS)==0) { #if ENERGEST_CONF_ON #include "lib/print-stats.h" print_stats(); #elif RADIOSTATS extern volatile unsigned long radioontime; PRINTF("%u(%u)s\n",clocktime,radioontime); #else PRINTF("%us\n",clocktime); #endif } #endif #if TESTRTIMER clocktime+=1; #endif #if PINGS && UIP_CONF_IPV6 extern void raven_ping6(void); if ((clocktime%PINGS)==1) { PRINTF("**Ping\n"); raven_ping6(); } #endif #if ROUTES && UIP_CONF_IPV6 if ((clocktime%ROUTES)==2) { extern uip_ds6_nbr_t uip_ds6_nbr_cache[]; extern uip_ds6_route_t uip_ds6_routing_table[]; extern uip_ds6_netif_t uip_ds6_if; uint8_t i,j; PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); for (i=0;i<UIP_DS6_ADDR_NB;i++) { if (uip_ds6_if.addr_list[i].isused) { ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr); PRINTF("\n"); } } PRINTF("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB); for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) { if(uip_ds6_nbr_cache[i].isused) { ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr); PRINTF("\n"); j=0; } } if (j) PRINTF(" <none>"); PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) { if(uip_ds6_routing_table[i].isused) { ipaddr_add(&uip_ds6_routing_table[i].ipaddr); PRINTF("/%u (via ", uip_ds6_routing_table[i].length); ipaddr_add(&uip_ds6_routing_table[i].nexthop); // if(uip_ds6_routing_table[i].state.lifetime < 600) { PRINTF(") %lus\n", uip_ds6_routing_table[i].state.lifetime); // } else { // PRINTF(")\n"); // } j=0; } } if (j) PRINTF(" <none>"); PRINTF("\n---------\n"); } #endif #if STACKMONITOR if ((clocktime%STACKMONITOR)==3) { extern uint16_t __bss_end; uint16_t p=(uint16_t)&__bss_end; do { if (*(uint16_t *)p != 0x4242) { PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); break; } p+=10; } while (p<RAMEND-10); } #endif } #endif /* PERIODICPRINTS */ //Use with RF230BB DEBUGFLOW to show path through driver #if RF230BB&&0 extern uint8_t rf230processflag; if (rf230processflag) { PRINTF("rf230p%d",rf230processflag); rf230processflag=0; } #endif #if RF230BB&&0 extern uint8_t rf230_interrupt_flag; if (rf230_interrupt_flag) { // if (rf230_interrupt_flag!=11) { PRINTF("**RI%u",rf230_interrupt_flag); // } rf230_interrupt_flag=0; } #endif } return 0; } /*---------------------------------------------------------------------------*/ void log_message(char *m1, char *m2) { PRINTF("%s%s\n", m1, m2); }