Subversion Repositories svn.mios32

Rev

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