wgpio.c

Go to the documentation of this file.
00001 /* Copyright (c) 2007, 2008 Axel Wachtler
00002    All rights reserved.
00003 
00004    Redistribution and use in source and binary forms, with or without
00005    modification, are permitted provided that the following conditions
00006    are met:
00007 
00008    * Redistributions of source code must retain the above copyright
00009      notice, this list of conditions and the following disclaimer.
00010    * Redistributions in binary form must reproduce the above copyright
00011      notice, this list of conditions and the following disclaimer in the
00012      documentation and/or other materials provided with the distribution.
00013    * Neither the name of the authors nor the names of its contributors
00014      may be used to endorse or promote products derived from this software
00015      without specific prior written permission.
00016 
00017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027    POSSIBILITY OF SUCH DAMAGE. */
00028 
00029 /* $Id: wgpio.c,v 1.12 2009/12/22 16:47:10 joerg_wunsch Exp $ */
00057 /* === includes ========================================== */
00058 #include "wgpio.h"
00059 
00060 /* === macros ============================================ */
00061 #define AWAKE_TIME   MSEC(1000)
00062 /* === types ============================================= */
00063 /* === globals =========================================== */
00064 /* prog ctx r/w */
00065 actor_ctx_t ActorCtx;
00066 uint8_t Led1Blnk = 0;
00067 
00068 /*  IRQ Variables r/w */
00069 volatile uint16_t TmoCounter = 0;
00070 
00071 /*  IRQ Variables wo */
00072 volatile event_t TrxEvent;
00073 volatile uint8_t KeyEvent = 0;
00074 volatile uint8_t TmoEvent = 0;
00075 /*  IRQ Variables ro */
00076 volatile app_state_t TrxState;
00077 
00078 /* === prototypes ======================================== */
00079 
00080 /* === functions ========================================= */
00081 
00085 int main(void)
00086 {
00087 app_ctx_t AppCtx = {0};
00088 
00089     trap_if_key_pressed();
00090     wgpio_init();
00091     AppCtx.appstate = APP_RUNNING;
00092     while(1)
00093     {
00094         /* free irq variables and work with actual copies */
00095         cli();
00096         AppCtx.rx.cmd = TrxEvent.cmd;
00097         AppCtx.rx.state = TrxEvent.state;
00098         TrxEvent.cmd = NONE;
00099         AppCtx.key = KeyEvent;
00100         KeyEvent = NONE_PRESS;
00101         AppCtx.tmo = TmoEvent;
00102         TmoEvent = 0;
00103         sei();
00104 
00105         switch(AppCtx.appstate)
00106         {
00107             case APP_RUNNING:
00108                 state_app_running(&AppCtx);
00109                 break;
00110 
00111             case TX_SWITCH_IN_PROGRESS:
00112                 state_tx_switch_in_progress(&AppCtx);
00113                 break;
00114 
00115             case TX_STATUS_IN_PROGRESS:
00116                 state_tx_status_in_progress(&AppCtx);
00117                 break;
00118 
00119             case APP_STATUS_PENDING:
00120                 state_app_status_pending(&AppCtx);
00121                 break;
00122 
00123             case APP_CONFIG:
00124                 state_app_config(&AppCtx);
00125                 break;
00126 
00127             default:
00128                 break;
00129         }
00130 
00131         if (AppCtx.tx.cmd != NONE && TrxState != TRX_TRANSMIT)
00132         {
00133             wgpio_send_status(AppCtx.tx.cmd, AppCtx.tx.state);
00134             AppCtx.tx.cmd = NONE;
00135         }
00136 
00137         wgpio_idle(AppCtx.slpmode);
00138     }
00139     return 0;
00140 }
00141 
00145 static void wgpio_init(void)
00146 {
00147     LED_INIT();
00148     KEY_INIT();
00149     TIMER_INIT();
00150 #if defined(SLEEP_ON_KEY)
00151     SLEEP_ON_KEY_INIT();
00152 #endif
00153     transceiver_init(CHANNEL, 0);
00154     TrxState = TRX_RECEIVE;
00155     sei();
00156     ACTOR_INIT();
00157     ActorCtx.role = 1;
00158 }
00159 
00160 static void wgpio_idle(uint8_t idlemode)
00161 {
00162     if (idlemode == SLEEP_MODE_IDLE)
00163     {
00164         SLEEP_ON_IDLE();
00165     }
00166     else if (idlemode == SLEEP_MODE_PWR_DOWN)
00167     {
00168         trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00169         TRX_SLPTR_HIGH();
00170         LED_SET_VALUE(0);
00171         #if defined(SLEEP_ON_KEY)
00172             SLEEP_ON_KEY();
00173         #else
00174             SLEEP_ON_IDLE();
00175         #endif
00176         TRX_SLPTR_LOW();
00177     }
00178 }
00179 
00180 #if defined(SLEEP_ON_KEY)
00181     ISR(SLEEP_ON_KEY_vect)
00182     {
00183     }
00184 #endif
00185 
00186 static void wgpio_actor_update(uint8_t state)
00187 {
00188     cli();
00189     if (state != 255)
00190     {
00191         ActorCtx.state = state;
00192     }
00193     else
00194     {
00195         ActorCtx.state ^= 1;
00196     }
00197     if(ActorCtx.state)
00198     {
00199         LED_SET(0);
00200         ACTOR_ON();
00201     }
00202     else
00203     {
00204         LED_CLR(0);
00205         ACTOR_OFF();
00206     }
00207     sei();
00208 }
00209 
00214 static bool wgpio_send_status(event_code_t cmd, uint8_t state)
00215 {
00216 static uint8_t seq = 0;
00217 key_frame_t txfrm;
00218 
00219     txfrm.frmctl = FCTL_KEY_FRAME;
00220     txfrm.seq = seq++;
00221     txfrm.dstpan = PANID;
00222     txfrm.dstaddr = 0;
00223     txfrm.srcaddr = 0;
00224     txfrm.cmd = cmd;
00225     txfrm.state = state;
00226     transceiver_send_frame((uint8_t*)&txfrm,sizeof(txfrm));
00227     TrxState = TRX_TRANSMIT;
00228     return true;
00229 }
00230 
00231 static void state_app_running(app_ctx_t *events)
00232 {
00233     events->slpmode = SLEEP_MODE_IDLE;
00234 
00235     if (events->key == LONG_PRESS)
00236     {
00237         trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00238         LED_SET_VALUE(ActorCtx.role);
00239         events->appstate = APP_CONFIG;
00240         status_led_config(1, 5);
00241     }
00242     else if (events->key == SHORT_PRESS)
00243     {
00244         events->appstate = TX_SWITCH_IN_PROGRESS;
00245         events->tx.cmd = CMD_SWITCH;
00246         if (ActorCtx.role == 1)
00247         {
00248             wgpio_actor_update(255);
00249             events->tx.state = ActorCtx.state;
00250         }
00251         else
00252         {
00253             events->tx.state = 255;
00254         }
00255     }
00256     else if (events->rx.cmd == CMD_SWITCH)
00257     {
00258         if (ActorCtx.role == 1)
00259         {
00260             events->appstate = TX_STATUS_IN_PROGRESS;
00261             events->tx.cmd = CMD_STATUS;
00262             events->tx.state = ActorCtx.state;
00263             wgpio_actor_update(events->rx.state);
00264         }
00265         status_led_config(0, 0);
00266     }
00267     else if (events->rx.cmd == CMD_QRY_STATUS)
00268     {
00269         if (ActorCtx.role == 1)
00270         {
00271             events->appstate = TX_STATUS_IN_PROGRESS;
00272             events->tx.cmd = CMD_STATUS;
00273             events->tx.state = ActorCtx.state;
00274         }
00275     }
00276     else if ((events->tmo) && (ActorCtx.role == 0))
00277     {
00278         events->slpmode = SLEEP_MODE_PWR_DOWN;
00279     }
00280 }
00281 
00282 
00283 static void state_tx_switch_in_progress(app_ctx_t *ctx)
00284 {
00285     if (ctx->rx.cmd == CMD_TX_DONE_OK)
00286     {
00287         ctx->appstate = APP_STATUS_PENDING;
00288         TmoCounter = MSEC(150);
00289         ctx->qrycnt = 4;
00290         status_led_config(1, 0);
00291     }
00292     else if (ctx->rx.cmd == CMD_TX_DONE_NOK)
00293     {
00294         ctx->appstate = APP_RUNNING;
00295         TmoCounter = AWAKE_TIME;
00296         status_led_config(0, 5);
00297     }
00298 }
00299 
00300 
00301 static void state_tx_status_in_progress(app_ctx_t *ctx)
00302 {
00303     /* for a status frame we do not care about the outcome */
00304     if (ctx->rx.cmd == CMD_TX_DONE_OK ||
00305         ctx->rx.cmd == CMD_TX_DONE_NOK )
00306     {
00307 
00308         TmoCounter = AWAKE_TIME;
00309         ctx->appstate = APP_RUNNING;
00310     }
00311 }
00312 
00313 
00314 static void state_app_status_pending(app_ctx_t *ctx)
00315 {
00316     if (ctx->rx.cmd == CMD_STATUS)
00317     {
00318         cli();
00319         TmoCounter = 0;
00320         sei();
00321         ctx->qrycnt = 0;
00322         TmoCounter = AWAKE_TIME;
00323         ctx->appstate = APP_RUNNING;
00324         status_led_config(0,0);
00325     }
00326     else if (ctx->tmo != 0)
00327     {
00328         status_led_config(0, 7);
00329         if (ctx->qrycnt > 0)
00330         {
00331             ctx->qrycnt --;
00332             cli();
00333                 TmoCounter = MSEC(150);
00334             sei();
00335             ctx->tx.cmd = CMD_QRY_STATUS;
00336         }
00337         else
00338         {
00339             TmoCounter = AWAKE_TIME;
00340             ctx->appstate = APP_RUNNING;
00341             LED_SET(1);
00342         }
00343     }
00344 }
00345 
00346 
00347 static void state_app_config(app_ctx_t *ctx)
00348 {
00349     if (ctx->key == SHORT_PRESS)
00350     {
00351 #if defined(SLEEP_ON_KEY)
00352         ActorCtx.role ^= 1;
00353         if(ActorCtx.role)
00354         {
00355             LED_SET(0);
00356         }
00357         else
00358         {
00359             LED_CLR(0);
00360         }
00361 #else
00362         ActorCtx.role = 1;
00363         status_led_config(1, 4);
00364 #endif
00365     }
00366     else if (ctx->key == LONG_PRESS)
00367     {
00368         TmoCounter = AWAKE_TIME;
00369         ctx->appstate = APP_RUNNING;
00370         status_led_config(0, 5);
00371         /* if role is note remote control, RDX is always on */
00372         if (ActorCtx.role == 1)
00373         {
00374             trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
00375         }
00376     }
00377 }
00378 
00382 #if defined(DOXYGEN)
00383 void TRX_IRQ_vect()
00384 #elif !defined(TRX_IF_RFA1)
00385 ISR(TRX_IRQ_vect)
00386 {
00387 uint8_t cause;
00388 key_frame_t rxfrm;
00389 
00390     cause = trx_reg_read(RG_IRQ_STATUS);
00391     if (TrxState == TRX_TRANSMIT)
00392     {
00393         cause = trx_bit_read(SR_TRAC_STATUS);
00394         TrxState = TRX_RECEIVE;
00395         if (cause == TRAC_SUCCESS)
00396         {
00397             TrxEvent.cmd = CMD_TX_DONE_OK;
00398         }
00399         else
00400         {
00401             TrxEvent.cmd = CMD_TX_DONE_NOK;
00402         }
00403         trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00404         trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
00405     }
00406     else if(TrxState == TRX_RECEIVE)
00407     {
00408         /* protect frame buffer */
00409         trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00410         trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
00411         cause = trx_frame_read ((uint8_t*)&rxfrm, sizeof(rxfrm), NULL);
00412         TrxEvent.cmd = rxfrm.cmd;
00413         TrxEvent.state = rxfrm.state;
00414         trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
00415     }
00416 }
00417 #endif
00418 
00419 #if defined(TRX_IF_RFA1)
00420 ISR(TRX24_RX_END_vect)
00421 {
00422     key_frame_t rxfrm;
00423 
00424     trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00425     trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
00426     (void)trx_frame_read ((uint8_t*)&rxfrm, sizeof(rxfrm), NULL);
00427     TrxEvent.cmd = rxfrm.cmd;
00428     TrxEvent.state = rxfrm.state;
00429     trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
00430 }
00431 
00432 ISR(TRX24_TX_END_vect)
00433 {
00434     uint8_t cause;
00435 
00436     cause = trx_bit_read(SR_TRAC_STATUS);
00437     TrxState = TRX_RECEIVE;
00438     if (cause == TRAC_SUCCESS)
00439     {
00440         TrxEvent.cmd = CMD_TX_DONE_OK;
00441     }
00442     else
00443     {
00444         TrxEvent.cmd = CMD_TX_DONE_NOK;
00445     }
00446     trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
00447     trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
00448 }
00449 #endif  /* RFA1 */
00450 
00455 #if defined(DOXYGEN)
00456 void TIMER_IRQ_vect()
00457 #else
00458 ISR(TIMER_IRQ_vect)
00459 #endif
00460 {
00461     LED_TOGGLE(1);
00462     if (KeyEvent == NONE_PRESS)
00463     {
00464         KeyEvent = debounce_key0();
00465     }
00466 
00467     if(TmoCounter > 0)
00468     {
00469         TmoCounter --;
00470         if (TmoCounter == 0)
00471         {
00472             TmoEvent = 1;
00473         }
00474     }
00475     LED_TOGGLE(1);
00476     status_led_handle();
00477 }
00478 
00479 
00480 static void status_led_config(uint8_t val, uint8_t blnk)
00481 {
00482     if(val != IGNORE)
00483     {
00484         if (val & 1)
00485         {
00486             LED_SET(1);
00487         }
00488         else
00489         {
00490             LED_CLR(1);
00491         }
00492     }
00493     if (blnk != IGNORE)
00494     {
00495         Led1Blnk = blnk;
00496     }
00497 }
00498 
00499 
00500 static void status_led_handle()
00501 {
00502 static uint16_t tmr_tick = 0;
00503 
00504     tmr_tick ++;
00505     if (tmr_tick >= MSEC(100))
00506     {
00507         tmr_tick = 0;
00508         if (Led1Blnk > 1)
00509         {
00510             Led1Blnk--;
00511             if(Led1Blnk==0)
00512             {
00513                 LED_CLR(1);
00514             }
00515             else
00516             {
00517                 LED_TOGGLE(1);
00518             }
00519         }
00520     }
00521 }
00522 
00523 /* EOF */

This documentation for µracoli was generated on Wed Feb 2 2011 by  doxygen 1.7.1