Subversion Repositories svn.mios32

Rev

Rev 1248 | Rev 1250 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1227 tk 1
// $Id: app.c 1249 2011-07-12 22:07:29Z tk $
2
/*
3
 * EmbSpeech Demo for MIOS32
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2011 Thorsten Klose (tk@midibox.org)
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 "synth.h"
1247 tk 21
#include "tasks.h"
1227 tk 22
 
23
#include <notestack.h>
24
 
1247 tk 25
// include source of the SCS
26
#include <scs.h>
27
#include "scs_config.h"
1227 tk 28
 
1247 tk 29
#include "synth_file.h"
30
#include "synth_file_b.h"
1227 tk 31
 
32
// define priority level for task:
33
// use same priority as MIOS32 specific tasks (3)
34
#define PRIORITY_TASK_PERIODIC_1MS   ( tskIDLE_PRIORITY + 3 )
35
 
36
// local prototype of the task function
37
static void TASK_Periodic_1mS(void *pvParameters);
38
 
1247 tk 39
// define priority level for control surface handler
40
// use lower priority as MIOS32 specific tasks (2), so that slow LCDs don't affect overall performance
41
#define PRIORITY_TASK_PERIOD_1mS_LP ( tskIDLE_PRIORITY + 2 )
1227 tk 42
 
1247 tk 43
// local prototype of the task function
44
static void TASK_Period_1mS_LP(void *pvParameters);
1227 tk 45
 
46
/////////////////////////////////////////////////////////////////////////////
47
// Local definitions
48
/////////////////////////////////////////////////////////////////////////////
49
 
50
#define NOTESTACK_SIZE 16
51
 
1247 tk 52
// C-2
1248 tk 53
#define PHRASE_NOTE_OFFSET 0x30
1227 tk 54
 
55
/////////////////////////////////////////////////////////////////////////////
56
// Local variables
57
/////////////////////////////////////////////////////////////////////////////
58
 
59
static notestack_t notestack;
60
static notestack_item_t notestack_items[NOTESTACK_SIZE];
61
 
62
 
63
/////////////////////////////////////////////////////////////////////////////
64
// Global Variables
65
/////////////////////////////////////////////////////////////////////////////
66
 
1247 tk 67
// for mutual exclusive SD Card access between different tasks
68
// The mutex is handled with MUTEX_SDCARD_TAKE and MUTEX_SDCARD_GIVE
69
// macros inside the application, which contain a different implementation 
70
// for emulation
71
xSemaphoreHandle xSDCardSemaphore;
1227 tk 72
 
1247 tk 73
 
1227 tk 74
/////////////////////////////////////////////////////////////////////////////
75
// This hook is called after startup to initialize the application
76
/////////////////////////////////////////////////////////////////////////////
77
void APP_Init(void)
78
{
79
  // initialize all LEDs
80
  MIOS32_BOARD_LED_Init(0xffffffff);
81
 
1247 tk 82
  // create semaphores
83
  xSDCardSemaphore = xSemaphoreCreateRecursiveMutex();
84
 
1227 tk 85
  // initialize the Notestack
86
  NOTESTACK_Init(&notestack, NOTESTACK_MODE_PUSH_TOP, &notestack_items[0], NOTESTACK_SIZE);
87
 
1247 tk 88
  // init Synth
89
  SYNTH_Init(0);
1229 tk 90
 
1247 tk 91
  // initialize all J10 pins as inputs with internal Pull-Up
92
  int pin;
93
  for(pin=0; pin<8; ++pin)
94
    MIOS32_BOARD_J10_PinInit(pin, MIOS32_BOARD_PIN_MODE_INPUT_PU);
1229 tk 95
 
1247 tk 96
  // initialize Standard Control Surface
97
  SCS_Init(0);
1227 tk 98
 
1247 tk 99
  // initialize local SCS configuration
100
  SCS_CONFIG_Init(0);
1227 tk 101
 
1247 tk 102
  // initialize file system
103
  SYNTH_FILE_Init(0);
104
 
1227 tk 105
  // start task
106
  xTaskCreate(TASK_Periodic_1mS, (signed portCHAR *)"Periodic_1mS", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIODIC_1MS, NULL);
1247 tk 107
  xTaskCreate(TASK_Period_1mS_LP, (signed portCHAR *)"1mS_LP", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS_LP, NULL);
1227 tk 108
}
109
 
110
 
111
/////////////////////////////////////////////////////////////////////////////
112
// This task is running endless in background
113
/////////////////////////////////////////////////////////////////////////////
114
void APP_Background(void)
115
{
116
}
117
 
118
 
119
/////////////////////////////////////////////////////////////////////////////
120
// This hook is called when a MIDI package has been received
121
/////////////////////////////////////////////////////////////////////////////
122
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
123
{
124
  // if note event over MIDI channel #1 controls note of both oscillators
125
  // Note On received?
126
  if( midi_package.chn == Chn1 &&
127
      (midi_package.type == NoteOn || midi_package.type == NoteOff) ) {
128
 
129
    // branch depending on Note On/Off event
130
    if( midi_package.event == NoteOn && midi_package.velocity > 0 ) {
131
      // push note into note stack
132
      NOTESTACK_Push(&notestack, midi_package.note, midi_package.velocity);
133
    } else {
134
      // remove note from note stack
135
      NOTESTACK_Pop(&notestack, midi_package.note);
136
    }
137
 
138
 
139
    // still a note in stack?
140
    if( notestack.len ) {
141
      // take first note of stack
142
      u8 note = notestack_items[0].note;
143
      u8 velocity = notestack_items[0].tag;
144
 
145
#if 0
146
      // set frequency for both oscillators
147
      int chn;
148
      for(chn=0; chn<2; ++chn) {
149
    SYNTH_FrequencySet(chn, frqtab[note]);
150
    SYNTH_VelocitySet(chn, velocity);
151
      }
152
#endif
153
 
1247 tk 154
      // play note
1248 tk 155
      int phrase_num = note - PHRASE_NOTE_OFFSET;
156
      while( phrase_num < 0)
157
    phrase_num += SYNTH_NUM_PHRASES;
158
      while( phrase_num > SYNTH_NUM_PHRASES )
159
    phrase_num -= SYNTH_NUM_PHRASES;
1247 tk 160
 
161
      // legato...
162
      if( notestack.len == 1 )
1248 tk 163
    SYNTH_PhraseStop(phrase_num);
1247 tk 164
 
1248 tk 165
      SYNTH_PhrasePlay(phrase_num, velocity);
1229 tk 166
 
1227 tk 167
      // set board LED
168
      MIOS32_BOARD_LED_Set(1, 1);
169
    } else {
170
      // turn off LED (can also be used as a gate output!)
171
      MIOS32_BOARD_LED_Set(1, 0);
172
 
173
#if 0
174
      // set velocity to 0 for all oscillators
175
      int chn;
176
      for(chn=0; chn<2; ++chn)
177
    SYNTH_VelocitySet(chn, 0x00);
178
#endif
179
    }
180
 
181
#if 0
182
    // optional debug messages
183
    NOTESTACK_SendDebugMessage(&notestack);
184
#endif
1229 tk 185
  } else if( midi_package.type == CC ) {
1248 tk 186
    u8 phrase_num = 0;
1247 tk 187
    u8 phoneme_ix = midi_package.chn;
188
    u32 value = midi_package.value;
1229 tk 189
 
1247 tk 190
    if( midi_package.cc_number < 16 ) {
191
    } else if( midi_package.cc_number < 32 ) {
192
      u8 phoneme_par = midi_package.cc_number - 16;
1248 tk 193
      SYNTH_PhonemeParSet(phrase_num, phoneme_ix, phoneme_par, value);
1247 tk 194
    } else if( midi_package.cc_number < 48 ) {
1248 tk 195
      u8 phrase_par = midi_package.cc_number - 32;
196
      SYNTH_PhraseParSet(phrase_num, phrase_par, value);
197
    } else if( midi_package.cc_number < 64 ) {
198
      u8 global_par = midi_package.cc_number - 48;
1247 tk 199
      SYNTH_GlobalParSet(global_par, value);
1229 tk 200
    }
1227 tk 201
  }
1229 tk 202
 
1227 tk 203
}
204
 
205
 
206
/////////////////////////////////////////////////////////////////////////////
207
// This hook is called before the shift register chain is scanned
208
/////////////////////////////////////////////////////////////////////////////
209
void APP_SRIO_ServicePrepare(void)
210
{
1247 tk 211
#ifdef MIOS32_FAMILY_LPC17xx
212
  // pass current pin state of J10
213
  // only available for LPC17xx, all others (like STM32) default to SRIO
1249 tk 214
  SCS_AllPinsSet(0xff00 | MIOS32_BOARD_J10_Get());
1247 tk 215
#endif
216
 
217
  // update encoders/buttons of SCS
218
  SCS_EncButtonUpdate_Tick();
1227 tk 219
}
220
 
221
 
222
/////////////////////////////////////////////////////////////////////////////
223
// This hook is called after the shift register chain has been scanned
224
/////////////////////////////////////////////////////////////////////////////
225
void APP_SRIO_ServiceFinish(void)
226
{
227
}
228
 
229
 
230
/////////////////////////////////////////////////////////////////////////////
231
// This hook is called when a button has been toggled
232
// pin_value is 1 when button released, and 0 when button pressed
233
/////////////////////////////////////////////////////////////////////////////
234
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value)
235
{
1247 tk 236
  // for STM32 (no J10 available, accordingly encoder/buttons connected to DIN):
237
  // if DIN pin number between 0..7: pass to SCS
238
  if( pin < 8 )
239
    SCS_DIN_NotifyToggle(pin, pin_value);
1227 tk 240
}
241
 
242
 
243
/////////////////////////////////////////////////////////////////////////////
244
// This hook is called when an encoder has been moved
245
// incrementer is positive when encoder has been turned clockwise, else
246
// it is negative
247
/////////////////////////////////////////////////////////////////////////////
248
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer)
249
{
1247 tk 250
  // pass encoder event to SCS handler
251
  if( encoder == SCS_ENC_MENU_ID )
252
    SCS_ENC_MENU_NotifyChange(incrementer);
1227 tk 253
}
254
 
255
 
256
/////////////////////////////////////////////////////////////////////////////
257
// This hook is called when a pot has been moved
258
/////////////////////////////////////////////////////////////////////////////
259
void APP_AIN_NotifyChange(u32 pin, u32 pin_value)
260
{
261
}
262
 
263
 
264
/////////////////////////////////////////////////////////////////////////////
265
// This task scans J5 pins periodically
266
/////////////////////////////////////////////////////////////////////////////
267
static void TASK_Periodic_1mS(void *pvParameters)
268
{
269
  portTickType xLastExecutionTime;
270
 
271
  // Initialise the xLastExecutionTime variable on task entry
272
  xLastExecutionTime = xTaskGetTickCount();
273
 
274
  while( 1 ) {
275
    vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS);
276
 
277
    SYNTH_Tick();
1247 tk 278
  }
279
}
1227 tk 280
 
1247 tk 281
/////////////////////////////////////////////////////////////////////////////
282
// This task handles the control surface
283
/////////////////////////////////////////////////////////////////////////////
284
static void TASK_Period_1mS_LP(void *pvParameters)
285
{
286
  MIOS32_LCD_Clear();
287
 
288
  while( 1 ) {
289
    vTaskDelay(1 / portTICK_RATE_MS);
290
 
291
    // call SCS handler
292
    SCS_Tick();
293
 
294
    // SD Card handler
295
    MUTEX_SDCARD_TAKE;
296
    s32 status = SYNTH_FILE_CheckSDCard();
297
 
298
    if( status == 1 ) {
299
      DEBUG_MSG("SD Card connected: %s\n", SYNTH_FILE_VolumeLabel());
300
    } else if( status == 2 ) {
301
      DEBUG_MSG("SD Card disconnected\n");
302
    } else if( status == 3 ) {
303
      if( !SYNTH_FILE_SDCardAvailable() ) {
304
    DEBUG_MSG("SD Card not found\n");
305
      } else if( !SYNTH_FILE_VolumeAvailable() ) {
306
    DEBUG_MSG("ERROR: SD Card contains invalid FAT!\n");
307
      } else {
308
    int bank;
309
    for(bank=0; bank<SYNTH_FILE_B_NUM_BANKS; ++bank) {
310
      u8 numPatches = SYNTH_FILE_B_NumPatches(bank);
311
 
312
      if( numPatches ) {
313
        DEBUG_MSG("Bank #%d contains %d patches\n", bank+1, numPatches);
314
      } else {
315
        DEBUG_MSG("Bank #%d not found - creating new one\n", bank+1);
316
        if( (status=SYNTH_FILE_B_Create(synth_file_session_name, bank)) < 0 ) {
317
          DEBUG_MSG("Failed to create Bank #%d (status: %d)\n", bank+1, status);
318
        } else {
319
          DEBUG_MSG("Bank #%d successfully created!\n", bank+1);
320
 
321
          int numPatches = SYNTH_FILE_B_NumPatches(bank);
322
          int patch;
323
          for(patch=0; patch<numPatches; ++patch) {
324
        DEBUG_MSG("Writing Bank %d Patch #%d\n", bank+1, patch+1);
325
        MIOS32_LCD_CursorSet(0, 0); // TMP - use message system later
326
        MIOS32_LCD_PrintFormattedString("Write Patch %d.%03d  ", bank+1, patch+1);
327
        MIOS32_LCD_CursorSet(0, 1); // TMP - use message system later
328
        MIOS32_LCD_PrintFormattedString("Please wait...      ");
329
        u8 sourceGroup = 0;
330
        u8 rename_if_empty_name = 0;
331
        MUTEX_SDCARD_TAKE;
332
        if( (status=SYNTH_FILE_B_PatchWrite(synth_file_session_name, bank, patch, sourceGroup, rename_if_empty_name)) < 0 ) {
333
          DEBUG_MSG("Failed to write patch #%d into bank #%d (status: %d)\n", patch+1, bank+1, status);
334
        }
335
          }
336
          SCS_DisplayUpdateRequest();
337
        }
338
      }
1229 tk 339
    }
1247 tk 340
    status = SYNTH_FILE_UnloadAllFiles();
341
    status = SYNTH_FILE_LoadAllFiles(1);
342
    if( status < 0 ) {
343
      DEBUG_MSG("Failed to load the newly created files!\n");
344
    }
1227 tk 345
      }
346
    }
1247 tk 347
 
348
    MUTEX_SDCARD_GIVE;
1227 tk 349
  }
1247 tk 350
 
1227 tk 351
}
1247 tk 352