BeRTOS
pocketcmd.c
Go to the documentation of this file.
00001 
00056 #include "pocketcmd.h"
00057 #include "pocketbus.h"
00058 
00059 #include "cfg/cfg_pocketbus.h"
00060 
00061 // Define logging setting (for cfg/log.h module).
00062 #define LOG_LEVEL         POCKETBUS_LOG_LEVEL
00063 #define LOG_VERBOSITY     POCKETBUS_LOG_FORMAT
00064 #include <cfg/log.h>
00065 #include <cfg/debug.h>
00066 #include <cfg/macros.h>
00067 #include <cfg/module.h>
00068 
00069 #include <drv/timer.h>
00070 
00071 #include <cpu/byteorder.h>
00072 #include <cpu/detect.h>
00073 
00074 #include <string.h>
00075 
00080 void pocketcmd_poll(struct PocketCmdCtx *ctx)
00081 {
00082     PocketCmdMsg msg;
00083     while (pocketcmd_recv(ctx, &msg))
00084     {
00085         /* Check for command callback */
00086         pocketcmd_hook_t callback = ctx->search(msg.cmd);
00087 
00088         /* Call it if exists */
00089         if (callback)
00090             callback(&msg);
00091     }
00092 }
00093 
00094 
00095 
00100 bool pocketcmd_recv(struct PocketCmdCtx *ctx, PocketCmdMsg *recv_msg)
00101 {
00102     PocketMsg msg;
00103 
00104     /* Try to read a packet from pocketBus */
00105     while (pocketbus_recv(ctx->bus_ctx, &msg))
00106     {
00107         /* Check address */
00108         if (msg.addr == ctx->addr ||
00109             msg.addr == POCKETBUS_BROADCAST_ADDR)
00110         {
00111 
00112             #if CPU_AVR
00113                 const PocketCmdHdr *hdr = (const PocketCmdHdr *)msg.payload;
00114             #else
00115                 #if !CPU_ARM
00116                     #warning Fix alignment problem..
00117                     /*
00118                      * The code below make one memcopy, this the only way to
00119                      * solve alignment problem on ARM. If you are use other
00120                      * architecture you should find other way to optimize
00121                      * this code.
00122                      */
00123                 #endif
00124                 PocketCmdHdr hd;
00125                 memcpy(&hd, msg.payload, sizeof(PocketCmdHdr));
00126                 const PocketCmdHdr *hdr =  &hd;
00127             #endif
00128 
00129             pocketcmd_t cmd = be16_to_cpu(hdr->cmd);
00130 
00131             /* We're no longer waiting for a reply (in case we were) */
00132             if (cmd == ctx->waiting)
00133                 ctx->waiting = PKTCMD_NULL;
00134 
00135             recv_msg->cmd_ctx = ctx;
00136             recv_msg->cmd = cmd;
00137             recv_msg->len = msg.len - sizeof(PocketCmdHdr);
00138             recv_msg->buf = msg.payload + sizeof(PocketCmdHdr);
00139 
00140             return true;
00141         }
00142     }
00143 
00144     return false;
00145 }
00146 
00147 
00154 bool pocketcmd_send(struct PocketCmdCtx *ctx, pocketcmd_t cmd, const void *buf, size_t len, bool wait_reply)
00155 {
00156     /* Check if we are waiting a reply from someone */
00157     if (ctx->waiting != PKTCMD_NULL)
00158     {
00159         /* Check is reply timeout is elapsed */
00160         if (timer_clock() - ctx->reply_timer < ms_to_ticks(CONFIG_POCKETBUS_CMD_REPLY_TIMEOUT))
00161         {
00162             LOG_ERR("Pkt discard! waiting cmd[%04X]\n", ctx->waiting);
00163             return false;
00164         }
00165         else
00166         {
00167             LOG_INFO("Timeout waiting cmd[%04X]\n", ctx->waiting);
00168             ctx->waiting = PKTCMD_NULL;
00169         }
00170     }
00171 
00172     /* Endianess! */
00173     cmd = cpu_to_be16(cmd);
00174 
00175     /* Send packet */
00176     pocketbus_begin(ctx->bus_ctx, ctx->addr);
00177     pocketbus_write(ctx->bus_ctx, &cmd, sizeof(cmd));
00178     pocketbus_write(ctx->bus_ctx, buf, len);
00179     pocketbus_end(ctx->bus_ctx);
00180 
00181     if (wait_reply)
00182     {
00183         ctx->waiting = be16_to_cpu(cmd);
00184         ctx->reply_timer = timer_clock();
00185     }
00186 
00187     return true;
00188 }
00189 
00197 void pocketcmd_init(struct PocketCmdCtx *ctx, struct PocketBusCtx *bus_ctx, pocketbus_addr_t addr, pocketcmd_lookup_t search)
00198 {
00199     ASSERT(ctx);
00200     ASSERT(bus_ctx);
00201     ASSERT(search);
00202     MOD_CHECK(timer);
00203 
00204     memset(ctx, 0, sizeof(*ctx));
00205     ctx->bus_ctx = bus_ctx;
00206     ctx->search = search;
00207     pocketcmd_setAddr(ctx, addr);
00208 }
00209 
00213 void pocketcmd_replyAck(struct PocketCmdMsg *msg)
00214 {
00215     uint8_t ack[] = { POCKETBUS_ACK };
00216 
00217     pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, ack, sizeof(ack));
00218 }
00219 
00223 void pocketcmd_replyNak(struct PocketCmdMsg *msg)
00224 {
00225     uint8_t nak[] = { POCKETBUS_NAK };
00226 
00227     pocketcmd_slaveReply(msg->cmd_ctx, msg->cmd, nak, sizeof(nak));
00228 }
00229