pocketcmd.c

Go to the documentation of this file.
00001 
00058 #include "pocketcmd.h"
00059 #include "pocketbus.h"
00060 
00061 #include <cfg/macros.h>
00062 #include <cfg/debug.h>
00063 #include <cfg/module.h>
00064 
00065 #include <drv/timer.h>
00066 
00067 #include <cpu/byteorder.h>
00068 #include <cpu/detect.h>
00069 
00070 #include <string.h>
00071 
00076 void pocketcmd_poll(struct PocketCmdCtx *ctx)
00077 {
00078     PocketMsg msg;
00079 
00080     /* Try to read a packet from pocketBus */
00081     while (pocketbus_recv(ctx->bus_ctx, &msg))
00082     {
00083         /* Check address */
00084         if (msg.addr == ctx->addr ||
00085             msg.addr == POCKETBUS_BROADCAST_ADDR)
00086         {
00087 
00088             #if CPU_AVR
00089                 const PocketCmdHdr *hdr = (const PocketCmdHdr *)msg.payload;
00090             #else
00091                 #if !CPU_ARM
00092                     #warning Fix alignment problem..
00093                     /*
00094                      * The code below make one memcopy, this the only way to
00095                      * solve alignment problem on ARM. If you are use other
00096                      * architecture you should find other way to optimize
00097                      * this code.
00098                      */
00099                 #endif
00100                 PocketCmdHdr hd;
00101                 memcpy(&hd, msg.payload, sizeof(PocketCmdHdr));
00102                 const PocketCmdHdr *hdr =  &hd;
00103             #endif
00104 
00105             pocketcmd_t cmd = be16_to_cpu(hdr->cmd);
00106 
00107             /* We're no longer waiting for a reply (in case we were) */
00108             if (cmd == ctx->waiting)
00109                 ctx->waiting = PKTCMD_NULL;
00110 
00111             /* Check for command callback */
00112             pocketcmd_hook_t callback = ctx->search(cmd);
00113 
00114             /* Call it if exists */
00115             if (callback)
00116             {
00117                 PocketCmdMsg cmd_msg;
00118 
00119                 cmd_msg.cmd_ctx = ctx;
00120                 cmd_msg.cmd = cmd;
00121                 cmd_msg.len = msg.len - sizeof(PocketCmdHdr);
00122                 cmd_msg.buf = msg.payload + sizeof(PocketCmdHdr);
00123 
00124                 callback(&cmd_msg);
00125             }
00126         }
00127     }
00128 }
00129 
00136 bool pocketcmd_send(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len, bool wait_reply)
00137 {
00138     /* Check if we are waiting a reply from someone */
00139     if (ctx->waiting != PKTCMD_NULL)
00140     {
00141         /* Check is reply timeout is elapsed */
00142         if (timer_clock() - ctx->reply_timer < ms_to_ticks(PKTCMD_REPLY_TIMEOUT))
00143         {
00144             TRACEMSG("Pkt discard! waiting cmd[%04X]\n", ctx->waiting);
00145             return false;
00146         }
00147         else
00148         {
00149             TRACEMSG("Timeout waiting cmd[%04X]\n", ctx->waiting);
00150             ctx->waiting = PKTCMD_NULL;
00151         }
00152     }
00153 
00154     /* Endianess! */
00155     cmd = cpu_to_be16(cmd);
00156 
00157     /* Send packet */
00158     pocketbus_begin(ctx->bus_ctx, ctx->addr);
00159     pocketbus_write(ctx->bus_ctx, &cmd, sizeof(cmd));
00160     pocketbus_write(ctx->bus_ctx, buf, len);
00161     pocketbus_end(ctx->bus_ctx);
00162 
00163     if (wait_reply)
00164     {
00165         ctx->waiting = cmd;
00166         ctx->reply_timer = timer_clock();
00167     }
00168     return true;
00169 }
00170 
00178 void pocketcmd_init(struct PocketCmdCtx *ctx, struct PocketBusCtx *bus_ctx, pocketbus_addr_t addr, pocketcmd_lookup_t search)
00179 {
00180     ASSERT(ctx);
00181     ASSERT(bus_ctx);
00182     ASSERT(search);
00183     MOD_CHECK(timer);
00184 
00185     memset(ctx, 0, sizeof(*ctx));
00186     ctx->bus_ctx = bus_ctx;
00187     ctx->search = search;
00188     pocketcmd_setAddr(ctx, addr);
00189 }
00190 
00194 void pocketcmd_replyAck(struct PocketCmdMsg *msg)
00195 {
00196     uint8_t ack[] = { POCKETBUS_ACK };
00197 
00198     pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, ack, sizeof(ack));
00199 }
00200 
00204 void pocketcmd_replyNak(struct PocketCmdMsg *msg)
00205 {
00206     uint8_t nak[] = { POCKETBUS_NAK };
00207 
00208     pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, nak, sizeof(nak));
00209 }
00210