This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

Committer:
Clemo
Date:
Tue Oct 28 20:09:12 2014 +0000
Revision:
1:8ae4ab73ca6a
Parent:
0:cb80470434eb
First publication (untested)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Clemo 0:cb80470434eb 1 /*
Clemo 0:cb80470434eb 2 * @brief J2B Synthesizer
Clemo 0:cb80470434eb 3 *
Clemo 0:cb80470434eb 4 * @note
Clemo 0:cb80470434eb 5 * Copyright (C) Elektor, 2014
Clemo 0:cb80470434eb 6 * All rights reserved.
Clemo 0:cb80470434eb 7 *
Clemo 0:cb80470434eb 8 * @par
Clemo 0:cb80470434eb 9 * This software is supplied "AS IS" without any warranties of any kind,
Clemo 0:cb80470434eb 10 * and Elektor and its licensor disclaim any and all warranties, express
Clemo 0:cb80470434eb 11 * or implied, including all implied warranties of merchantability,
Clemo 0:cb80470434eb 12 * fitness for a particular purpose and non-infringement of intellectual
Clemo 0:cb80470434eb 13 * property rights. Elektor assumes no responsibility or liability for
Clemo 0:cb80470434eb 14 * the use of the software, conveys no license or rights under any patent,
Clemo 0:cb80470434eb 15 * copyright, mask work right, or any other intellectual property rights in
Clemo 0:cb80470434eb 16 * or to any products. Elektor reserves the right to make changes in the
Clemo 0:cb80470434eb 17 * software without notification. Elektor also makes no representation or
Clemo 0:cb80470434eb 18 * warranty that such application will be suitable for the specified use
Clemo 0:cb80470434eb 19 * without further testing or modification.
Clemo 0:cb80470434eb 20 *
Clemo 0:cb80470434eb 21 * @par
Clemo 0:cb80470434eb 22 * Permission to use, copy, modify, and distribute this software and its
Clemo 0:cb80470434eb 23 * documentation is hereby granted, under Elektor's and its licensor's
Clemo 0:cb80470434eb 24 * relevant copyrights in the software, without fee. This copyright,
Clemo 0:cb80470434eb 25 * permission, and disclaimer notice must appear in all copies of this code.
Clemo 0:cb80470434eb 26 */
Clemo 0:cb80470434eb 27
Clemo 0:cb80470434eb 28 //#include "chip.h"
Clemo 0:cb80470434eb 29 #include "board.h"
Clemo 0:cb80470434eb 30 #include "systick.h"
Clemo 0:cb80470434eb 31 #include "pwm_timer.h"
Clemo 0:cb80470434eb 32 #include "atmegatron.h"
Clemo 0:cb80470434eb 33 #include "lcd.h"
Clemo 0:cb80470434eb 34
Clemo 0:cb80470434eb 35
Clemo 0:cb80470434eb 36 pwm_timer_t sample_rate_clock;
Clemo 0:cb80470434eb 37 pwm_timer_t audio_out_clock;
Clemo 0:cb80470434eb 38 #define AUDIO_OUT_CHANNEL_1 (0)
Clemo 0:cb80470434eb 39 #define AUDIO_OUT_CHANNEL_2 (2)
Clemo 0:cb80470434eb 40 #define AUDIO_OUT_FREQUENCY_REGISTER (PWM_TIMER_FREQUENCY_REGISTER)
Clemo 0:cb80470434eb 41 #define SAMPLE_RATE_OUT_CHANNEL (3)
Clemo 0:cb80470434eb 42 #define SAMPLE_RATE_FREQUENCY_REGISTER (0)
Clemo 0:cb80470434eb 43
Clemo 0:cb80470434eb 44 volatile uint32_t pwm_update = 256;
Clemo 0:cb80470434eb 45 volatile uint32_t pwm_update_ch2 = 256;
Clemo 0:cb80470434eb 46 boolean mono = false;
Clemo 0:cb80470434eb 47
Clemo 0:cb80470434eb 48 // Audio out ISR
Clemo 0:cb80470434eb 49 void TIMER32_1_IRQHandler(void)
Clemo 0:cb80470434eb 50 {
Clemo 0:cb80470434eb 51 /*if (Chip_TIMER_MatchPending(LPC_TIMER32_1,AUDIO_OUT_FREQUENCY_REGISTER))
Clemo 0:cb80470434eb 52 {
Clemo 0:cb80470434eb 53 Chip_TIMER_ClearMatch(LPC_TIMER32_1,AUDIO_OUT_FREQUENCY_REGISTER);
Clemo 0:cb80470434eb 54 Chip_TIMER_SetMatch(LPC_TIMER32_1,AUDIO_OUT_CHANNEL_1,pwm_update);
Clemo 0:cb80470434eb 55 Chip_TIMER_SetMatch(LPC_TIMER32_1,AUDIO_OUT_CHANNEL_2,pwm_update_ch2);
Clemo 0:cb80470434eb 56 }*/
Clemo 0:cb80470434eb 57 }
Clemo 0:cb80470434eb 58
Clemo 0:cb80470434eb 59
Clemo 0:cb80470434eb 60 // Pitch ISR
Clemo 0:cb80470434eb 61 void TIMER32_0_IRQHandler(void)
Clemo 0:cb80470434eb 62 {
Clemo 0:cb80470434eb 63 //if (Chip_TIMER_MatchPending(LPC_TIMER32_0,SAMPLE_RATE_FREQUENCY_REGISTER))
Clemo 0:cb80470434eb 64 {
Clemo 0:cb80470434eb 65 // Clear interrupt flag.
Clemo 0:cb80470434eb 66 //Chip_TIMER_ClearMatch(LPC_TIMER32_0,SAMPLE_RATE_FREQUENCY_REGISTER);
Clemo 0:cb80470434eb 67 // If at end of wavetable, go back to start.
Clemo 0:cb80470434eb 68 if (master_index>WAVE_LEN-1)
Clemo 0:cb80470434eb 69 {
Clemo 0:cb80470434eb 70 master_index = 0;
Clemo 0:cb80470434eb 71 }
Clemo 0:cb80470434eb 72
Clemo 0:cb80470434eb 73 // Set sample value.
Clemo 0:cb80470434eb 74 // We have 4 bits more resolution than on AVR so multiply by 4.
Clemo 0:cb80470434eb 75 // pwm_update is consumed in the Audio Out ISR.
Clemo 0:cb80470434eb 76 pwm_update = master_output[master_index] + 128;
Clemo 0:cb80470434eb 77 if (mono==true) pwm_update_ch2 = master_output[master_index] + 128;
Clemo 0:cb80470434eb 78 else pwm_update_ch2 = master_output_ch2[master_index] + 128;
Clemo 0:cb80470434eb 79 //Chip_TIMER_SetMatch(audio_out_clock.timer,AUDIO_OUT_CHANNEL,master_output[master_index]+128);
Clemo 0:cb80470434eb 80 // Increment position in wavetable.
Clemo 0:cb80470434eb 81 master_index++;
Clemo 0:cb80470434eb 82 // Set pitch.
Clemo 0:cb80470434eb 83 //Chip_TIMER_SetMatch(LPC_TIMER32_0,SAMPLE_RATE_FREQUENCY_REGISTER,master_ocr1);
Clemo 0:cb80470434eb 84 // Keep duty-cycle of 50%.
Clemo 0:cb80470434eb 85 //Chip_TIMER_SetMatch(LPC_TIMER32_0,SAMPLE_RATE_OUT_CHANNEL,master_ocr1>>1);
Clemo 0:cb80470434eb 86 }
Clemo 0:cb80470434eb 87 }
Clemo 0:cb80470434eb 88
Clemo 0:cb80470434eb 89
Clemo 0:cb80470434eb 90 void setup(void)
Clemo 0:cb80470434eb 91 {
Clemo 0:cb80470434eb 92 // The hardware setup has been removed from setup and is done before.
Clemo 0:cb80470434eb 93 // Here we now only initialize synthesizer stuff.
Clemo 0:cb80470434eb 94
Clemo 0:cb80470434eb 95 Init_Waves(); // Initialize wavetables.
Clemo 0:cb80470434eb 96 Init_Hardware(); // Initialize input controls.
Clemo 0:cb80470434eb 97 LFO_CalcVal(); // Initialize LFO.
Clemo 0:cb80470434eb 98 AEnv_CalcVal(); // Initialize amplitude envelope.
Clemo 0:cb80470434eb 99 FEnv_CalcVal(); // Initialize filter/pitch envelope.
Clemo 0:cb80470434eb 100 Filt_CalcVals(); // Initialize filter.
Clemo 0:cb80470434eb 101
Clemo 0:cb80470434eb 102 if (POLL_MIDI==1)
Clemo 0:cb80470434eb 103 {
Clemo 0:cb80470434eb 104 // Open MIDI port (standard serial port)
Clemo 0:cb80470434eb 105 MIDI_Init();
Clemo 0:cb80470434eb 106 }
Clemo 0:cb80470434eb 107 else
Clemo 0:cb80470434eb 108 {
Clemo 0:cb80470434eb 109 // Open the port for debugging.
Clemo 0:cb80470434eb 110 Serial.begin(9600);
Clemo 0:cb80470434eb 111 }
Clemo 0:cb80470434eb 112
Clemo 0:cb80470434eb 113 Memory_Vanilla(); //load the Vanilla patch
Clemo 0:cb80470434eb 114 Hardware_LED_StartFlash(0,5); //flash to say "I'm ready!"
Clemo 0:cb80470434eb 115 }
Clemo 0:cb80470434eb 116
Clemo 0:cb80470434eb 117
Clemo 0:cb80470434eb 118 void loop_priority_low(void)
Clemo 0:cb80470434eb 119 {
Clemo 0:cb80470434eb 120 static uint32_t t_prev = 0;
Clemo 0:cb80470434eb 121 uint32_t t;
Clemo 0:cb80470434eb 122
Clemo 0:cb80470434eb 123 if (POLL_MIDI==1)
Clemo 0:cb80470434eb 124 {
Clemo 0:cb80470434eb 125 // Poll the MIDI input.
Clemo 0:cb80470434eb 126 MIDI_Poll();
Clemo 0:cb80470434eb 127 }
Clemo 0:cb80470434eb 128 if (POLL_HARD==1)
Clemo 0:cb80470434eb 129 {
Clemo 0:cb80470434eb 130 t = systick_counter;
Clemo 0:cb80470434eb 131 if (t>=t_prev+10)
Clemo 0:cb80470434eb 132 {
Clemo 0:cb80470434eb 133 // Limit hardware polling to 100 Hz.
Clemo 0:cb80470434eb 134 t_prev = t;
Clemo 0:cb80470434eb 135 // Poll the hardware (potentiometers, rotary encoders and buttons).
Clemo 0:cb80470434eb 136 Hardware_Poll();
Clemo 0:cb80470434eb 137 }
Clemo 0:cb80470434eb 138 }
Clemo 0:cb80470434eb 139
Clemo 0:cb80470434eb 140 if (POLL_TEST==1)
Clemo 0:cb80470434eb 141 {
Clemo 0:cb80470434eb 142 if (master_tick>=Testmode_Get_NextTick())
Clemo 0:cb80470434eb 143 {
Clemo 0:cb80470434eb 144 // If test mode is being used, trigger next test note if it's time to.
Clemo 0:cb80470434eb 145 Testmode_ProcessNext();
Clemo 0:cb80470434eb 146 }
Clemo 0:cb80470434eb 147 }
Clemo 0:cb80470434eb 148
Clemo 0:cb80470434eb 149 #ifdef __HAS_ARPEGGIATOR__
Clemo 0:cb80470434eb 150 Arp_Poll(); //poll the arpeggiator and see if it's time for a note (if it's on)
Clemo 0:cb80470434eb 151 #endif // __HAS_ARPEGGIATOR__
Clemo 0:cb80470434eb 152
Clemo 0:cb80470434eb 153 display_draw(false);
Clemo 0:cb80470434eb 154 keyboard_scan_matrix();
Clemo 0:cb80470434eb 155 }
Clemo 0:cb80470434eb 156
Clemo 0:cb80470434eb 157
Clemo 0:cb80470434eb 158 void loop_priority_high(void)
Clemo 0:cb80470434eb 159 {
Clemo 0:cb80470434eb 160 // Update master_tick.
Clemo 0:cb80470434eb 161 master_tick = systick_counter;
Clemo 0:cb80470434eb 162
Clemo 0:cb80470434eb 163 LFO_CalcVal(); //calculate the current output of the LFO
Clemo 0:cb80470434eb 164 AEnv_CalcVal(); //calculate the current output of the amplitude envelope
Clemo 0:cb80470434eb 165 FEnv_CalcVal(); //calculate the current output of the filter/pitch envelope
Clemo 0:cb80470434eb 166 Filt_CalcVals(); //calculate the variables used by the filter
Clemo 0:cb80470434eb 167 Pitch_Process(); //calculate the current pitch
Clemo 0:cb80470434eb 168 Master_Let_SampleFreq(); //set interrupt freq based on above calculation
Clemo 0:cb80470434eb 169 // If a key is down (actually is amplitude envelope idle):
Clemo 0:cb80470434eb 170 if (Aenv_Get_State()>0)
Clemo 0:cb80470434eb 171 {
Clemo 0:cb80470434eb 172 // Process the wavetable (filter/envelope/fx etc...).
Clemo 0:cb80470434eb 173 Wave_Process();
Clemo 0:cb80470434eb 174 Flange_Process_Channel2();
Clemo 0:cb80470434eb 175 }
Clemo 0:cb80470434eb 176 // Otherwise clear the wavetable. This is to stop.
Clemo 0:cb80470434eb 177 else
Clemo 0:cb80470434eb 178 {
Clemo 0:cb80470434eb 179 Wave_Clear();
Clemo 0:cb80470434eb 180 Flange_ClearBuffer();
Clemo 0:cb80470434eb 181 }
Clemo 0:cb80470434eb 182 }
Clemo 0:cb80470434eb 183
Clemo 0:cb80470434eb 184
Clemo 0:cb80470434eb 185 /*void loop(void)
Clemo 0:cb80470434eb 186 {
Clemo 0:cb80470434eb 187 if (POLL_MIDI==1)
Clemo 0:cb80470434eb 188 {
Clemo 0:cb80470434eb 189 // Poll the MIDI input.
Clemo 0:cb80470434eb 190 Chip_GPIO_WritePortBit(LPC_GPIO_PORT,0,10,true);
Clemo 0:cb80470434eb 191 MIDI_Poll();
Clemo 0:cb80470434eb 192 Chip_GPIO_WritePortBit(LPC_GPIO_PORT,0,10,false);
Clemo 0:cb80470434eb 193 }
Clemo 0:cb80470434eb 194 if (POLL_HARD==1)
Clemo 0:cb80470434eb 195 {
Clemo 0:cb80470434eb 196 // Poll the hardware (potentiometers, rotary encoders and buttons).
Clemo 0:cb80470434eb 197 Hardware_Poll();
Clemo 0:cb80470434eb 198 }
Clemo 0:cb80470434eb 199
Clemo 0:cb80470434eb 200 // Update master_tick.
Clemo 0:cb80470434eb 201 master_tick = systick_counter;
Clemo 0:cb80470434eb 202
Clemo 0:cb80470434eb 203 if (POLL_TEST==1)
Clemo 0:cb80470434eb 204 {
Clemo 0:cb80470434eb 205 if (master_tick>=Testmode_Get_NextTick())
Clemo 0:cb80470434eb 206 {
Clemo 0:cb80470434eb 207 // If test mode is being used, trigger next test note if it's time to.
Clemo 0:cb80470434eb 208 Testmode_ProcessNext();
Clemo 0:cb80470434eb 209 }
Clemo 0:cb80470434eb 210 }
Clemo 0:cb80470434eb 211 #ifdef __HAS_ARPEGGIATOR__
Clemo 0:cb80470434eb 212 Arp_Poll(); //poll the arpeggiator and see if it's time for a note (if it's on)
Clemo 0:cb80470434eb 213 #endif // __HAS_ARPEGGIATOR__
Clemo 0:cb80470434eb 214 LFO_CalcVal(); //calculate the current output of the LFO
Clemo 0:cb80470434eb 215 AEnv_CalcVal(); //calculate the current output of the amplitude envelope
Clemo 0:cb80470434eb 216 FEnv_CalcVal(); //calculate the current output of the filter/pitch envelope
Clemo 0:cb80470434eb 217 Filt_CalcVals(); //calculate the variables used by the filter
Clemo 0:cb80470434eb 218 Pitch_Process(); //calculate the current pitch
Clemo 0:cb80470434eb 219 Master_Let_SampleFreq(); //set interrupt freq based on above calculation
Clemo 0:cb80470434eb 220 // If a key is down (actually is amplitude envelope idle):
Clemo 0:cb80470434eb 221 if (Aenv_Get_State()>0)
Clemo 0:cb80470434eb 222 {
Clemo 0:cb80470434eb 223 // Process the wavetable (filter/envelope/fx etc...).
Clemo 0:cb80470434eb 224 Wave_Process();
Clemo 0:cb80470434eb 225 }
Clemo 0:cb80470434eb 226 // Otherwise clear the wavetable. This is to stop.
Clemo 0:cb80470434eb 227 else
Clemo 0:cb80470434eb 228 {
Clemo 0:cb80470434eb 229 Wave_Clear();
Clemo 0:cb80470434eb 230 Flange_ClearBuffer();
Clemo 0:cb80470434eb 231 }
Clemo 0:cb80470434eb 232 }*/
Clemo 0:cb80470434eb 233
Clemo 0:cb80470434eb 234
Clemo 0:cb80470434eb 235 int main_org(void)
Clemo 0:cb80470434eb 236 {
Clemo 0:cb80470434eb 237 // Generic initialization.
Clemo 0:cb80470434eb 238 // Before we get here the startup routine has already called SystemInit,
Clemo 0:cb80470434eb 239 // which resides in the file sysinit.c
Clemo 0:cb80470434eb 240 //SystemCoreClockUpdate();
Clemo 0:cb80470434eb 241 Board_Init();
Clemo 0:cb80470434eb 242 //SysTick_Config(SystemCoreClock/SYSTICK_RATE_HZ);
Clemo 0:cb80470434eb 243
Clemo 0:cb80470434eb 244 // Setup LCD, pushbuttons and rotary encoders.
Clemo 0:cb80470434eb 245 keyboard_init();
Clemo 0:cb80470434eb 246 display_init();
Clemo 0:cb80470434eb 247
Clemo 0:cb80470434eb 248 // Setup PWM timer for audio output.
Clemo 0:cb80470434eb 249 // Use default frequency register (MR3).
Clemo 0:cb80470434eb 250 // Audio timer is LPC_TIMER32_1, i.e. CT32B1
Clemo 0:cb80470434eb 251 // MAT10 (PIO0_13) is PWM1.
Clemo 0:cb80470434eb 252 // MAT11 (PIO0_14) is shared with S5B.
Clemo 0:cb80470434eb 253 // MAT12 (PIO0_15) is shared with green LED1.
Clemo 0:cb80470434eb 254 // MAT13 (PIO0_16) is shared with S6B.
Clemo 0:cb80470434eb 255 audio_out_clock = pwm_timers[AUDIO_OUT_TIMER];
Clemo 0:cb80470434eb 256 audio_out_clock.frequency_register = AUDIO_OUT_FREQUENCY_REGISTER;
Clemo 0:cb80470434eb 257 PwmTimer_Init(&audio_out_clock,281250/2);
Clemo 0:cb80470434eb 258 // Setup channel 0 for PWM output on pin 34 (PIO0_13).
Clemo 0:cb80470434eb 259 PwmTimer_InitChannel(&audio_out_clock,AUDIO_OUT_CHANNEL_1,500); // Duty-cycle x10 for more precision.
Clemo 0:cb80470434eb 260 PwmTimer_InitChannel(&audio_out_clock,AUDIO_OUT_CHANNEL_2,500); // Duty-cycle x10 for more precision.
Clemo 0:cb80470434eb 261 PwmTimer_Start(&audio_out_clock);
Clemo 0:cb80470434eb 262 PwmTimer_EnableInterrupt(&audio_out_clock,AUDIO_OUT_FREQUENCY_REGISTER);
Clemo 0:cb80470434eb 263 //NVIC_SetPriority(TIMER_32_1_IRQn,0);
Clemo 0:cb80470434eb 264
Clemo 0:cb80470434eb 265 // Setup PWM timer for pitch/sample rate.
Clemo 0:cb80470434eb 266 // Sample rate timer is LPC_TIMER32_0, i.e. CT32B0
Clemo 0:cb80470434eb 267 // MAT00 (PIO0_18) is PWM2.
Clemo 0:cb80470434eb 268 // MAT01 (PIO0_19) is shared with S6A.
Clemo 0:cb80470434eb 269 // MAT02 (PIO0_1) is shared with the ISP enable pin / S9.
Clemo 0:cb80470434eb 270 // MAT03 (PIO1_27) is FX32.
Clemo 0:cb80470434eb 271 sample_rate_clock = pwm_timers[SAMPLE_RATE_TIMER];
Clemo 0:cb80470434eb 272 sample_rate_clock.frequency_register = SAMPLE_RATE_FREQUENCY_REGISTER;
Clemo 0:cb80470434eb 273 // This frequency setting has no effect because master_ocr1 controls the frequency.
Clemo 0:cb80470434eb 274 PwmTimer_Init(&sample_rate_clock,440*32);
Clemo 0:cb80470434eb 275 // Setup channel 0 for PWM output on pin 12 (PIO1_27).
Clemo 0:cb80470434eb 276 PwmTimer_InitChannel(&sample_rate_clock,SAMPLE_RATE_OUT_CHANNEL,500); // Duty-cycle x10 for more precision.
Clemo 0:cb80470434eb 277 PwmTimer_Start(&sample_rate_clock);
Clemo 0:cb80470434eb 278 PwmTimer_EnableInterrupt(&sample_rate_clock,SAMPLE_RATE_FREQUENCY_REGISTER);
Clemo 0:cb80470434eb 279 //NVIC_SetPriority(TIMER_32_0_IRQn,1);
Clemo 0:cb80470434eb 280
Clemo 0:cb80470434eb 281 // Initialize random number generator (seems to be missing in original code).
Clemo 0:cb80470434eb 282 randomSeed(0); // TODO: find a better seed.
Clemo 0:cb80470434eb 283
Clemo 0:cb80470434eb 284 // Call the Arduino setup function.
Clemo 0:cb80470434eb 285 setup();
Clemo 0:cb80470434eb 286
Clemo 0:cb80470434eb 287 // LEDs toggle in interrupt handlers.
Clemo 0:cb80470434eb 288 //uint32_t seconds_counter_prev = seconds_counter;
Clemo 0:cb80470434eb 289
Clemo 0:cb80470434eb 290 while (1)
Clemo 0:cb80470434eb 291 {
Clemo 0:cb80470434eb 292 // Use pushbutton S11 ("Spare") to quickly enter ISP mode.
Clemo 0:cb80470434eb 293 /*if (keyboard_get_pushbutton(BOARD_KEYBOARD_S22)==key_pressed)
Clemo 0:cb80470434eb 294 {
Clemo 0:cb80470434eb 295 __disable_irq();
Clemo 0:cb80470434eb 296 // How can we invoke USB ISP mode from software?
Clemo 0:cb80470434eb 297 // This call invokes serial ISP.
Clemo 0:cb80470434eb 298 Chip_FLASH_ReInvokeISP();
Clemo 0:cb80470434eb 299 }*/
Clemo 0:cb80470434eb 300
Clemo 0:cb80470434eb 301 if (keyboard_get_pushbutton_changed(BOARD_KEYBOARD_S22)==true)
Clemo 0:cb80470434eb 302 {
Clemo 0:cb80470434eb 303 if (keyboard_get_pushbutton(BOARD_KEYBOARD_S22,true)==key_pressed)
Clemo 0:cb80470434eb 304 {
Clemo 0:cb80470434eb 305 mono = !mono;
Clemo 0:cb80470434eb 306 }
Clemo 0:cb80470434eb 307 }
Clemo 0:cb80470434eb 308
Clemo 0:cb80470434eb 309 loop_priority_low();
Clemo 0:cb80470434eb 310 // The idea was to call loop_priority_high from the systick ISR to
Clemo 0:cb80470434eb 311 // fix the sample calculation rate to a stable known value. This
Clemo 0:cb80470434eb 312 // was OK on the LPC1343, but execution is too long on the LPC1347?
Clemo 0:cb80470434eb 313 // The assembly code is identical for both cases.
Clemo 0:cb80470434eb 314 loop_priority_high();
Clemo 0:cb80470434eb 315
Clemo 0:cb80470434eb 316 // Do we need this?
Clemo 0:cb80470434eb 317 //__WFI();
Clemo 0:cb80470434eb 318 }
Clemo 0:cb80470434eb 319
Clemo 0:cb80470434eb 320 //return 0;
Clemo 0:cb80470434eb 321 }
Clemo 0:cb80470434eb 322
Clemo 0:cb80470434eb 323 /**
Clemo 0:cb80470434eb 324 * @}
Clemo 0:cb80470434eb 325 */