This is a part of the Kinetiszer project.
main.c
- Committer:
- Clemo
- Date:
- 2014-10-28
- Revision:
- 0:cb80470434eb
File content as of revision 0:cb80470434eb:
/* * @brief J2B Synthesizer * * @note * Copyright (C) Elektor, 2014 * All rights reserved. * * @par * This software is supplied "AS IS" without any warranties of any kind, * and Elektor and its licensor disclaim any and all warranties, express * or implied, including all implied warranties of merchantability, * fitness for a particular purpose and non-infringement of intellectual * property rights. Elektor assumes no responsibility or liability for * the use of the software, conveys no license or rights under any patent, * copyright, mask work right, or any other intellectual property rights in * or to any products. Elektor reserves the right to make changes in the * software without notification. Elektor also makes no representation or * warranty that such application will be suitable for the specified use * without further testing or modification. * * @par * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted, under Elektor's and its licensor's * relevant copyrights in the software, without fee. This copyright, * permission, and disclaimer notice must appear in all copies of this code. */ //#include "chip.h" #include "board.h" #include "systick.h" #include "pwm_timer.h" #include "atmegatron.h" #include "lcd.h" pwm_timer_t sample_rate_clock; pwm_timer_t audio_out_clock; #define AUDIO_OUT_CHANNEL_1 (0) #define AUDIO_OUT_CHANNEL_2 (2) #define AUDIO_OUT_FREQUENCY_REGISTER (PWM_TIMER_FREQUENCY_REGISTER) #define SAMPLE_RATE_OUT_CHANNEL (3) #define SAMPLE_RATE_FREQUENCY_REGISTER (0) volatile uint32_t pwm_update = 256; volatile uint32_t pwm_update_ch2 = 256; boolean mono = false; // Audio out ISR void TIMER32_1_IRQHandler(void) { /*if (Chip_TIMER_MatchPending(LPC_TIMER32_1,AUDIO_OUT_FREQUENCY_REGISTER)) { Chip_TIMER_ClearMatch(LPC_TIMER32_1,AUDIO_OUT_FREQUENCY_REGISTER); Chip_TIMER_SetMatch(LPC_TIMER32_1,AUDIO_OUT_CHANNEL_1,pwm_update); Chip_TIMER_SetMatch(LPC_TIMER32_1,AUDIO_OUT_CHANNEL_2,pwm_update_ch2); }*/ } // Pitch ISR void TIMER32_0_IRQHandler(void) { //if (Chip_TIMER_MatchPending(LPC_TIMER32_0,SAMPLE_RATE_FREQUENCY_REGISTER)) { // Clear interrupt flag. //Chip_TIMER_ClearMatch(LPC_TIMER32_0,SAMPLE_RATE_FREQUENCY_REGISTER); // If at end of wavetable, go back to start. if (master_index>WAVE_LEN-1) { master_index = 0; } // Set sample value. // We have 4 bits more resolution than on AVR so multiply by 4. // pwm_update is consumed in the Audio Out ISR. pwm_update = master_output[master_index] + 128; if (mono==true) pwm_update_ch2 = master_output[master_index] + 128; else pwm_update_ch2 = master_output_ch2[master_index] + 128; //Chip_TIMER_SetMatch(audio_out_clock.timer,AUDIO_OUT_CHANNEL,master_output[master_index]+128); // Increment position in wavetable. master_index++; // Set pitch. //Chip_TIMER_SetMatch(LPC_TIMER32_0,SAMPLE_RATE_FREQUENCY_REGISTER,master_ocr1); // Keep duty-cycle of 50%. //Chip_TIMER_SetMatch(LPC_TIMER32_0,SAMPLE_RATE_OUT_CHANNEL,master_ocr1>>1); } } void setup(void) { // The hardware setup has been removed from setup and is done before. // Here we now only initialize synthesizer stuff. Init_Waves(); // Initialize wavetables. Init_Hardware(); // Initialize input controls. LFO_CalcVal(); // Initialize LFO. AEnv_CalcVal(); // Initialize amplitude envelope. FEnv_CalcVal(); // Initialize filter/pitch envelope. Filt_CalcVals(); // Initialize filter. if (POLL_MIDI==1) { // Open MIDI port (standard serial port) MIDI_Init(); } else { // Open the port for debugging. Serial.begin(9600); } Memory_Vanilla(); //load the Vanilla patch Hardware_LED_StartFlash(0,5); //flash to say "I'm ready!" } void loop_priority_low(void) { static uint32_t t_prev = 0; uint32_t t; if (POLL_MIDI==1) { // Poll the MIDI input. MIDI_Poll(); } if (POLL_HARD==1) { t = systick_counter; if (t>=t_prev+10) { // Limit hardware polling to 100 Hz. t_prev = t; // Poll the hardware (potentiometers, rotary encoders and buttons). Hardware_Poll(); } } if (POLL_TEST==1) { if (master_tick>=Testmode_Get_NextTick()) { // If test mode is being used, trigger next test note if it's time to. Testmode_ProcessNext(); } } #ifdef __HAS_ARPEGGIATOR__ Arp_Poll(); //poll the arpeggiator and see if it's time for a note (if it's on) #endif // __HAS_ARPEGGIATOR__ display_draw(false); keyboard_scan_matrix(); } void loop_priority_high(void) { // Update master_tick. master_tick = systick_counter; LFO_CalcVal(); //calculate the current output of the LFO AEnv_CalcVal(); //calculate the current output of the amplitude envelope FEnv_CalcVal(); //calculate the current output of the filter/pitch envelope Filt_CalcVals(); //calculate the variables used by the filter Pitch_Process(); //calculate the current pitch Master_Let_SampleFreq(); //set interrupt freq based on above calculation // If a key is down (actually is amplitude envelope idle): if (Aenv_Get_State()>0) { // Process the wavetable (filter/envelope/fx etc...). Wave_Process(); Flange_Process_Channel2(); } // Otherwise clear the wavetable. This is to stop. else { Wave_Clear(); Flange_ClearBuffer(); } } /*void loop(void) { if (POLL_MIDI==1) { // Poll the MIDI input. Chip_GPIO_WritePortBit(LPC_GPIO_PORT,0,10,true); MIDI_Poll(); Chip_GPIO_WritePortBit(LPC_GPIO_PORT,0,10,false); } if (POLL_HARD==1) { // Poll the hardware (potentiometers, rotary encoders and buttons). Hardware_Poll(); } // Update master_tick. master_tick = systick_counter; if (POLL_TEST==1) { if (master_tick>=Testmode_Get_NextTick()) { // If test mode is being used, trigger next test note if it's time to. Testmode_ProcessNext(); } } #ifdef __HAS_ARPEGGIATOR__ Arp_Poll(); //poll the arpeggiator and see if it's time for a note (if it's on) #endif // __HAS_ARPEGGIATOR__ LFO_CalcVal(); //calculate the current output of the LFO AEnv_CalcVal(); //calculate the current output of the amplitude envelope FEnv_CalcVal(); //calculate the current output of the filter/pitch envelope Filt_CalcVals(); //calculate the variables used by the filter Pitch_Process(); //calculate the current pitch Master_Let_SampleFreq(); //set interrupt freq based on above calculation // If a key is down (actually is amplitude envelope idle): if (Aenv_Get_State()>0) { // Process the wavetable (filter/envelope/fx etc...). Wave_Process(); } // Otherwise clear the wavetable. This is to stop. else { Wave_Clear(); Flange_ClearBuffer(); } }*/ int main_org(void) { // Generic initialization. // Before we get here the startup routine has already called SystemInit, // which resides in the file sysinit.c //SystemCoreClockUpdate(); Board_Init(); //SysTick_Config(SystemCoreClock/SYSTICK_RATE_HZ); // Setup LCD, pushbuttons and rotary encoders. keyboard_init(); display_init(); // Setup PWM timer for audio output. // Use default frequency register (MR3). // Audio timer is LPC_TIMER32_1, i.e. CT32B1 // MAT10 (PIO0_13) is PWM1. // MAT11 (PIO0_14) is shared with S5B. // MAT12 (PIO0_15) is shared with green LED1. // MAT13 (PIO0_16) is shared with S6B. audio_out_clock = pwm_timers[AUDIO_OUT_TIMER]; audio_out_clock.frequency_register = AUDIO_OUT_FREQUENCY_REGISTER; PwmTimer_Init(&audio_out_clock,281250/2); // Setup channel 0 for PWM output on pin 34 (PIO0_13). PwmTimer_InitChannel(&audio_out_clock,AUDIO_OUT_CHANNEL_1,500); // Duty-cycle x10 for more precision. PwmTimer_InitChannel(&audio_out_clock,AUDIO_OUT_CHANNEL_2,500); // Duty-cycle x10 for more precision. PwmTimer_Start(&audio_out_clock); PwmTimer_EnableInterrupt(&audio_out_clock,AUDIO_OUT_FREQUENCY_REGISTER); //NVIC_SetPriority(TIMER_32_1_IRQn,0); // Setup PWM timer for pitch/sample rate. // Sample rate timer is LPC_TIMER32_0, i.e. CT32B0 // MAT00 (PIO0_18) is PWM2. // MAT01 (PIO0_19) is shared with S6A. // MAT02 (PIO0_1) is shared with the ISP enable pin / S9. // MAT03 (PIO1_27) is FX32. sample_rate_clock = pwm_timers[SAMPLE_RATE_TIMER]; sample_rate_clock.frequency_register = SAMPLE_RATE_FREQUENCY_REGISTER; // This frequency setting has no effect because master_ocr1 controls the frequency. PwmTimer_Init(&sample_rate_clock,440*32); // Setup channel 0 for PWM output on pin 12 (PIO1_27). PwmTimer_InitChannel(&sample_rate_clock,SAMPLE_RATE_OUT_CHANNEL,500); // Duty-cycle x10 for more precision. PwmTimer_Start(&sample_rate_clock); PwmTimer_EnableInterrupt(&sample_rate_clock,SAMPLE_RATE_FREQUENCY_REGISTER); //NVIC_SetPriority(TIMER_32_0_IRQn,1); // Initialize random number generator (seems to be missing in original code). randomSeed(0); // TODO: find a better seed. // Call the Arduino setup function. setup(); // LEDs toggle in interrupt handlers. //uint32_t seconds_counter_prev = seconds_counter; while (1) { // Use pushbutton S11 ("Spare") to quickly enter ISP mode. /*if (keyboard_get_pushbutton(BOARD_KEYBOARD_S22)==key_pressed) { __disable_irq(); // How can we invoke USB ISP mode from software? // This call invokes serial ISP. Chip_FLASH_ReInvokeISP(); }*/ if (keyboard_get_pushbutton_changed(BOARD_KEYBOARD_S22)==true) { if (keyboard_get_pushbutton(BOARD_KEYBOARD_S22,true)==key_pressed) { mono = !mono; } } loop_priority_low(); // The idea was to call loop_priority_high from the systick ISR to // fix the sample calculation rate to a stable known value. This // was OK on the LPC1343, but execution is too long on the LPC1347? // The assembly code is identical for both cases. loop_priority_high(); // Do we need this? //__WFI(); } //return 0; } /** * @} */