# 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 */