X-Git-Url: http://git.droids-corp.org/?p=protos%2Fxbee-avr.git;a=blobdiff_plain;f=main.c;h=0d5cad65d3558c8456c7eab9d8bb35128a094730;hp=b6014db2a1ddfb8f1c31e77b4daca5094fc7fdf7;hb=f74db5fd03bcd38af3ca533e7531dd70454dfaaf;hpb=d6014994e06ebe952d51bef2e36a795f624c4b4d diff --git a/main.c b/main.c index b6014db..0d5cad6 100644 --- a/main.c +++ b/main.c @@ -25,6 +25,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* fuses: + * avrdude -p atmega1284p -P usb -c avrispmkii -U lfuse:w:0xff:m -U hfuse:w:0x91:m -U efuse:w:0xff:m + */ + #include #include #include @@ -48,18 +52,13 @@ #include #include -#include "xbee_neighbor.h" -#include "xbee_atcmd.h" -#include "xbee_stats.h" -#include "xbee_buf.h" -#include "xbee_proto.h" -#include "xbee.h" -#include "cmdline.h" -#include "callout.h" -#include "rc_proto.h" +#include "eeprom_config.h" +#include "beep.h" #include "main.h" struct xbeeboard xbeeboard; +volatile uint16_t global_ms; +struct callout_manager cm; #define TIMEOUT_MS 1000 @@ -85,51 +84,56 @@ static void hexdump(const char *title, const void *buf, unsigned int len) #define LINE_LEN 80 char line[LINE_LEN]; /* space needed 8+16*3+3+16 == 75 */ - printf("%s at [%p], len=%d\n", title, data, len); + printf_P(PSTR("%s at [%p], len=%d\r\n"), title, data, len); ofs = 0; while (ofs < len) { /* format 1 line in the buffer, then use printk to print them */ - out = snprintf(line, LINE_LEN, "%08X", ofs); + out = snprintf_P(line, LINE_LEN, PSTR("%08X"), ofs); for (i=0; ofs+i < len && i<16; i++) - out += snprintf(line+out, LINE_LEN - out, " %02X", - data[ofs+i]&0xff); + out += snprintf_P(line+out, LINE_LEN - out, + PSTR(" %02X"), + data[ofs+i]&0xff); for (;i<=16;i++) out += snprintf(line+out, LINE_LEN - out, " "); for (i=0; ofs < len && i<16; i++, ofs++) { unsigned char c = data[ofs]; if (!isascii(c) || !isprint(c)) c = '.'; - out += snprintf(line+out, LINE_LEN - out, "%c", c); + out += snprintf_P(line+out, + LINE_LEN - out, + PSTR("%c"), c); } - printf("%s\n", line); + printf_P(PSTR("%s\r\n"), line); } } static int parse_xmit_status(struct xbee_ctx *ctx, struct xbee_xmit_status_hdr *frame, unsigned len) { + (void)len; + if (ctx == NULL) { - printf("no context\n"); + printf_P(PSTR("no context\r\n")); return -1; } /* see if it matches a xmit query (atcmd_query must be NULL) */ - if (ctx->atcmd_query[0] == '\0') { - printf("invalid response 2\n"); + if (ctx->atcmd_query[0] != '\0') { + printf_P(PSTR("invalid response 2\r\n")); return -1; } /* XXX use defines for these values */ if (frame->delivery_status == 0x00) - printf("Success\n"); + printf_P(PSTR("Success\r\n")); else if (frame->delivery_status == 0x01) - printf("MAC ACK Failure\n"); + printf_P(PSTR("MAC ACK Failure\r\n")); else if (frame->delivery_status == 0x15) - printf("Invalid destination endpoint\n"); + printf_P(PSTR("Invalid destination endpoint\r\n")); else if (frame->delivery_status == 0x21) - printf("Network ACK Failure\n"); + printf_P(PSTR("Network ACK Failure\r\n")); else if (frame->delivery_status == 0x25) - printf("Route Not Found\n"); + printf_P(PSTR("Route Not Found\r\n")); return 0; } @@ -138,7 +142,7 @@ static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, unsigned len) { char atcmd_str[3]; - struct xbee_atcmd_pgm *cmd_pgm; + const struct xbee_atcmd *cmd_pgm; struct xbee_atcmd cmd; union { uint8_t u8; @@ -148,7 +152,7 @@ static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, } __attribute__((packed)) *result; if (ctx == NULL) { - printf("no context\n"); + printf_P(PSTR("no context\r\n")); return -1; } @@ -158,36 +162,36 @@ static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, /* see if it matches query */ if (memcmp(atcmd_str, ctx->atcmd_query, 2)) { - printf("invalid response <%c%c><%s><%s>\n", - frame->cmd & 0xFF, - (frame->cmd >> 8) & 0xFF, - atcmd_str, ctx->atcmd_query); + printf_P(PSTR("invalid response <%c%c><%s><%s>\r\n"), + frame->cmd & 0xFF, + (frame->cmd >> 8) & 0xFF, + atcmd_str, ctx->atcmd_query); return -1; } /* see if it exists */ cmd_pgm = xbee_atcmd_lookup_name(atcmd_str); if (cmd_pgm == NULL) { - printf("unknown response\n"); + printf_P(PSTR("unknown response\r\n")); return -1; } memcpy_P(&cmd, cmd_pgm, sizeof(cmd)); /* bad status */ if (frame->status == 1) { - printf("Status is error\n"); + printf_P(PSTR("Status is error\r\n")); return -1; } else if (frame->status == 2) { - printf("Invalid command\n"); + printf_P(PSTR("Invalid command\r\n")); return -1; } else if (frame->status == 3) { - printf("Invalid parameter\n"); + printf_P(PSTR("Invalid parameter\r\n")); return -1; } else if (frame->status != 0) { - printf("Unknown status error %d\n", frame->status); + printf_P(PSTR("Unknown status error %d\r\n"), frame->status); return -1; } @@ -199,15 +203,19 @@ static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, result = (void *)frame->data; len -= offsetof(struct xbee_atresp_hdr, data); if (cmd.flags & XBEE_ATCMD_F_PARAM_U8 && len == sizeof(uint8_t)) - printf("<%s> is 0x%x\n", atcmd_str, result->u8); + printf_P(PSTR("<%s> is 0x%x\r\n"), atcmd_str, result->u8); else if (cmd.flags & XBEE_ATCMD_F_PARAM_U16 && len == sizeof(uint16_t)) - printf("<%s> is 0x%x\n", atcmd_str, ntohs(result->u16)); + printf_P(PSTR("<%s> is 0x%x\r\n"), + atcmd_str, + ntohs(result->u16)); else if (cmd.flags & XBEE_ATCMD_F_PARAM_U32 && len == sizeof(uint32_t)) - printf("<%s> is 0x%"PRIx32"\n", atcmd_str, ntohl(result->u32)); + printf_P(PSTR("<%s> is 0x%"PRIx32"\r\n"), + atcmd_str, + ntohl(result->u32)); else if (cmd.flags & XBEE_ATCMD_F_PARAM_S16 && len == sizeof(int16_t)) - printf("<%s> is %d\n", atcmd_str, ntohs(result->s16)); + printf_P(PSTR("<%s> is %d\r\n"), atcmd_str, ntohs(result->s16)); else if (len == 0) - printf("no data, status ok\n"); + printf_P(PSTR("no data, status ok\r\n")); else hexdump("atcmd answer", frame->data, len); @@ -218,20 +226,32 @@ static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, int xbee_recv_data(struct xbee_recv_hdr *recvframe, unsigned len) { - int datalen = len - sizeof(*recvframe); - struct rc_proto_hdr *rch = (struct rc_proto_hdr *) recvframe; + unsigned int datalen; + struct rc_proto_hdr *rch = (struct rc_proto_hdr *) &recvframe->data; + if (len < sizeof(*recvframe)) + return -1; + + datalen = len - sizeof(*recvframe); if (datalen < sizeof(struct rc_proto_hdr)) return -1; switch (rch->type) { - case RC_PROTO_TYPE_CHANNEL: + case RC_PROTO_TYPE_CHANNEL: { + struct rc_proto_channel *rcc = + (struct rc_proto_channel *) recvframe->data; + int16_t val; if (datalen != sizeof(struct rc_proto_channel)) return -1; + val = ntohs(rcc->axis[0]); + val >>= 6; + val += 512; + spi_servo_set(0, val); break; + } case RC_PROTO_TYPE_RANGE: { struct rc_proto_range *rcr = - (struct rc_proto_range *) recvframe; + (struct rc_proto_range *) recvframe->data; if (datalen != sizeof(struct rc_proto_range)) return -1; @@ -258,21 +278,22 @@ void xbee_rx(struct xbee_dev *dev, int channel, int type, int do_hexdump = xbee_hexdump; if (xbee_debug) - printf("type=0x%x, channel=%d, ctx=%p\n", type, channel, ctx); + printf_P(PSTR("type=0x%x, channel=%d, ctx=%p\r\n"), + type, channel, ctx); /* if ctx is !NULL, it is an answer to a query */ if (ctx != NULL) { /* XXX only delete timeout if answer matched */ xbee_unload_timeout(ctx); if (xbee_debug && ctx->atcmd_query) - printf("Received answer to query <%c%c>\n", - ctx->atcmd_query[0], ctx->atcmd_query[1]); + printf_P(PSTR("Received answer to query <%c%c>\r\n"), + ctx->atcmd_query[0], ctx->atcmd_query[1]); } /* some additional checks before sending */ switch (type) { case XBEE_TYPE_MODEM_STATUS: { - printf("Received Modem Status frame\n"); + printf_P(PSTR("Received Modem Status frame\r\n")); break; } @@ -291,8 +312,8 @@ void xbee_rx(struct xbee_dev *dev, int channel, int type, } addr; memcpy(&addr, frame, sizeof(addr)); addr.u64 = ntohll(addr.u64); - printf("from remote address %"PRIx32"%"PRIx32"\n", - addr.u32.high, addr.u32.low); + printf_P(PSTR("from remote address %"PRIx32"%"PRIx32"\r\n"), + addr.u32.high, addr.u32.low); /* this answer contains an atcmd answer at offset 10 */ if (dump_atcmd(ctx, frame + 10, len - 10) < 0) @@ -325,7 +346,7 @@ void xbee_rx(struct xbee_dev *dev, int channel, int type, case XBEE_TYPE_EXPL_RECV: case XBEE_TYPE_NODE_ID: default: - printf("Invalid frame\n"); + printf_P(PSTR("Invalid frame\r\n")); do_hexdump = 1; break; } @@ -350,7 +371,7 @@ static int xbeeapp_send(struct xbee_ctx *ctx, int type, void *buf, unsigned len, int channel; if (len > XBEE_MAX_FRAME_LEN) { - printf("frame too large\n"); + printf_P(PSTR("frame too large\r\n")); return -1; } @@ -358,7 +379,7 @@ static int xbeeapp_send(struct xbee_ctx *ctx, int type, void *buf, unsigned len, channel = xbee_register_channel(xbee_dev, XBEE_CHANNEL_ANY, xbee_rx, NULL); if (channel < 0) { - printf("cannot send: no free channel\n"); + printf_P(PSTR("cannot send: no free channel\r\n")); return -1; } @@ -368,8 +389,8 @@ static int xbeeapp_send(struct xbee_ctx *ctx, int type, void *buf, unsigned len, xbee_set_opaque(xbee_dev, channel, ctx); if (xbee_debug) - printf("send frame channel=%d type=0x%x len=%d\n", - channel, type, len); + printf_P(PSTR("send frame channel=%d type=0x%x len=%d\r\n"), + channel, type, len); if (xbee_hexdump) hexdump("xmit frame", buf, len); @@ -377,7 +398,7 @@ static int xbeeapp_send(struct xbee_ctx *ctx, int type, void *buf, unsigned len, ret = xbee_proto_xmit(xbee_dev, channel, type, buf, len); if (ret < 0) { - printf("cannot send\n"); + printf_P(PSTR("cannot send\r\n")); xbee_unregister_channel(xbee_dev, channel); return -1; } @@ -467,7 +488,10 @@ static void evt_timeout(struct callout_manager *cm, struct callout *clt, { struct xbee_ctx *ctx = arg; - printf("Timeout\n"); + (void)cm; + (void)clt; + + printf_P(PSTR("Timeout\r\n")); /* restart command line */ xbee_stdin_enable(); @@ -489,24 +513,29 @@ void xbee_unload_timeout(struct xbee_ctx *ctx) void bootloader(void) { -#define BOOTLOADER_ADDR 0x1e000 +#define BOOTLOADER_ADDR 0x3f000 if (pgm_read_byte_far(BOOTLOADER_ADDR) == 0xff) { printf_P(PSTR("Bootloader is not present\r\n")); return; } cli(); /* ... very specific :( */ + TIMSK0 = 0; + TIMSK1 = 0; + TIMSK2 = 0; + TIMSK3 = 0; EIMSK = 0; + UCSR0B = 0; + UCSR1B = 0; SPCR = 0; TWCR = 0; ACSR = 0; ADCSRA = 0; - __asm__ __volatile__ ("ldi r31,0xf0\n"); - __asm__ __volatile__ ("ldi r30,0x00\n"); - __asm__ __volatile__ ("ijmp\n"); - - /* never returns */ + /* XXX */ + /* __asm__ __volatile__ ("ldi r31,0xf8\n"); */ + /* __asm__ __volatile__ ("ldi r30,0x00\n"); */ + /* __asm__ __volatile__ ("eijmp\n"); */ } void xbee_mainloop(void) @@ -518,25 +547,28 @@ void xbee_mainloop(void) int16_t c; /* from xbee to cmdline */ - c = CDC_Device_ReceiveByte(&VirtualSerial2_CDC_Interface); + c = xbee_dev_recv(NULL); if (c >= 0) - CDC_Device_SendByte(&VirtualSerial1_CDC_Interface, - (uint8_t)c); + cmdline_dev_send((uint8_t)c, NULL); /* from cmdline to xbee */ - c = CDC_Device_ReceiveByte(&VirtualSerial1_CDC_Interface); + c = cmdline_dev_recv(NULL); if (c == 4) { /* CTRL-d */ + xbee_dev_send('A', NULL); + xbee_dev_send('T', NULL); + xbee_dev_send('C', NULL); + xbee_dev_send('N', NULL); + xbee_dev_send('\n', NULL); xbee_raw = 0; rdline_newline(&xbeeboard.rdl, xbeeboard.prompt); } else if (c >= 0) { /* send to xbee */ - CDC_Device_SendByte(&VirtualSerial2_CDC_Interface, - (uint8_t)c); + xbee_dev_send((uint8_t)c, NULL); + /* echo on cmdline */ - CDC_Device_SendByte(&VirtualSerial1_CDC_Interface, - (uint8_t)c); + cmdline_dev_send((uint8_t)c, NULL); } } else { @@ -544,9 +576,94 @@ void xbee_mainloop(void) cmdline_poll(); xbee_proto_rx(xbee_dev); } + } +} + +/* return time in milliseconds on unsigned 16 bits */ +static uint16_t get_time_ms(void) +{ + return global_ms; +} + +static void main_timer_interrupt(void) +{ + static uint16_t cycles; + static uint8_t cpt; + + cpt++; + + /* interrupt every 2048 cycles */ + cycles += 2048; + if (cycles >= 12000) { + cycles -= 12000; + global_ms ++; + } + + /* LED blink */ + if (global_ms & 0x80) + LED1_ON(); + else + LED1_OFF(); - CDC_Device_USBTask(&VirtualSerial1_CDC_Interface); - CDC_Device_USBTask(&VirtualSerial2_CDC_Interface); - USB_USBTask(); + if (cpt & beep_mask) + BUZZER_ON(); + else + BUZZER_OFF(); + + /* call scheduler every 682us with interrupt unlocked */ + sei(); + if ((cpt & 0x3) == 0) + scheduler_interrupt(); +} + +int main(void) +{ + //struct callout t1; + FILE *xbee_file; + int8_t err; + struct xbee_dev dev; + + DDRA = 0x07 /* LEDs */ | 0x10 /* buzzer */; + + uart_init(); + uart_register_rx_event(CMDLINE_UART, emergency); + + fdevopen(cmdline_dev_send, cmdline_dev_recv); + xbee_file = fdevopen(xbee_dev_send, xbee_dev_recv); + scheduler_init(); + timer_init(); + timer0_register_OV_intr(main_timer_interrupt); + + cmdline_init(); + spi_servo_init(); + beep_init(); + + printf_P(PSTR("\r\n")); + rdline_newline(&xbeeboard.rdl, xbeeboard.prompt); + + callout_manager_init(&cm, get_time_ms); + //callout_reset(&cm, &t1, 500, PERIODICAL, do_led_blink, NULL); + + /* initialize libxbee */ + err = xbee_init(); + if (err < 0) + return -1; + + xbee_dev = &dev; + + /* open xbee device */ + if (xbee_open(xbee_dev, xbee_file) < 0) + return -1; + + /* register default channel with a callback */ + if (xbee_register_channel(xbee_dev, XBEE_DEFAULT_CHANNEL, + xbee_rx, NULL) < 0) { + fprintf(stderr, "cannot register default channel\n"); + return -1; } + sei(); + + eeprom_load_config(); + xbee_mainloop(); + return 0; }