sigmaN 0 9 июля, 2017 Опубликовано 9 июля, 2017 · Жалоба Всем привет! Сейчас сделано как-то так. Прекрасно работает, расширяется. Всем доволен, но хотелось бы сравнить с тру 8ми битным подходом. Собственно какую-нибудь хорошую реализацию конечного автомата и хотелось бы где-то посмотреть. enum DeviceEvents { DEVEV_HEARTBEAT, //this event occures every ~100ms DEVEV_STARTBTN_PRESSED, //etc... DEVEV_NO_EVENT = 0xff, } enum DeviceState_enum { DEVSTATE_OFF, DEVSTATE_LOCKED, //etc.... DEVSTATE_INVALID = 0xff, } //state interface class struct DeviceStateImplementation { virtual void EnterThisStateFrom( const DeviceState_enum &prevState ) = 0; //Handles event and returns new device state in response of event virtual DeviceState_enum HandleEvent( const DeviceEvents &event ) = 0; }; //Implementation of DEVSTATE_OFF state class StateImpl_OFF: public DeviceStateImplementation { timestamp_t MillisecondsCounter; uint8_t MinutesCounter; bool ReactOnStartBTNRelease; void ResetMillisecondsCounter(); public: virtual void EnterThisStateFrom( const DeviceState_enum &prevState ); virtual DeviceState_enum HandleEvent( const DeviceEvents &event ); }; //Implementation of DEVSTATE_OFF state void StateImpl_OFF::EnterThisStateFrom( const DeviceState_enum &prevState ) { TurnOffAllOutputs(); DisableRPMMeasure(); G_SettingsStateSelector.ResetPressCounter(); ReactOnStartBTNRelease = false; ResetMillisecondsCounter(); } void StateImpl_OFF::ResetMillisecondsCounter() { MillisecondsCounter = GetTickCount(); MinutesCounter = 0; } DeviceState_enum StateImpl_OFF::HandleEvent( const DeviceEvents &event ) { DeviceState_enum retval = DEVSTATE_OFF; switch(event) { case DEVEV_HEARTBEAT: ACC_LEDBlinker.DoTheJob(); if( G_SettingsStateSelector.GetSelectedState() != DEVSTATE_INVALID ) { ACC_LEDBlinker.StartEndlessBlinkSequence(100, 100);//fast blinking indicating some settings mode was selected } break; case DEVEV_STARTBTN_PRESSED: ReactOnStartBTNRelease = true; break; case DEVEV_STARTBTN_RELEASED: //react on release only if press also was made in this state if( ReactOnStartBTNRelease ) { ResetMillisecondsCounter(); if( GlobalVarsRef.BrakePedal.GetButtonState() == GPIOBTNSTATE_PUSHED ) { DeviceState_enum SelectedSettingsModeState = G_SettingsStateSelector.GetSelectedState(); if( SelectedSettingsModeState != DEVSTATE_INVALID ) retval = SelectedSettingsModeState; else retval = DEVSTATE_CRANKING; } else { retval = DEVSTATE_IGNON; } } break; case DEVEV_STARTBTN_LONGPRESS: if( GlobalVarsRef.BrakePedal.GetButtonState() == GPIOBTNSTATE_PUSHED ) retval = DEVSTATE_FORCEDCRANKING; else retval = DEVSTATE_ACCON; break; case DEVEV_BREAKPEDAL_PRESSED: ResetMillisecondsCounter(); G_SettingsStateSelector.SelectorWasPressed(); ACC_LED::Clear(); ACC_LEDBlinker.StartBlinkSequence(2, 50, 100); break; case DEVEV_BREAKPEDAL_RELEASED: ACC_LED::Clear(); ACC_LEDBlinker.AbortBlinkSequence(); break; case DEVEV_ENGINE_STARTED: retval = DEVSTATE_RUNNING; break; case DEVEV_ENGINE_STALLED: break; } return retval; } /////main state machine implementation class MainStateMachine { public: void EnterStateForced( const DeviceState_enum &state ); void ProcessEvent( const DeviceEvents &evnt ); private: DeviceStateImplementation *CurrentDevStateImplementation; //<----pointer to state interface class DeviceState_enum CurrentDevState; void SetNewDeviceState( const DeviceState_enum &newDevState ); }; void MainStateMachine::ProcessEvent( const DeviceEvents &evnt ) { DeviceState_enum newDevState = CurrentDevStateImplementation->HandleEvent( evnt ); if( newDevState != CurrentDevState ) SetNewDeviceState( newDevState ); } void MainStateMachine::SetNewDeviceState( const DeviceState_enum &newDevState ) { switch( newDevState ) { case DEVSTATE_OFF: CurrentDevStateImplementation = &OFFState; break; case DEVSTATE_LOCKED: CurrentDevStateImplementation = &LockedState; break; } CurrentDevStateImplementation->EnterThisStateFrom( CurrentDevState ); CurrentDevState = newDevState; } //main loop simplifiyed int main() { while(1) { event = DEVEV_HEARTBEAT; while( event != DEVEV_NO_EVENT ) { MainStateMachine.ProcessEvent( event ); event = DetectOneMoreEvents(); } } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 9 июля, 2017 Опубликовано 9 июля, 2017 · Жалоба Всем доволен, но хотелось бы сравнить с тру 8ми битным подходом. Собственно какую-нибудь хорошую реализацию конечного автомата и хотелось бы где-то посмотреть. В ИТМО есть Шалыто А.А. И у них есть сайт со статьями по "switch-тенологиям"... is.ifmo.ru Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 9 июля, 2017 Опубликовано 9 июля, 2017 · Жалоба iosifk, спасибо, кажется нашел пдфку с которой стоит начать http://is.ifmo.ru/books/_book.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 9 июля, 2017 Опубликовано 9 июля, 2017 · Жалоба iosifk, спасибо, кажется нашел пдфку с которой стоит начать http://is.ifmo.ru/books/_book.pdf Еще в КиТ, в архиве статей 2006-11 и до 2007-8 статьи, автор Татарчевский... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба Всем доволен, но хотелось бы сравнить с тру 8ми битным подходом. Собственно какую-нибудь хорошую реализацию конечного автомата и хотелось бы где-то посмотреть. Биты то при чем? Реализация автомата - дело интимное. При реализации UI как автомата параметры такие: - состояний - около сотни - событий - два десятка (кнопки и таймеры) - новое состояние определяется внутри обработки конкретного состояния (т.к. не все, что происходит и изменяет состояния - это события) - изменение состояния - тоже событие (удобно для единообразия) - Х-макросы для перечисления имен функций, названий состояний, текста в первой строке, особенностей поддержки каждого состояния (например, чистить или нет экран) - механизм возврата в предыдущее состояние Очень важная для меня цель была - прозрачность понимания, т.к. приходится корректировать проекты после большого перерыва. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба Биты при том, что при моей нынешней реализации(которую я вкратце привел) У меня при всём удобстве в редактировании и расширении маленько так сожрало и флэша и памяти. Труды Шалыто А.А. я конечно изучу, полезно будет по любому, но думал может ещё народ скинет разных исходников "на посмотреть". Может есть что-то готовое и красиво реализованное, например как protothreads, где switch красиво обыгран макросами или я не знаю... Реализацию табличного какого-нибудь подхода глянуть. И именно 8ми битный контроллер был обозначен для того, чтоб не приводили полномасштабных вариантов с UI Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба Биты при том, что при моей нынешней реализации(которую я вкратце привел) У меня при всём удобстве в редактировании и расширении маленько так сожрало и флэша и памяти. И именно 8ми битный контроллер был обозначен для того, чтоб не приводили полномасштабных вариантов с UI UI - это не GUI, это всего лишь дисплей 2х16, 4 кнопки и STM8. Давайте адрес почты, пришлю файлов, но не весь проект. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба Спасибо, будет интересно посмотреть! altersoft mail.ru Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба iosifk, спасибо, кажется нашел пдфку с которой стоит начать http://is.ifmo.ru/books/_book.pdf Хм. Читать осторожно - у неподготовленного читателя может вызвать взрыв мозга. :) Что касается автоматов на МК с минимумум ресурсов (будем так называть '8ми битные контролеры') то тут явно напрашивается нечто на голом С либо в виде большого switch, либо таблицей переходов (в зависимости от количества состояний, переходов и архитектуры самого МК). А что бы не было 'мучительно больно' это все поддерживать (как минимум модифицировать) напрашивается какой нибудь генератор (либо из готовых, что были упомянуты в статье, либо что нибудь самописное на каком нибудь Perl'е или Python'е) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба Что касается автоматов на МК с минимумум ресурсов (будем так называть '8ми битные контролеры') то тут явно напрашивается нечто на голом С либо в виде большого switch, либо таблицей переходов Вот на исходнички чего-нибудь такого и было бы интересно посмотреть. В частности интересно реализовать одинаковые автоматы двумя разными способами и сравнить их по быстродействию/занимаемой памяти.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба либо в виде большого switch, либо таблицей переходов уже десять лет назад IAR AVR делал таблицу из большого свича на высоких уровнях оптимизации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 10 июля, 2017 Опубликовано 10 июля, 2017 · Жалоба Вот дойдут как-нибудь руки до сравнений и будет интересно посмотреть на результаты. Так то в моей текущей реализации вызов обработчика событий идет через указатель CurrentDevStateImplementation, который является указателем на интерфейс класса, хотя записан туда адрес конкретной реализации. Что при вызове метода через этот указатель ВНЕЗАПНО приводит к использованию vtable https://ru.wikipedia.org/wiki/%D0%A2%D0%B0%...%B4%D0%BE%D0%B2 В связи с чем и становится интересно, а будет ли реальная экономия хоть чего-нибудь если все эти состояния положить в огромный switch, который потом IAR доблестно превратит в таблицу с адресами функций... Что в итоге будет снова ооочень напоминать vtable ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 26 11 июля, 2017 Опубликовано 11 июля, 2017 · Жалоба . . . В связи с чем и становится интересно, а будет ли реальная экономия хоть чего-нибудь если все эти состояния положить в огромный switch, который потом IAR доблестно превратит в таблицу с адресами функций... Что в итоге будет снова ооочень напоминать vtable ) Смотря как компилятором реализуется работа vtable и какая "вложенность". Если использовать правильный switch (опятьже зависит от комилятора) который генерирует "вычисляемые" переходы. "правильный" - это в IAR конструкция switch ( __even_in_range(TBIV, 14) ) { ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 11 июля, 2017 Опубликовано 11 июля, 2017 · Жалоба Dog Pawlowa, можно тоже исходники глянуть? [email protected] А то как не крути вечно такой колхоз получается (Передача пакета данных по usart) void Sendpackage(void){ static uint8_t mode; static uint16_t counter; uint8_t* Data; switch(mode){ case 0:{ //--------------------------------------------- //--------Ожидание команды на отправку--------- //--------------------------------------------- if(TransmitDataStart==Transmit_START){ TransmitDataStart=Transmit_STOP; Data=&Protocol; mode=1; } break; } //------------------------------------------------- case 1:{ if(counter<sizeof(ProtocolExchange_t)){ if(USART3->SR & USART_SR_TC){ USART3->DR =(uint8_t)Data[counter]; counter++; } }else{ mode=0; } break; } //------------------------------------------------- } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 11 июля, 2017 Опубликовано 11 июля, 2017 · Жалоба Смотря как компилятором реализуется работа vtable и какая "вложенность". Ну "вложенность" получается 1. Указатель на абстрактный класс указывает на реализацию класса. Про __even_in_range() не знал, протестируем Add: Последний IAR STM8 Error[Pe020]: identifier "__even_in_range" is undefined main.cpp 140 :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться