X-Git-Url: http://git.droids-corp.org/?p=protos%2Fxbee-avr.git;a=blobdiff_plain;f=main.c;h=aded3128ed26a3fdecaae993016e70fd51b15e73;hp=2d1dd158f1a2c63d8b9936c7d564cc64400c62b9;hb=HEAD;hpb=a8c1b4c97c02a29a202362263597e90d36f25c18 diff --git a/main.c b/main.c index 2d1dd15..aded312 100644 --- a/main.c +++ b/main.c @@ -26,7 +26,8 @@ */ /* fuses: - * avrdude -p atmega1284p -P usb -c avrispmkii -U lfuse:w:0xff:m -U hfuse:w:0x99:m -U efuse:w:0xff:m + * avrdude -p atmega1284p -P usb -c avrispmkii -U lfuse:w:0xff:m -U hfuse:w:0x91:m -U efuse:w:0xff:m + * -> it failed but I answered y, then make reset and it was ok */ #include @@ -46,479 +47,24 @@ #include #include -#include -#include #include #include #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 "spi_servo.h" +#include "../fpv-common/i2c_commands.h" +#include "eeprom_config.h" +#include "beep.h" +#include "xbee_user.h" +#include "i2c_protocol.h" #include "main.h" struct xbeeboard xbeeboard; -volatile uint16_t global_ms; -struct callout_manager cm; - -#define TIMEOUT_MS 1000 +volatile uint32_t global_ms; /* global xbee device */ struct xbee_dev *xbee_dev; -/* events */ -//static struct event stdin_read_event, xbee_read_event; - -/* parameters */ -int xbee_raw = 0; -int xbee_hexdump = 0; -int xbee_debug = 0; - -int xbee_cmdline_input_enabled = 1; - -static struct xbee_ctx xbee_ctx[XBEE_MAX_CHANNEL]; - -static void hexdump(const char *title, const void *buf, unsigned int len) -{ - unsigned int i, out, ofs; - const unsigned char *data = buf; -#define LINE_LEN 80 - char line[LINE_LEN]; /* space needed 8+16*3+3+16 == 75 */ - - 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_P(line, LINE_LEN, PSTR("%08X"), ofs); - for (i=0; ofs+i < len && i<16; i++) - 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_P(line+out, - LINE_LEN - out, - PSTR("%c"), c); - } - 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_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_P(PSTR("invalid response 2\r\n")); - return -1; - } - - /* XXX use defines for these values */ - if (frame->delivery_status == 0x00) - printf_P(PSTR("Success\r\n")); - else if (frame->delivery_status == 0x01) - printf_P(PSTR("MAC ACK Failure\r\n")); - else if (frame->delivery_status == 0x15) - printf_P(PSTR("Invalid destination endpoint\r\n")); - else if (frame->delivery_status == 0x21) - printf_P(PSTR("Network ACK Failure\r\n")); - else if (frame->delivery_status == 0x25) - printf_P(PSTR("Route Not Found\r\n")); - - return 0; -} - -static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, - unsigned len) -{ - char atcmd_str[3]; - const struct xbee_atcmd *cmd_pgm; - struct xbee_atcmd cmd; - union { - uint8_t u8; - uint16_t u16; - uint32_t u32; - int16_t s16; - } __attribute__((packed)) *result; - - if (ctx == NULL) { - printf_P(PSTR("no context\r\n")); - return -1; - } - - /* get AT command from frame */ - memcpy(atcmd_str, &frame->cmd, 2); - atcmd_str[2] = '\0'; - - /* see if it matches query */ - if (memcmp(atcmd_str, ctx->atcmd_query, 2)) { - 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_P(PSTR("unknown response\r\n")); - return -1; - } - memcpy_P(&cmd, cmd_pgm, sizeof(cmd)); - - /* bad status */ - if (frame->status == 1) { - printf_P(PSTR("Status is error\r\n")); - return -1; - } - else if (frame->status == 2) { - printf_P(PSTR("Invalid command\r\n")); - return -1; - } - else if (frame->status == 3) { - printf_P(PSTR("Invalid parameter\r\n")); - return -1; - } - else if (frame->status != 0) { - printf_P(PSTR("Unknown status error %d\r\n"), frame->status); - return -1; - } - - /* callback */ - if (ctx->func != NULL) - ctx->func(frame, len, ctx->arg); - - /* dump 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_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_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_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_P(PSTR("<%s> is %d\r\n"), atcmd_str, ntohs(result->s16)); - else if (len == 0) - printf_P(PSTR("no data, status ok\r\n")); - else - hexdump("atcmd answer", frame->data, len); - - - return 0; -} - - -int xbee_recv_data(struct xbee_recv_hdr *recvframe, unsigned len) -{ - 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: { - 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->data; - - if (datalen != sizeof(struct rc_proto_range)) - return -1; - - if (rcr->power_level >= MAX_POWER_LEVEL) - return -1; - - rc_proto_rx_range(rcr->power_level); - - break; - } - default: - return -1; - } - - return 0; -} - -/* socat /dev/ttyUSB0,raw,echo=0,b115200 /dev/ttyACM1,raw,echo=0,b115200 */ -void xbee_rx(struct xbee_dev *dev, int channel, int type, - void *frame, unsigned len, void *opaque) -{ - struct xbee_ctx *ctx = opaque; - int do_hexdump = xbee_hexdump; - - if (xbee_debug) - 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_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_P(PSTR("Received Modem Status frame\r\n")); - break; - } - - case XBEE_TYPE_RMT_ATRESP: { - union { - uint64_t u64; - struct { -#if BYTE_ORDER == LITTLE_ENDIAN - uint32_t low; - uint32_t high; -#else - uint32_t high; - uint32_t low; -#endif - } u32; - } addr; - memcpy(&addr, frame, sizeof(addr)); - addr.u64 = ntohll(addr.u64); - 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) - do_hexdump = 1; - break; - } - case XBEE_TYPE_ATRESP: { - if (dump_atcmd(ctx, frame, len) < 0) - do_hexdump = 1; - break; - } - - case XBEE_TYPE_XMIT_STATUS: { - if (parse_xmit_status(ctx, frame, len) < 0) - do_hexdump = 1; - break; - } - - case XBEE_TYPE_RECV: { - if (xbee_recv_data(frame, len) < 0) - do_hexdump = 1; - break; - } - - case XBEE_TYPE_ATCMD: - case XBEE_TYPE_ATCMD_Q: - case XBEE_TYPE_XMIT: - case XBEE_TYPE_EXPL_XMIT: - case XBEE_TYPE_RMT_ATCMD: - case XBEE_TYPE_EXPL_RECV: - case XBEE_TYPE_NODE_ID: - default: - printf_P(PSTR("Invalid frame\r\n")); - do_hexdump = 1; - break; - } - - if (do_hexdump) - hexdump("undecoded rx frame", frame, len); - - /* restart command line if it was a blocking query */ - if (ctx != NULL) { - xbee_unregister_channel(dev, channel); - if (ctx->foreground) { - xbee_stdin_enable(); - rdline_newline(&xbeeboard.rdl, xbeeboard.prompt); - } - } -} - -static int xbeeapp_send(struct xbee_ctx *ctx, int type, void *buf, unsigned len, - int foreground) -{ - int ret; - int channel; - - if (len > XBEE_MAX_FRAME_LEN) { - printf_P(PSTR("frame too large\r\n")); - return -1; - } - - /* register a channel */ - channel = xbee_register_channel(xbee_dev, XBEE_CHANNEL_ANY, - xbee_rx, NULL); - if (channel < 0) { - printf_P(PSTR("cannot send: no free channel\r\n")); - return -1; - } - - /* copy context in the static struct table (avoiding a malloc) */ - memcpy(&xbee_ctx[channel], ctx, sizeof(*ctx)); - ctx = &xbee_ctx[channel]; - xbee_set_opaque(xbee_dev, channel, ctx); - - if (xbee_debug) - 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); - - /* transmit the frame on this channel */ - ret = xbee_proto_xmit(xbee_dev, channel, type, buf, - len); - if (ret < 0) { - printf_P(PSTR("cannot send\r\n")); - xbee_unregister_channel(xbee_dev, channel); - return -1; - } - - ctx->channel = channel; - xbee_load_timeout(ctx); /* load a timeout event */ - - /* suspend command line until we have answer or timeout */ - if (foreground) { - ctx->foreground = 1; - rdline_stop(&xbeeboard.rdl); /* don't display prompt when return */ - xbee_stdin_disable(); /* unload file descriptor polling */ - } - - return 0; -} - -/* send an AT command with parameters filled by caller. Disable - * command line until we get the answer or until a timeout occurs */ -int xbeeapp_send_atcmd(const char *atcmd_str, - void *param, unsigned param_len, int foreground, - int (*func)(void *frame, unsigned len, void *arg), void *arg) -{ - struct xbee_ctx ctx; - struct { - struct xbee_atcmd_hdr atcmd; - char buf[XBEE_MAX_FRAME_LEN]; - } __attribute__((packed)) frame; - - memset(&ctx, 0, sizeof(ctx)); - ctx.atcmd_query[0] = atcmd_str[0]; - ctx.atcmd_query[1] = atcmd_str[1]; - ctx.func = func; - ctx.arg = arg; - - memcpy(&frame.atcmd.cmd, atcmd_str, 2); - memcpy(&frame.buf, param, param_len); - - if (xbeeapp_send(&ctx, XBEE_TYPE_ATCMD, &frame, - sizeof(struct xbee_atcmd_hdr) + - param_len, foreground) < 0) { - return -1; - } - - return 0; -} - -int xbeeapp_send_msg(uint64_t addr, void *data, - unsigned data_len, int foreground) -{ - struct xbee_ctx ctx; - struct { - struct xbee_xmit_hdr xmit; - char buf[XBEE_MAX_FRAME_LEN]; - } __attribute__((packed)) frame; - - memset(&ctx, 0, sizeof(ctx)); - ctx.atcmd_query[0] = '\0'; - - frame.xmit.dstaddr = htonll(addr); - frame.xmit.reserved = htons(0xFFFE); - frame.xmit.bcast_radius = 0; - frame.xmit.opts = 0; - memcpy(&frame.buf, data, data_len); - - if (xbeeapp_send(&ctx, XBEE_TYPE_XMIT, &frame, - sizeof(struct xbee_xmit_hdr) + - data_len, foreground) < 0) { - return -1; - } - - return 0; -} - -void xbee_stdin_enable(void) -{ - xbee_cmdline_input_enabled = 1; -} - -void xbee_stdin_disable(void) -{ - xbee_cmdline_input_enabled = 0; -} - -static void evt_timeout(struct callout_manager *cm, struct callout *clt, - void *arg) -{ - struct xbee_ctx *ctx = arg; - - (void)cm; - (void)clt; - - printf_P(PSTR("Timeout\r\n")); - - /* restart command line */ - xbee_stdin_enable(); - rdline_newline(&xbeeboard.rdl, xbeeboard.prompt); - - /* free event */ - xbee_unregister_channel(xbee_dev, ctx->channel); -} - -void xbee_load_timeout(struct xbee_ctx *ctx) -{ - callout_reset(&cm, &ctx->timeout, TIMEOUT_MS, SINGLE, evt_timeout, ctx); -} - -void xbee_unload_timeout(struct xbee_ctx *ctx) -{ - callout_stop(&cm, &ctx->timeout); -} - void bootloader(void) { #define BOOTLOADER_ADDR 0x3f000 @@ -546,59 +92,24 @@ void bootloader(void) /* __asm__ __volatile__ ("eijmp\n"); */ } -void xbee_mainloop(void) -{ - while (1) { - callout_manage(&cm); - - if (xbee_raw) { - int16_t c; - - /* from xbee to cmdline */ - c = xbee_dev_recv(NULL); - if (c >= 0) - cmdline_dev_send((uint8_t)c, NULL); - - /* from cmdline to xbee */ - c = cmdline_dev_recv(NULL); - if (c == 4) { /* CTRL-d */ - xbee_raw = 0; - rdline_newline(&xbeeboard.rdl, - xbeeboard.prompt); - } - else if (c >= 0) { - /* send to xbee */ - xbee_dev_send((uint8_t)c, NULL); - - /* echo on cmdline */ - cmdline_dev_send((uint8_t)c, NULL); - } - } - else { - if (xbee_cmdline_input_enabled) - cmdline_poll(); - xbee_proto_rx(xbee_dev); - } - } -} - /* return time in milliseconds on unsigned 16 bits */ -static uint16_t get_time_ms(void) +uint16_t get_time_ms(void) { - return global_ms; + uint16_t ms; + uint8_t flags; + IRQ_LOCK(flags); + ms = global_ms; + IRQ_UNLOCK(flags); + return ms; } static void main_timer_interrupt(void) { static uint16_t cycles; - static uint8_t cpt; + static uint8_t cpt = 0; + static uint8_t stack = 0; - /* interrupt every 2048 cycles */ - cycles += 2048; - if (cycles >= 12000) { - cycles -= 12000; - global_ms ++; - } + cpt++; /* LED blink */ if (global_ms & 0x80) @@ -606,38 +117,67 @@ static void main_timer_interrupt(void) else LED1_OFF(); - /* call scheduler every 682us with interrupt unlocked */ + if (cpt & beep_mask) + BUZZER_ON(); + else + BUZZER_OFF(); + + if ((cpt & 0x03) != 0) + return; + + /* the following code is only called one interrupt among 4: every 682us + * (at 12 Mhz) = 8192 cycles */ + cycles += 8192; + if (cycles >= 12000) { + cycles -= 12000; + global_ms ++; + } + + /* called */ + if (stack++ == 0) + LED2_ON(); sei(); if ((cpt & 0x3) == 0) - scheduler_interrupt(); + callout_manage(&xbeeboard.intr_cm); + cli(); + if (--stack == 0) + LED2_OFF(); } int main(void) { - //struct callout t1; FILE *xbee_file; int8_t err; struct xbee_dev dev; - DDRA = 0x07; /* LEDs */ + 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(); + callout_mgr_init(&xbeeboard.intr_cm, get_time_ms); - printf_P(PSTR("\r\n")); - rdline_newline(&xbeeboard.rdl, xbeeboard.prompt); + cmdline_init(); + /* LOGS */ + error_register_emerg(mylog); + error_register_error(mylog); + error_register_warning(mylog); + error_register_notice(mylog); + error_register_debug(mylog); + + /* I2C */ + i2c_init(I2C_MODE_MASTER, I2C_MAINBOARD_ADDR); + i2c_protocol_init(); + i2c_register_recv_event(i2c_recvevent); + i2c_register_send_event(i2c_sendevent); - callout_manager_init(&cm, get_time_ms); - //callout_reset(&cm, &t1, 500, PERIODICAL, do_led_blink, NULL); + spi_servo_init(); + beep_init(); /* initialize libxbee */ err = xbee_init(); @@ -652,13 +192,22 @@ int main(void) /* register default channel with a callback */ if (xbee_register_channel(xbee_dev, XBEE_DEFAULT_CHANNEL, - xbee_rx, NULL) < 0) { + xbeeapp_rx, NULL) < 0) { fprintf(stderr, "cannot register default channel\n"); return -1; } + xbeeapp_init(); + + rc_proto_init(); + sei(); + eeprom_load_config(); + + printf_P(PSTR("\r\n")); + rdline_newline(&xbeeboard.rdl, xbeeboard.prompt); + xbee_mainloop(); return 0; }