-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.c
249 lines (197 loc) · 4.99 KB
/
app.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
/*
* app.c
*
* Application file for stroboscope
*
* Created on: 20 June 2014
* Author: james
*
* Target: ATMEGA328P
*/
/*
* Standard Library Includes
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
/*
* AVR Includes (Defines and Primitives)
*/
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
/*
* Utility Library Includes
*/
#include "util_macros.h"
#include "util_units.h"
/*
* Device Includes
*/
// None
/*
* Generic Library Includes
*/
#include "button.h"
/*
* AVR Library Includes
*/
#include "lib_clk.h"
#include "lib_io.h"
#include "lib_tmr8_tick.h"
#include "lib_tmr16_pwm.h"
#include "lib_encoder.h"
/*
* Local Application Includes
*/
#include "ui.h"
#include "strobe.h"
#include "app.h"
#include "app_test_harness.h"
/*
* Private Defines and Datatypes
*/
#define APP_TICK_MS 100
#define BLINK_TICK_MS 500
#define OUTPUT_COMPARE_1_PORT IO_PORTB
#define OUTPUT_COMPARE_1_PIN 1
/*
* Function Prototypes
*/
static void setupTimer(void);
static void setupIO(void);
static void applicationTick(void);
static void handleEncoderChange(int16_t change);
static inline void SetStrobe(void);
/*
* Private Variables
*/
static TMR8_TICK_CONFIG appTick;
static TMR8_TICK_CONFIG heartbeatTick;
static bool s_bSettingsChanged = false;
static STROBESETTINGS const * s_settings;
int main(void)
{
/* Disable watchdog: not required for this application */
MCUSR &= ~(1 << WDRF);
wdt_disable();
setupTimer();
setupIO();
UI_Init();
/* All processing interrupt based from here*/
DO_TEST_HARNESS_SETUP();
sei();
// Update display on first application tick
s_settings = Strobe_Init();
s_bSettingsChanged = true;
while (true)
{
DO_TEST_HARNESS_RUNNING();
UI_Tick();
if (TMR8_Tick_TestAndClear(&appTick))
{
applicationTick();
DO_TEST_HARNESS_TICK();
}
if (TMR8_Tick_TestAndClear(&heartbeatTick))
{
IO_Control(IO_PORTB, 5, IO_TOGGLE);
}
}
return 0;
}
/* APP_HalfFreq, APP_ThirdFreq, APP_DoubleFreq, APP_TrebleFreq
: Callbacks from the ui module for the half, third, double, treble buttons
: Redirects straight to strobe module
*/
void APP_HalfFreq() { s_settings = HalfFrequency(); s_bSettingsChanged = true;}
void APP_ThirdFreq() { s_settings = ThirdFrequency(); s_bSettingsChanged = true;}
void APP_DoubleFreq() { s_settings = DoubleFrequency(); s_bSettingsChanged = true;}
void APP_TrebleFreq() { s_settings = TrebleFrequency(); s_bSettingsChanged = true;}
/*
* Private Functions
*/
/* setupTimer, setupIO
: Once-only setup functions
*/
static void setupIO(void)
{
// Heartbeat LED
IO_SetMode(IO_PORTB, 5, IO_MODE_OUTPUT);
// Main strobe output
IO_SetMode(OUTPUT_COMPARE_1_PORT, OUTPUT_COMPARE_1_PIN, IO_MODE_OUTPUT);
}
static void setupTimer(void)
{
CLK_Init(0);
TMR8_Tick_Init(3, 0);
appTick.reload = APP_TICK_MS;
appTick.active = true;
TMR8_Tick_AddTimerConfig(&appTick);
heartbeatTick.reload = BLINK_TICK_MS;
heartbeatTick.active = true;
TMR8_Tick_AddTimerConfig(&heartbeatTick);
s_settings = GetSettings();
SetStrobe();
}
/* applicationTick
: Handles change of encoder by polling and sending to either
: UI (for display) or strobe (for parameter settings)
*/
static void applicationTick(void)
{
int encoderChange = ENC_GetMovement();
if (encoderChange)
{
if (!UI_EncoderButtonIsPressed())
{
// Encoder is controlling rpm/frequency or duty
handleEncoderChange(encoderChange);
}
else
{
// Encoder is moving cursor on display
UI_HandleEncoderChange(encoderChange);
}
}
if (s_bSettingsChanged)
{
s_bSettingsChanged = false;
UI_UpdateDisplay((s_settings->frequency + 5U) / 10U, s_settings->rpm, s_settings->duty);
SetStrobe();
}
}
/* handleEncoderChange
: Converts encoder movement to change in strobe paramter value.
: Passes that change in value to the strobe module.
: The change of duty/frequency/rpm is the place value of the digit multipled by the encoder movement.
*/
static void handleEncoderChange(int16_t change)
{
uint16_t multipliers[] = {1, 10, 100, 1000, 10000};
change *= multipliers[ UI_SelectedDigit() ];
switch (UI_SelectedLine())
{
case RPM:
s_settings = AlterRPM(change); // Each encoder tick is change of 1RPM * multiplier
break;
case FREQ:
s_settings = AlterFrequency(change * 10); // Each encoder tick is change of 10mHz * multiplier
break;
case DUTY:
s_settings = AlterDuty(change); // Each encoder tick is change of 1% * multiplier
break;
}
s_bSettingsChanged = true;
}
static inline void SetStrobe(void)
{
#ifndef TEST_HARNESS
TMR16_PWM_Set(s_settings->frequency, s_settings->duty, TMR_OCCHAN_A);
#else
TMR16_PWM_Set(s_settings->frequency, s_settings->duty, TMR_OCCHAN_A, TEST_HARNESS_TMR16_DEBUG_PTR());
#endif
}