/** * Author(s)...: Pashgan http://ChipEnable.Ru * Target(s)...: любой микроконтроллер mega * Compiler....: IAR 5.11A * Description.: Заготовка для событийной системы на таблицах * Data........: 30.09.12 */ #include "event-system.h" #include /* функция-заглушка */ static void EmptyFunc(void); /* кольцевой буфер */ static volatile es_event_t cycleBuf[SIZE_BUF]; static volatile uint8_t tailBuf = 0; static volatile uint8_t headBuf = 0; static volatile uint8_t countBuf = 0; static volatile es_state_t _State; typedef struct { es_state_t state; es_event_t event; es_state_t nextState; void (*pStateFunc1)(void); void (*pStateFunc2)(void); } table_state_t; /** таблица состояний */ const table_state_t stateTable[] PROGMEM = { /* STATE EVENT NEXT STATE STATE_FUNC1 STATE_FUNC2 */ /* show date, time */ {stShowTime, evBTN1Pressed, stShowMMSS, dotOnPersistent, showMMSS}, {stShowMMSS, evBTN1Pressed, stShowWDay, showWDay, dotOff}, {stShowWDay, evBTN1Pressed, stShowMDay, showMDay, dotOff}, {stShowMDay, evBTN1Pressed, stShowMon, showMonth, dotOff}, {stShowMon, evBTN1Pressed, stShowYear, showYear, dotOff}, #if (USE_BRIGHT_CONTROL == 1) {stShowYear, evBTN1Pressed, stShowBright, showBright, NULL}, {stShowBright, evBTN1Pressed, stShowTime, showTime, NULL}, #else {stShowYear, evBTN1Pressed, stShowTime, showTime, NULL}, #endif /* display wdt */ {stShowWDay, evDisplayWDT, stShowTime, showTime, NULL}, {stShowMDay, evDisplayWDT, stShowTime, showTime, NULL}, {stShowMon, evDisplayWDT, stShowTime, showTime, NULL}, {stShowYear, evDisplayWDT, stShowTime, showTime, NULL}, {stShowBright, evDisplayWDT, stShowTime, showTime, NULL}, /* refresh output */ {stShowTime, evNewSecond, stNoChange, showTime, NULL}, {stShowMMSS, evNewSecond, stNoChange, showMMSS, NULL}, {stShowWDay, evRefreshCal, stNoChange, showWDay, NULL}, {stShowMDay, evRefreshCal, stNoChange, showMDay, NULL}, {stShowMon, evRefreshCal, stNoChange, showMonth, NULL}, {stShowYear, evRefreshCal, stNoChange, showYear, NULL}, /* set time */ {stShowTime, evBTN1Holded, stSetHH, setTimeBegin, setHHBegin}, {stShowMMSS, evBTN1Holded, stSetHH, setTimeBegin, setMMBegin}, {stSetHH, evBTN1Pressed, stSetMM, setMMBegin, NULL}, {stSetMM, evBTN1Pressed, stSetHH, setHHBegin, NULL}, {stSetHH, evNewSecond, stNoChange, setTimeShow, NULL}, {stSetMM, evNewSecond, stNoChange, setTimeShow, NULL}, {stSetHH, evBTN1Holded, stShowTime, setTimeEnd, showTime}, {stSetMM, evBTN1Holded, stShowTime, setTimeEnd, showTime}, {stSetHH, evBTN3Pressed, stNoChange, setHHInc, setTimeShow}, {stSetHH, evBTN2Pressed, stNoChange, setHHDec, setTimeShow}, {stSetMM, evBTN3Pressed, stNoChange, setMMInc, setTimeShow}, {stSetMM, evBTN2Pressed, stNoChange, setMMDec, setTimeShow}, /* set calendar */ {stShowWDay, evBTN3Pressed, stNoChange, incWDay, showWDay}, {stShowMDay, evBTN3Pressed, stNoChange, incMDay, showMDay}, {stShowMon, evBTN3Pressed, stNoChange, incMonth, showMonth}, {stShowYear, evBTN3Pressed, stNoChange, incYear, showYear}, {stShowWDay, evBTN2Pressed, stNoChange, decWDay, showWDay}, {stShowMDay, evBTN2Pressed, stNoChange, decMDay, showMDay}, {stShowMon, evBTN2Pressed, stNoChange, decMonth, showMonth}, {stShowYear, evBTN2Pressed, stNoChange, decYear, showYear}, #if (USE_BRIGHT_CONTROL == 1) /* set bright */ {stShowBright, evBTN3Pressed, stNoChange, incBright, showBright}, {stShowBright, evBTN2Pressed, stNoChange, decBright, showBright}, #endif // USE_BRIGHT_CONTROL /* обязательная пустая строка таблицы */ {stNoChange, eventNull, stNoChange, EmptyFunc, EmptyFunc} }; /** * @brief Take event. * @param None * @retval Event */ es_event_t ES_GetEvent(void) { es_event_t event; if (countBuf > 0){ event = cycleBuf[headBuf]; countBuf--; headBuf = (headBuf + 1) & (SIZE_BUF - 1); return event; } return eventNull; } /** * @brief Place event. * @param Event * @retval None */ void ES_PlaceEvent(es_event_t event) { if (countBuf < SIZE_BUF){ cycleBuf[tailBuf] = event; tailBuf = (tailBuf + 1) & (SIZE_BUF - 1); countBuf++; /* сигнализация переполнения буфера событий */ // } else { // while(1); } } /** * @brief Initialize event system. * @param Start Event * @retval None */ void ES_Init(es_state_t init_state) { tailBuf = 0; headBuf = 0; countBuf = 0; _State = init_state; } /** * @brief Fake function. * @param None * @retval None */ static void EmptyFunc(void) { } /* макросы для чтения флэш памяти */ #define prb(data) pgm_read_byte(&(data)) #define prw(data) pgm_read_word(&(data)) /** * @brief Dispatcher of event system. * @param Event * @retval None */ void ES_Dispatch(es_event_t event) { uint8_t i; void (*pStateFunc1)(void); void (*pStateFunc2)(void); pStateFunc1 = NULL; pStateFunc2 = NULL; /* определяем следующее состояние */ for (i=0; prb(stateTable[i].state); i++) { /* если совпадают текущее состояние и поступившее событие */ if (prb(stateTable[i].state) == _State && prb(stateTable[i].event) == event) { /* меняем состояние если требуется */ if (prb(stateTable[i].nextState) != stNoChange) { _State = prb(stateTable[i].nextState); } /* получаем адреса функций */ pStateFunc1 = (void *)prw(stateTable[i].pStateFunc1); pStateFunc2 = (void *)prw(stateTable[i].pStateFunc2); break; } } if (pStateFunc1) pStateFunc1(); if (pStateFunc2) pStateFunc2(); } /** * @brief Return current state code. * @param None * @retval Event */ es_state_t ES_GetState(void) { return _State; } /** * @brief Set current state to given code . * @param Event * @retval None */ void ES_SetState(es_state_t new_state) { _State = new_state; }