Rev 2263 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2263 | tk | 1 | // $Id: app.c 2425 2016-11-03 00:44:22Z tk $ |
2 | /* |
||
3 | * MIOS32 Application Template |
||
4 | * |
||
5 | * ========================================================================== |
||
6 | * |
||
7 | * Copyright (C) <year> <your name> (<your email address>) |
||
8 | * Licensed for personal non-commercial use only. |
||
9 | * All other rights reserved. |
||
10 | * |
||
11 | * ========================================================================== |
||
12 | */ |
||
13 | |||
14 | ///////////////////////////////////////////////////////////////////////////// |
||
15 | // Include files |
||
16 | ///////////////////////////////////////////////////////////////////////////// |
||
17 | |||
18 | #include <mios32.h> |
||
19 | #include "app.h" |
||
20 | #include <blm_scalar_master.h> |
||
21 | |||
22 | // FreeRTOS |
||
23 | #include <FreeRTOS.h> |
||
24 | #include <portmacro.h> |
||
25 | #include <task.h> |
||
26 | #include <queue.h> |
||
27 | #include <semphr.h> |
||
28 | |||
29 | |||
30 | ///////////////////////////////////////////////////////////////////////////// |
||
31 | // FreeRTOS tasks and semaphores |
||
32 | ///////////////////////////////////////////////////////////////////////////// |
||
33 | |||
34 | // this semaphore (resp. mutex) ensures exclusive access to the MIDI Out port |
||
35 | xSemaphoreHandle xMIDIOUTSemaphore; |
||
36 | |||
37 | // simplify access to this mutex |
||
38 | #define MUTEX_MIDIOUT_TAKE { TASKS_MUTEX_MIDIOUT_Take(); } |
||
39 | #define MUTEX_MIDIOUT_GIVE { TASKS_MUTEX_MIDIOUT_Give(); } |
||
40 | |||
41 | // periodic task |
||
42 | static void TASK_Period1mS(void *pvParameters); |
||
43 | #define PRIORITY_TASK_PERIOD1MS ( tskIDLE_PRIORITY + 2 ) // lower than MIDI |
||
44 | |||
45 | |||
46 | ///////////////////////////////////////////////////////////////////////////// |
||
47 | // Local functions |
||
48 | ///////////////////////////////////////////////////////////////////////////// |
||
49 | static s32 APP_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in); |
||
50 | static s32 APP_MIDI_TimeOut(mios32_midi_port_t port); |
||
51 | |||
52 | static s32 APP_BLM_ButtonCallback(u8 blm, blm_scalar_master_element_t element_type, u8 button_x, u8 button_y, u8 button_depressed); |
||
53 | static s32 APP_BLM_FaderCallback(u8 blm, u8 fader, u8 value); |
||
54 | |||
55 | |||
56 | ///////////////////////////////////////////////////////////////////////////// |
||
57 | // This hook is called after startup to initialize the application |
||
58 | ///////////////////////////////////////////////////////////////////////////// |
||
59 | void APP_Init(void) |
||
60 | { |
||
61 | u8 blm = 0; // currently only a single blm device is supported |
||
62 | |||
63 | // create semaphores |
||
64 | xMIDIOUTSemaphore = xSemaphoreCreateRecursiveMutex(); |
||
65 | |||
66 | // initialize all LEDs |
||
67 | MIOS32_BOARD_LED_Init(0xffffffff); |
||
68 | |||
69 | // initialize BLM_SCALAR_MASTER communication handler |
||
70 | BLM_SCALAR_MASTER_Init(0); |
||
71 | |||
72 | // install BLM callbacks |
||
73 | BLM_SCALAR_MASTER_ButtonCallback_Init(APP_BLM_ButtonCallback); |
||
74 | BLM_SCALAR_MASTER_FaderCallback_Init(APP_BLM_FaderCallback); |
||
75 | |||
76 | // set MIDI port (change here if your MBHP_BLM_SCALAR is connected to a different port) |
||
77 | BLM_SCALAR_MASTER_MIDI_PortSet(blm, UART2); // == IN3/OUT3 |
||
78 | |||
79 | // install SysEx callback |
||
80 | MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser); |
||
81 | |||
82 | // install timeout callback function |
||
83 | MIOS32_MIDI_TimeOutCallback_Init(APP_MIDI_TimeOut); |
||
84 | |||
85 | // start tasks |
||
2425 | tk | 86 | xTaskCreate(TASK_Period1mS, "Period1mS", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD1MS, NULL); |
2263 | tk | 87 | |
88 | // send layout request to MBHP_BLM_SCALAR |
||
89 | BLM_SCALAR_MASTER_SendRequest(blm, 0x00); |
||
90 | } |
||
91 | |||
92 | |||
93 | ///////////////////////////////////////////////////////////////////////////// |
||
94 | // This task is running endless in background |
||
95 | ///////////////////////////////////////////////////////////////////////////// |
||
96 | void APP_Background(void) |
||
97 | { |
||
98 | } |
||
99 | |||
100 | |||
101 | ///////////////////////////////////////////////////////////////////////////// |
||
102 | // This hook is called each mS from the main task which also handles DIN, ENC |
||
103 | // and AIN events. You could add more jobs here, but they shouldn't consume |
||
104 | // more than 300 uS to ensure the responsiveness of buttons, encoders, pots. |
||
105 | // Alternatively you could create a dedicated task for application specific |
||
106 | // jobs as explained in $MIOS32_PATH/apps/tutorials/006_rtos_tasks |
||
107 | ///////////////////////////////////////////////////////////////////////////// |
||
108 | void APP_Tick(void) |
||
109 | { |
||
110 | u8 blm = 0; // currently only a single blm device is supported |
||
111 | static blm_scalar_master_connection_state_t prev_connection_state = BLM_SCALAR_MASTER_CONNECTION_STATE_IDLE; |
||
112 | blm_scalar_master_connection_state_t connection_state = BLM_SCALAR_MASTER_ConnectionStateGet(blm); |
||
113 | |||
114 | // print message on connection change and turn on/off the status LED |
||
115 | if( connection_state != prev_connection_state ) { |
||
116 | prev_connection_state = connection_state; |
||
117 | |||
118 | if( connection_state == BLM_SCALAR_MASTER_CONNECTION_STATE_IDLE ) { |
||
119 | MUTEX_MIDIOUT_TAKE; |
||
120 | MIOS32_MIDI_SendDebugMessage("BLM has been disconnected."); // will appear ca. 10 seconds after communication is broken |
||
121 | MIOS32_BOARD_LED_Set(1, 0); |
||
122 | MUTEX_MIDIOUT_GIVE; |
||
123 | } else { |
||
124 | MUTEX_MIDIOUT_TAKE; |
||
125 | MIOS32_MIDI_SendDebugMessage("BLM has been connected."); // will appear ca. 5 seconds after BLM has been connected |
||
126 | MIOS32_MIDI_SendDebugMessage("Reported grid layout: %dx%d with %d colours.", BLM_SCALAR_MASTER_NumColumnsGet(blm), BLM_SCALAR_MASTER_NumRowsGet(blm), BLM_SCALAR_MASTER_NumColoursGet(blm)); |
||
127 | MIOS32_BOARD_LED_Set(1, 1); |
||
128 | MUTEX_MIDIOUT_GIVE; |
||
129 | } |
||
130 | } |
||
131 | } |
||
132 | |||
133 | |||
134 | ///////////////////////////////////////////////////////////////////////////// |
||
135 | // This hook is called each mS from the MIDI task which checks for incoming |
||
136 | // MIDI events. You could add more MIDI related jobs here, but they shouldn't |
||
137 | // consume more than 300 uS to ensure the responsiveness of incoming MIDI. |
||
138 | ///////////////////////////////////////////////////////////////////////////// |
||
139 | void APP_MIDI_Tick(void) |
||
140 | { |
||
141 | } |
||
142 | |||
143 | |||
144 | ///////////////////////////////////////////////////////////////////////////// |
||
145 | // This hook is called when a MIDI package has been received |
||
146 | ///////////////////////////////////////////////////////////////////////////// |
||
147 | void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) |
||
148 | { |
||
149 | // forward to BLM master |
||
150 | BLM_SCALAR_MASTER_MIDI_Receive(port, midi_package); |
||
151 | } |
||
152 | |||
153 | |||
154 | ///////////////////////////////////////////////////////////////////////////// |
||
155 | // This function parses an incoming sysex stream for MIOS32 commands |
||
156 | ///////////////////////////////////////////////////////////////////////////// |
||
157 | static s32 APP_SYSEX_Parser(mios32_midi_port_t port, u8 midi_in) |
||
158 | { |
||
159 | // forward SysEx to BLM MASTER |
||
160 | BLM_SCALAR_MASTER_SYSEX_Parser(port, midi_in); |
||
161 | |||
162 | return 0; // no error |
||
163 | } |
||
164 | |||
165 | |||
166 | ///////////////////////////////////////////////////////////////////////////// |
||
167 | // This function parses an incoming sysex stream for MIOS32 commands |
||
168 | ///////////////////////////////////////////////////////////////////////////// |
||
169 | static s32 APP_MIDI_TimeOut(mios32_midi_port_t port) |
||
170 | { |
||
171 | // forward timeout to BLM MASTER |
||
172 | BLM_SCALAR_MASTER_MIDI_TimeOut(port); |
||
173 | |||
174 | return 0; // no error |
||
175 | } |
||
176 | |||
177 | |||
178 | ///////////////////////////////////////////////////////////////////////////// |
||
179 | // This function is called when a BLM button has been pressed/depressed |
||
180 | ///////////////////////////////////////////////////////////////////////////// |
||
181 | static s32 APP_BLM_ButtonCallback(u8 blm, blm_scalar_master_element_t element_id, u8 button_x, u8 button_y, u8 button_depressed) |
||
182 | { |
||
183 | // for demo purposes we implemented following: |
||
184 | // - message will be print whenever a button has been pressed |
||
185 | // later you want to remove these messages from your application, because they consume time! |
||
186 | // - button toggles between green and off |
||
187 | // - if SHIFT button is pressed, the button toggles between red and off |
||
188 | // - the SHIFT button toggles between yellow and off |
||
189 | |||
190 | // the BLM_SCALAR driver doesn't store the button state, but we can retrieve it with the colour |
||
191 | u8 shift_button_pressed = BLM_SCALAR_MASTER_LED_Get(blm, BLM_SCALAR_MASTER_ELEMENT_SHIFT, 0, 0) == BLM_SCALAR_MASTER_COLOUR_YELLOW; |
||
192 | |||
193 | // current colour |
||
194 | blm_scalar_master_colour_t colour = BLM_SCALAR_MASTER_LED_Get(blm, element_id, button_x, button_y); |
||
195 | |||
196 | // set new colour |
||
197 | if( element_id == BLM_SCALAR_MASTER_ELEMENT_SHIFT ) { |
||
198 | blm_scalar_master_colour_t new_colour = button_depressed ? BLM_SCALAR_MASTER_COLOUR_OFF : BLM_SCALAR_MASTER_COLOUR_YELLOW; |
||
199 | BLM_SCALAR_MASTER_LED_Set(blm, element_id, button_x, button_y, new_colour); |
||
200 | } else { |
||
201 | if( !button_depressed ) { |
||
202 | blm_scalar_master_colour_t new_colour = BLM_SCALAR_MASTER_COLOUR_OFF; |
||
203 | if( colour != BLM_SCALAR_MASTER_COLOUR_OFF ) { |
||
204 | new_colour = BLM_SCALAR_MASTER_COLOUR_OFF; |
||
205 | } else { |
||
206 | new_colour = shift_button_pressed ? BLM_SCALAR_MASTER_COLOUR_RED : BLM_SCALAR_MASTER_COLOUR_GREEN; |
||
207 | } |
||
208 | |||
209 | BLM_SCALAR_MASTER_LED_Set(blm, element_id, button_x, button_y, new_colour); |
||
210 | } |
||
211 | } |
||
212 | |||
213 | |||
214 | // print messages for debugging purposes |
||
215 | switch( element_id ) { |
||
216 | case BLM_SCALAR_MASTER_ELEMENT_GRID: { |
||
217 | MUTEX_MIDIOUT_TAKE; |
||
218 | MIOS32_MIDI_SendDebugMessage("BLM Grid Button x=%d y=%d %s\n", button_x, button_y, button_depressed ? "depressed" : "pressed"); |
||
219 | MUTEX_MIDIOUT_GIVE; |
||
220 | } break; |
||
221 | |||
222 | case BLM_SCALAR_MASTER_ELEMENT_EXTRA_ROW: { |
||
223 | MUTEX_MIDIOUT_TAKE; |
||
224 | MIOS32_MIDI_SendDebugMessage("BLM Extra Row Button: x=%d y=%d %s\n", button_x, button_y, button_depressed ? "depressed" : "pressed"); |
||
225 | MUTEX_MIDIOUT_GIVE; |
||
226 | } break; |
||
227 | |||
228 | case BLM_SCALAR_MASTER_ELEMENT_EXTRA_COLUMN: { |
||
229 | MUTEX_MIDIOUT_TAKE; |
||
230 | MIOS32_MIDI_SendDebugMessage("BLM Extra Column Button: x=%d y=%d %s\n", button_x, button_y, button_depressed ? "depressed" : "pressed"); |
||
231 | MUTEX_MIDIOUT_GIVE; |
||
232 | } break; |
||
233 | |||
234 | case BLM_SCALAR_MASTER_ELEMENT_SHIFT: { |
||
235 | MUTEX_MIDIOUT_TAKE; |
||
236 | MIOS32_MIDI_SendDebugMessage("BLM Shift Button: x=%d y=%d %s\n", button_x, button_y, button_depressed ? "depressed" : "pressed"); |
||
237 | MUTEX_MIDIOUT_GIVE; |
||
238 | } break; |
||
239 | |||
240 | default: |
||
241 | return -1; // unexpected element_id |
||
242 | } |
||
243 | |||
244 | return 0; // no error |
||
245 | } |
||
246 | |||
247 | ///////////////////////////////////////////////////////////////////////////// |
||
248 | // This function is called when a BLM fader has been moved |
||
249 | ///////////////////////////////////////////////////////////////////////////// |
||
250 | static s32 APP_BLM_FaderCallback(u8 blm, u8 fader, u8 value) |
||
251 | { |
||
252 | // just forward as CC event |
||
253 | MUTEX_MIDIOUT_TAKE; |
||
254 | MIOS32_MIDI_SendCC(DEFAULT, fader, 1, value); |
||
255 | MUTEX_MIDIOUT_GIVE; |
||
256 | |||
257 | return 0; // no error |
||
258 | } |
||
259 | |||
260 | |||
261 | ///////////////////////////////////////////////////////////////////////////// |
||
262 | // This hook is called before the shift register chain is scanned |
||
263 | ///////////////////////////////////////////////////////////////////////////// |
||
264 | void APP_SRIO_ServicePrepare(void) |
||
265 | { |
||
266 | } |
||
267 | |||
268 | |||
269 | ///////////////////////////////////////////////////////////////////////////// |
||
270 | // This hook is called after the shift register chain has been scanned |
||
271 | ///////////////////////////////////////////////////////////////////////////// |
||
272 | void APP_SRIO_ServiceFinish(void) |
||
273 | { |
||
274 | } |
||
275 | |||
276 | |||
277 | ///////////////////////////////////////////////////////////////////////////// |
||
278 | // This hook is called when a button has been toggled |
||
279 | // pin_value is 1 when button released, and 0 when button pressed |
||
280 | ///////////////////////////////////////////////////////////////////////////// |
||
281 | void APP_DIN_NotifyToggle(u32 pin, u32 pin_value) |
||
282 | { |
||
283 | } |
||
284 | |||
285 | |||
286 | ///////////////////////////////////////////////////////////////////////////// |
||
287 | // This hook is called when an encoder has been moved |
||
288 | // incrementer is positive when encoder has been turned clockwise, else |
||
289 | // it is negative |
||
290 | ///////////////////////////////////////////////////////////////////////////// |
||
291 | void APP_ENC_NotifyChange(u32 encoder, s32 incrementer) |
||
292 | { |
||
293 | } |
||
294 | |||
295 | |||
296 | ///////////////////////////////////////////////////////////////////////////// |
||
297 | // This hook is called when a pot has been moved |
||
298 | ///////////////////////////////////////////////////////////////////////////// |
||
299 | void APP_AIN_NotifyChange(u32 pin, u32 pin_value) |
||
300 | { |
||
301 | } |
||
302 | |||
303 | |||
304 | ///////////////////////////////////////////////////////////////////////////// |
||
305 | // This task is called periodically each mS |
||
306 | ///////////////////////////////////////////////////////////////////////////// |
||
307 | static void TASK_Period1mS(void *pvParameters) |
||
308 | { |
||
309 | portTickType xLastExecutionTime; |
||
310 | |||
311 | // Initialise the xLastExecutionTime variable on task entry |
||
312 | xLastExecutionTime = xTaskGetTickCount(); |
||
313 | |||
314 | while( 1 ) { |
||
315 | vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS); |
||
316 | |||
317 | // skip delay gap if we had to wait for more than 5 ticks to avoid |
||
318 | // unnecessary repeats until xLastExecutionTime reached xTaskGetTickCount() again |
||
319 | portTickType xCurrentTickCount = xTaskGetTickCount(); |
||
320 | if( xLastExecutionTime < (xCurrentTickCount-5) ) |
||
321 | xLastExecutionTime = xCurrentTickCount; |
||
322 | |||
323 | // call BLM handler, e.g. to send LED updates |
||
324 | BLM_SCALAR_MASTER_Periodic_mS(); |
||
325 | } |
||
326 | } |
||
327 | |||
328 | |||
329 | ///////////////////////////////////////////////////////////////////////////// |
||
330 | // Function to take/give MIDI OUT Semaphore |
||
331 | // Note: mios32_defines.h provides special macros which call this function, |
||
332 | // so that it can also be used by drivers (such as BLM_SCALAR_MASTER) |
||
333 | ///////////////////////////////////////////////////////////////////////////// |
||
334 | |||
335 | void TASKS_MUTEX_MIDIOUT_Take(void) |
||
336 | { |
||
337 | if( xMIDIOUTSemaphore ) { |
||
338 | while( xSemaphoreTakeRecursive(xMIDIOUTSemaphore, (portTickType)1) != pdTRUE ); |
||
339 | } |
||
340 | } |
||
341 | |||
342 | void TASKS_MUTEX_MIDIOUT_Give(void) |
||
343 | { |
||
344 | if( xMIDIOUTSemaphore ) { |
||
345 | xSemaphoreGiveRecursive(xMIDIOUTSemaphore); |
||
346 | } |
||
347 | } |