-
Notifications
You must be signed in to change notification settings - Fork 0
/
sm_dimmer.c
277 lines (236 loc) · 9.38 KB
/
sm_dimmer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/***************************************************************************//**
* @file sm_dimmer.c
*******************************************************************************/
#include "Arduino.h"
#include "sm_dimmer.h"
// Typedefs ====================================================================
struct DIMMER_SM_st {
STATE_MACHINE sm;
uint32_t Events;
uint16_t Timer;
};
typedef struct DIMMER_SM_st DIMMER_SM;
typedef void DIMMER_STATE_FUNC (DIMMER_SM* me, uint16_t event);
// Local variables =============================================================
static DIMMER_SM DSM;
#define DEFINE_MY_OBJECT() DIMMER_SM* const me = &DSM;
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define LedPwm_pin 1
#define LedExtra_pin 2
#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__)
#define LedPwm_pin 12
#define LedExtra_pin 11
#else
#error Unknown CPU: provide code for your CPU
#endif
#define LED_PWM_DIMMED 64
const uint16_t TholdDim = 1500 / 10; // [10ms]
const uint16_t ToutExtra = 5000 / 10; // [10ms]
const uint16_t ToutLongSw = 1500 / 10; // [10ms]
// Local function declarations =================================================
static void DimmerSt_LedOff(DIMMER_SM* me, uint16_t event);
static void DimmerSt_StartDim(DIMMER_SM* me, uint16_t event);
static void DimmerSt_Dimmed(DIMMER_SM* const me, uint16_t event);
static void DimmerSt_NormalStart(DIMMER_SM* const me, uint16_t event);
static void DimmerSt_NormalBright(DIMMER_SM* const me, uint16_t event);
static void DimmerSt_ExtraBright(DIMMER_SM* const me, uint16_t event);
// Function definitions ========================================================
static inline void Led_SetPwm(uint8_t pwm) { OCR1A = ~pwm; }
static inline void LedExtra_On() { digitalWrite(LedExtra_pin, HIGH); }
static inline void LedExtra_Off() { digitalWrite(LedExtra_pin, LOW); }
//u @startuml
//u skinparam defaultTextAlignment left
//u state DimmerSM {
/***************************************************************************//**
* @brief Initialize state machine
*******************************************************************************/
void DimmerSM_Init() {
DEFINE_MY_OBJECT();
Led_SetPwm(0); // LED switch off
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
TCCR1 = 1<<PWM1A | 3<<COM1A0 | 1<<CS10; // Timer1: PWM mode
#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__)
TCCR1A = 3<<COM1A0 | 1<<WGM10; // Timer1: fast PWM 8bit, clr at top
TCCR1B = 1<<WGM12 | 1<<CS10; // Timer1 start, presc:/1
#else
#error Unknown CPU: provide code for Timer1 PWM setting
#endif
pinMode(LedPwm_pin, OUTPUT);
pinMode(LedExtra_pin, OUTPUT);
me->Events = 0;
StateMachineInit(&me->sm, (SM_STATE_FUNC*)&DimmerSt_LedOff); //u [*] -left-> LedOff
}
/***************************************************************************//**
* @brief Execute event handler
*******************************************************************************/
void DimmerSM_EventProc (uint16_t event) {
DEFINE_MY_OBJECT();
StateMachine((STATE_MACHINE*)me, event);
}
/***************************************************************************//**
* @brief Check and execute asynchron event (from event buffer)
*******************************************************************************/
void DimmerSM_CheckEvent (void) {
DEFINE_MY_OBJECT();
if (me->Events) {
uint32_t mask = 1;
uint8_t ev;
for (ev = 0; ev < 32; ev++) {
if (me->Events & mask) {
me->Events &= ~mask;
StateMachine((STATE_MACHINE*)me, ev);
break;
}
mask <<= 1; // shift left
}
}
}
/***************************************************************************//**
* @brief Send (asynchron) event to state machine
*******************************************************************************/
static inline void EventSend (DIMMER_SM* const me, uint16_t event) {
me->Events |= (1 << event);
}
// State definitions ===========================================================
//u state LedOff {
/***************************************************************************//**
* @brief LEDs switched off
*******************************************************************************/
void DimmerSt_LedOff(DIMMER_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u LedOff: entry:
Led_SetPwm(0); //u LedOff: LED PWM: 0%
}break;
case EV_STATE_EXIT: {
}break;
case EV_DSM_SW1_PRESS:
case EV_DSM_SW2_PRESS: {
SM_SET_STATE(&DimmerSt_StartDim); //u LedOff -left-> StartDim : push SW1\nor SW2
}break;
}
}
//u }
//u state Delay1
//u state StartDim {
/***************************************************************************//**
* @brief LED start dimmed
*******************************************************************************/
void DimmerSt_StartDim(DIMMER_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u StartDim: entry:
me->Timer = 0; //u StartDim: t start
Led_SetPwm(LED_PWM_DIMMED); //u StartDim: LED PWM: dimmed
}break;
case EV_STATE_EXIT: {
}break;
case EV_DSM_SW1_REL:
case EV_DSM_SW2_REL: {
SM_SET_STATE(&DimmerSt_NormalStart); //u StartDim --> NormalStart : release\nSW1 or SW2
}break;
case EV_DSM_TICK_10MS: {
if (++me->Timer > TholdDim) { //u StartDim -up-> Delay1 : t>TholdDim
SM_SET_STATE_DELAYED(&DimmerSt_Dimmed, 200/10); //u Delay1 -> Dimmed
Led_SetPwm(0); //u Delay1: LED PWM: 0%
}
}break;
}
}
//u }
//u state Dimmed {
/***************************************************************************//**
* @brief LED Dimmed
*******************************************************************************/
void DimmerSt_Dimmed(DIMMER_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u Dimmed: entry:
Led_SetPwm(LED_PWM_DIMMED); //u Dimmed: LED PWM: dimmed
}break;
case EV_STATE_EXIT: {
}break;
case EV_DSM_SW1_PRESS:
case EV_DSM_SW2_PRESS: {
SM_SET_STATE(&DimmerSt_LedOff); //u Dimmed --> LedOff : push SW1\nor SW2
}break;
}
}
//u }
//u state NormalStart {
/***************************************************************************//**
* @brief LED normal brightness start phase
*******************************************************************************/
void DimmerSt_NormalStart(DIMMER_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u NormalStart: entry:
me->Timer = 0; //u NormalStart: t start
Led_SetPwm(255); //u NormalStart: LED PWM: 100%
}break;
case EV_STATE_EXIT: {
}break;
case EV_DSM_SW1_PRESS: {
SM_SET_STATE(&DimmerSt_LedOff); //u NormalStart -up-> LedOff : push\nSW1
}break;
case EV_DSM_SW2_PRESS: {
SM_SET_STATE(&DimmerSt_ExtraBright); //u NormalStart --> ExtraBright : push\nSW2
}break;
case EV_DSM_TICK_10MS: {
if (++me->Timer > ToutExtra) {
SM_SET_STATE(&DimmerSt_NormalBright); //u NormalStart -> NormalBright : t>ToutExtra
}
}break;
}
}
//u }
//u state NormalBright {
/***************************************************************************//**
* @brief LED normal brightness
*******************************************************************************/
void DimmerSt_NormalBright(DIMMER_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u NormalBright: entry:
me->Timer = 0; //u NormalBright: t stop
}break; //u NormalBright:
case EV_STATE_EXIT: {
}break;
case EV_DSM_SW1_PRESS: {
SM_SET_STATE(&DimmerSt_LedOff); //u NormalBright -up-> LedOff : push\nSW1
}break;
case EV_DSM_SW2_PRESS: {
me->Timer++; //u NormalBright: push SW2: t start
}break;
case EV_DSM_SW2_REL: {
SM_SET_STATE(&DimmerSt_LedOff); //u NormalBright -up-> LedOff : release\nSW2
}break;
case EV_DSM_TICK_10MS: {
if (me->Timer) { // timer running
if (++me->Timer > ToutLongSw) { // expired timeout for key long pressing
SM_SET_STATE(&DimmerSt_ExtraBright); //u NormalBright --> ExtraBright : t>ToutLongSw
}
}
}break;
}
}
//u }
//u state ExtraBright {
/***************************************************************************//**
* @brief LED extra brightness
*******************************************************************************/
void DimmerSt_ExtraBright(DIMMER_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u ExtraBright: entry:
me->Timer = 0;
LedExtra_On(); //u ExtraBright: extra LED on
}break; //u ExtraBright:
case EV_STATE_EXIT: { //u ExtraBright: exit:
LedExtra_Off(); //u ExtraBright: extra LED on
}break;
case EV_DSM_SW1_PRESS:
case EV_DSM_SW2_PRESS: {
SM_SET_STATE(&DimmerSt_LedOff); //u ExtraBright -up-> LedOff : push SW1\nor SW2
}break;
case EV_DSM_TICK_10MS: {
}break;
}
}
//u }
//u }
//u @enduml