00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00057
00058 #include "wgpio.h"
00059
00060
00061 #define AWAKE_TIME MSEC(1000)
00062
00063
00064
00065 actor_ctx_t ActorCtx;
00066 uint8_t Led1Blnk = 0;
00067
00068
00069 volatile uint16_t TmoCounter = 0;
00070
00071
00072 volatile event_t TrxEvent;
00073 volatile uint8_t KeyEvent = 0;
00074 volatile uint8_t TmoEvent = 0;
00075
00076 volatile app_state_t TrxState;
00077
00078
00079
00080
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
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
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
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
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
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