X-Git-Url: http://git.droids-corp.org/?p=protos%2Fxbee-avr.git;a=blobdiff_plain;f=main.c;h=aded3128ed26a3fdecaae993016e70fd51b15e73;hp=272090f12aa4ca5fa47a0b814789a7047e7ff10c;hb=HEAD;hpb=6bef00254dd5299a966d73a5d6ab3ce561e93745 diff --git a/main.c b/main.c index 272090f..aded312 100644 --- a/main.c +++ b/main.c @@ -25,6 +25,11 @@ * 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 + * -> it failed but I answered y, then make reset and it was ok + */ + #include #include #include @@ -42,511 +47,167 @@ #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 "../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; - -#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("%s at [%p], len=%d\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); - for (i=0; ofs+i < len && i<16; i++) - out += snprintf(line+out, LINE_LEN - out, " %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); - } - printf("%s\n", line); - } -} - -static int parse_xmit_status(struct xbee_ctx *ctx, - struct xbee_xmit_status_hdr *frame, unsigned len) +void bootloader(void) { - if (ctx == NULL) { - printf("no context\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"); - return -1; +#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; - /* XXX use defines for these values */ - if (frame->delivery_status == 0x00) - printf("Success\n"); - else if (frame->delivery_status == 0x01) - printf("MAC ACK Failure\n"); - else if (frame->delivery_status == 0x15) - printf("Invalid destination endpoint\n"); - else if (frame->delivery_status == 0x21) - printf("Network ACK Failure\n"); - else if (frame->delivery_status == 0x25) - printf("Route Not Found\n"); - - return 0; + /* XXX */ + /* __asm__ __volatile__ ("ldi r31,0xf8\n"); */ + /* __asm__ __volatile__ ("ldi r30,0x00\n"); */ + /* __asm__ __volatile__ ("eijmp\n"); */ } -static int dump_atcmd(struct xbee_ctx *ctx, struct xbee_atresp_hdr *frame, - unsigned len) +/* return time in milliseconds on unsigned 16 bits */ +uint16_t get_time_ms(void) { - char atcmd_str[3]; - struct xbee_atcmd_pgm *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("no context\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("invalid response <%c%c><%s><%s>\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"); - return -1; - } - memcpy_P(&cmd, cmd_pgm, sizeof(cmd)); - - /* bad status */ - if (frame->status == 1) { - printf("Status is error\n"); - return -1; - } - else if (frame->status == 2) { - printf("Invalid command\n"); - return -1; - } - else if (frame->status == 3) { - printf("Invalid parameter\n"); - return -1; - } - else if (frame->status != 0) { - printf("Unknown status error %d\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("<%s> is 0x%x\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)); - else if (cmd.flags & XBEE_ATCMD_F_PARAM_U32 && len == sizeof(uint32_t)) - printf("<%s> is 0x%"PRIx32"\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)); - else if (len == 0) - printf("no data, status ok\n"); - else - hexdump("atcmd answer", frame->data, len); - - - return 0; + uint16_t ms; + uint8_t flags; + IRQ_LOCK(flags); + ms = global_ms; + IRQ_UNLOCK(flags); + return ms; } - -int xbee_recv_data(struct xbee_recv_hdr *recvframe, unsigned len) +static void main_timer_interrupt(void) { - int datalen = len - sizeof(*recvframe); - struct rc_proto_hdr *rch = (struct rc_proto_hdr *) &recvframe->data; - - if (datalen < sizeof(struct rc_proto_hdr)) - return -1; - - switch (rch->type) { - case RC_PROTO_TYPE_CHANNEL: - if (datalen != sizeof(struct rc_proto_channel)) - return -1; - break; - case RC_PROTO_TYPE_RANGE: { - struct rc_proto_range *rcr = - (struct rc_proto_range *) recvframe->data; + static uint16_t cycles; + static uint8_t cpt = 0; + static uint8_t stack = 0; - if (datalen != sizeof(struct rc_proto_range)) - return -1; + cpt++; - if (rcr->power_level >= MAX_POWER_LEVEL) - return -1; - - rc_proto_rx_range(rcr->power_level); - - break; - } - default: - return -1; - } + /* LED blink */ + if (global_ms & 0x80) + LED1_ON(); + else + LED1_OFF(); - return 0; -} + if (cpt & beep_mask) + BUZZER_ON(); + else + BUZZER_OFF(); -/* 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("type=0x%x, channel=%d, ctx=%p\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]); - } + if ((cpt & 0x03) != 0) + return; - /* some additional checks before sending */ - switch (type) { - case XBEE_TYPE_MODEM_STATUS: { - printf("Received Modem Status frame\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("from remote address %"PRIx32"%"PRIx32"\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("Invalid frame\n"); - do_hexdump = 1; - break; + /* 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 ++; } - 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); - } - } + /* called */ + if (stack++ == 0) + LED2_ON(); + sei(); + if ((cpt & 0x3) == 0) + callout_manage(&xbeeboard.intr_cm); + cli(); + if (--stack == 0) + LED2_OFF(); } -static int xbeeapp_send(struct xbee_ctx *ctx, int type, void *buf, unsigned len, - int foreground) +int main(void) { - int ret; - int channel; - - if (len > XBEE_MAX_FRAME_LEN) { - printf("frame too large\n"); + 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); + timer_init(); + timer0_register_OV_intr(main_timer_interrupt); + + callout_mgr_init(&xbeeboard.intr_cm, get_time_ms); + + 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); + + spi_servo_init(); + beep_init(); + + /* initialize libxbee */ + err = xbee_init(); + if (err < 0) return -1; - } - /* register a channel */ - channel = xbee_register_channel(xbee_dev, XBEE_CHANNEL_ANY, - xbee_rx, NULL); - if (channel < 0) { - printf("cannot send: no free channel\n"); - return -1; - } + xbee_dev = &dev; - /* 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("send frame channel=%d type=0x%x len=%d\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("cannot send\n"); - xbee_unregister_channel(xbee_dev, channel); + /* open xbee device */ + if (xbee_open(xbee_dev, xbee_file) < 0) 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) { + /* register default channel with a callback */ + if (xbee_register_channel(xbee_dev, XBEE_DEFAULT_CHANNEL, + xbeeapp_rx, NULL) < 0) { + fprintf(stderr, "cannot register default channel\n"); return -1; } - return 0; -} + xbeeapp_init(); -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; - } + rc_proto_init(); - return 0; -} + sei(); -void xbee_stdin_enable(void) -{ - xbee_cmdline_input_enabled = 1; -} + eeprom_load_config(); -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; - - printf("Timeout\n"); - - /* restart command line */ - xbee_stdin_enable(); + printf_P(PSTR("\r\n")); 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 0x1e000 - if (pgm_read_byte_far(BOOTLOADER_ADDR) == 0xff) { - printf_P(PSTR("Bootloader is not present\r\n")); - return; - } - cli(); - /* ... very specific :( */ - EIMSK = 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 */ -} - -void xbee_mainloop(void) -{ - while (1) { - callout_manage(&cm); - - if (xbee_raw) { - int16_t c; - - /* from xbee to cmdline */ - c = CDC_Device_ReceiveByte(&VirtualSerial2_CDC_Interface); - if (c >= 0) - CDC_Device_SendByte(&VirtualSerial1_CDC_Interface, - (uint8_t)c); - - /* from cmdline to xbee */ - c = CDC_Device_ReceiveByte(&VirtualSerial1_CDC_Interface); - if (c == 4) { /* CTRL-d */ - 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); - /* echo on cmdline */ - CDC_Device_SendByte(&VirtualSerial1_CDC_Interface, - (uint8_t)c); - } - } - else { - if (xbee_cmdline_input_enabled) - cmdline_poll(); - xbee_proto_rx(xbee_dev); - } - - CDC_Device_USBTask(&VirtualSerial1_CDC_Interface); - CDC_Device_USBTask(&VirtualSerial2_CDC_Interface); - USB_USBTask(); - } + xbee_mainloop(); + return 0; }