// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // adcon.c - A/D conversion // version 1.00 - 20070525 // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define FCY 20000000 // cycle machine frequency #include "p30f3014.h" #include "adcon.h" #include "buttn.h" #define defined_in extern #include "glob.h" extern int logvalue[]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // hardware AD converters assignment #define SQWIDE ADCBUFC // P1 width #define PORTAM ADCBUFB // P2 portamento #define LFOFRQ ADCBUFA // P3 lfo frequ #define LFOLEV ADCBUF9 // P4 lfo level #define FILFRQ ADCBUF5 // P5 filter frequ #define FILRES ADCBUF3 // P7 filter resonance #define EN1ATK ADCBUF1 // P9 env1 ar attack #define EN1REL ADCBUF7 // P11 env1 ar release #define EN1SWP ADCBUF8 // P13 env1 ar sweep #define EN2ATK ADCBUF4 // P6 env2 adsr attack #define EN2DEC ADCBUF2 // P8 env2 adsr decay #define EN2SUS ADCBUF0 // P10 env2 adsr sustain #define EN2REL ADCBUF6 // P12 env2 adsr release // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void adcon_ini(void) // A/D conversion initialization { // AD configuration ADPCFG = 0; // AN0-AN12 as analog inputs TRISB = 0x1FFF; // port B as input ADCON1bits.FORM = 0; // int (0000 dddd dddd dddd) ADCON1bits.SSRC = 7; // 2 T3 contr.; 7 autom. ADCON1bits.ASAM = 1; // auto-start immediately ADCON2bits.CSCNA = 1; // scan for CH0+ S/H for MUX A ADCON2bits.SMPI = 15; // int for each 16th sam/conv ADCON2bits.BUFM = 0; // buffer mode select 0=16 words ADCON2bits.ALTS = 0; // alter.input sample Mode Select ADCON3bits.SAMC = 15; // Auto Sample Time bits ADCON3bits.ADRC = 1; // source ck 0=system 1=internal ADCON3bits.ADCS = 63; // A/D Conv Clock Select bits // ADCHS: A/D Input Select Register ADCHS = 0; // clear selection ADCHSbits.CH0NA = 0; // ch.0 neg.input sel.for MUX A // ADCSSL: A/D Input Scan Select Register ADCSSL = 0x1FFF; // scan AN0 thru AN12 giving // results into ADCBUF0 to ADCBUF12 IEC0bits.ADIE = 0; // disable AD interrupt ADCON1bits.ADON = 1; // enable AD converter } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int adcon_read(void) // read analog return has data { if (! ADCON1bits.DONE) return 0; // analog data not available if (g_buttune == TNHALFT) // if halftone tune selected { g_o1half = SQWIDE; // P1 dco1 tune g_o2half = PORTAM; // P2 dco2 tune } else if (g_buttune == TNPITCH) // if pitch tune selected { g_o1ptch = SQWIDE; // P1 dco1 tune g_o2ptch = PORTAM; // P2 dco2 tune } else { g_sqwide = SQWIDE; // P1 width g_portam = PORTAM; // P2 portamento } g_lfofrq = LFOFRQ; // P3 lfo frequ g_lfolev = LFOLEV; // P4 lfo level g_filfrq = FILFRQ; // P5 filter frequ g_filres = FILRES; // P7 filter resonance g_en1atk = EN1ATK; // P9 env1 ar attack g_en1rel = EN1REL; // P11 env1 ar release g_en1swp = EN1SWP; // P13 env1 ar sweep g_en2atk = EN2ATK; // P6 env2 adsr attack g_en2dec = EN2DEC; // P8 env2 adsr decay g_en2sus = EN2SUS; // P10 env2 adsr sustain g_en2rel = EN2REL; // P12 env2 adsr release ADCON1bits.DONE = 0; // starts AD conversion return 1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // adcon.h - A/D conversion // version 1.00 - 20070525 // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void adcon_ini(void); // A/D conversion initialization int adcon_read(void); // read analog ports // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // buttn.c - buttons on check and display statuses // version 1.02 - 20070611 - optimizing buttons debounce // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // buttons 1 to 5 are allocated to RD9, RD3, RA11, RF6, RC13 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define DBOUNC 256 // debounce counter value #include "p30f3014.h" #include "buttn.h" #include "dsply.h" #define defined_in extern #include "glob.h" static int buttn_led[4] = {8, 4, 2, 1}; // public: int buttn_change = 0; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void buttn_ini(void) // buttons initialization { TRISA |= 0x0800; // RA11 is button 3 TRISC |= 0x2000; // RC13 is button 5 TRISD |= 0x0208; // RD9 & RD3 are buttons 1 & 2 TRISF |= 0x0040; // RF6 id button 4 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void buttn_run(void) // scanning button states { static int debounce = 0; static int reachtop = 0; if ((PORTBUT1WAVE) // if button 1 released && (PORTBUT2MODN) // and button 2 released && (PORTBUT3DCO2) // and button 3 released && (PORTBUT4MIDI) // and button 4 released && (PORTBUT5TUNE)) // and button 5 released { if (debounce) debounce --; // debounce else reachtop = 0; return; } else // if any pressed { if (reachtop) return; // if top reached return debounce ++; // increments value for shoot if (debounce < DBOUNC) return; // if not reached level return } if (! PORTBUT1WAVE) // if button 1 pressed { g_butwave ++; // advance wave g_butwave &= 0x03; // truncate dsply_write(DSPLWAVE, buttn_led[g_butwave]); // show } if (! PORTBUT2MODN) // if button 2 pressed { g_butmodn ++; // advance modulation g_butmodn &= 0x03; // truncate dsply_write(DSPLMODN, buttn_led[g_butmodn]); // show } if (! PORTBUT3DCO2) // if button 3 pressed { g_butdco2 = // change status (g_butdco2 == DCO2ON) ? DCO2OF : DCO2ON; // toggle status dsply_write(DSPLDCO2, g_butdco2); // shows selection } if ((g_buttune == TUNEOFF) // ignore if in tune state && (! PORTBUT4MIDI)) // if button 4 pressed { g_butmidi ++; // advance midi channel g_butmidi &= 0x000F; // truncate dsply_write(DSPLMIDI, g_butmidi); // shows selection } if (! PORTBUT5TUNE) // if button 5 pressed { g_buttune ++; // advancing selection if (g_buttune >= 3) g_buttune = 0; // toggle switch(g_buttune) { case TUNEOFF: dsply_write(DSPLMIDI, g_butmidi);// shows midi ch break; case TNHALFT: dsply_write(DSPLMIDI, 16); // shows 'H' character break; case TNPITCH: dsply_write(DSPLMIDI, 17); // shows 'P' character break; } } reachtop = 1; // flag reach debounce buttn_change = 1; // flag button change } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void buttn_show(void) // shows buttons status { dsply_write(DSPLWAVE, buttn_led[g_butwave]); // shows selection dsply_write(DSPLMODN, buttn_led[g_butmodn]); // shows selection dsply_write(DSPLDCO2, g_butdco2); // shows button selection dsply_write(DSPLMIDI, g_butmidi); // shows button selection if (g_buttune == TNHALFT) dsply_write(DSPLMIDI, 16); if (g_buttune == TNPITCH) dsply_write(DSPLMIDI, 17); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // buttn.h - buttons on check and display statuses // version 1.02 - 20070611 - optimizing buttons debounce // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // buttons 1 to 5 are allocated to RD9, RD3, RA11, RF6, RC13 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //#define MODOFF 0 #define MODFRQ 0 #define MODAMP 1 #define MODWID 2 #define MODWAR 3 #define TUNEOFF 0 #define TNHALFT 1 #define TNPITCH 2 #define DCO2OF 0 #define DCO2ON 1 #define PORTBUT1WAVE PORTDbits.RD9 #define PORTBUT2MODN PORTDbits.RD3 #define PORTBUT3DCO2 PORTAbits.RA11 #define PORTBUT4MIDI PORTFbits.RF6 #define PORTBUT5TUNE PORTCbits.RC13 void buttn_ini(void); // buttons initialization void buttn_run(void); // scanning button states void buttn_show(void); // shows initial status // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dacon.c - D/A converter // version 1.00 - 20070525 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "dacon.h" #define defined_in extern // defined external #include "glob.h" // global variables // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dacon_ini(void) // D/A converter initialization { // DA converter init TRISD &= 0xFEFB; // port D bits 2 and 8 as output TRISF &= 0xFFC0; // port F bits 0 to 5 as output } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void dacon_write(void) // write sample to A/D converter { int hi, lo; // split for DA converter g_sample += 2048; // bias for unsigned hi = g_sample >> 6; // high order 6 bits lo = g_sample & 0x003F; // low order 6 bits PORTDbits.RD2 = 0; // DA reset clock latch high PORTDbits.RD8 = 0; // DA reset clock latch low PORTF = hi; // DA output high part PORTDbits.RD2 = 1; // DA positive clock latch high PORTF = lo; // DA output low part PORTDbits.RD8 = 1; // DA positive clock latch low } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dacon.h - D/A converter // version 1.00 - 20070525 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dacon_ini(void); // D/A converter initialization void dacon_write(void); // write sample to A/D converter // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /********************************************************************** * © 2005 Microchip Technology Inc. * * FileName: DataEEPROM.h * Dependencies: Header (.h) files if applicable, see below * Processor: dsPIC30Fxxxx * Compiler: MPLAB® C30 v1.32.00 or higher * IDE: MPLAB® IDE v7.20.01 or later * Dev. Board Used: dsPICDEM 1.1 Development Board * Hardware Dependencies: None * * SOFTWARE LICENSE AGREEMENT: * Microchip Technology Inc. (“Microchip”) licenses this software to you * solely for use with Microchip dsPIC® digital signal controller * products. The software is owned by Microchip and is protected under * applicable copyright laws. All rights reserved. * * SOFTWARE IS PROVIDED “AS IS.” MICROCHIP EXPRESSLY DISCLAIMS ANY * WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP * BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), * ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. * * REVISION HISTORY: *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Author Date Comments on this revision *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Erminio Bonizonni/HV 11/02/05 First release of source file * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * ADDITIONAL NOTES: * **********************************************************************/ #define WORD 1 #define ROW 16 #define ALL_EEPROM 0xFFFF #define ERROREE -1 /* * ReadEErow prototype: * Parameters Definition: * Page: is the 8 most significant bits of the source address in EEPROM * Offset: is 16 least significant bits of the source address in EEPROM * DataOut: is the 16-bit address of the destination RAM location or array * Size: is the number of words to read from EEPROM and is a value of 1 or 16 * Return Value: * Function returns ERROREE (or -1) if Size is invalid */ extern int ReadEE(int Page, int Offset, int* DataOut, int Size); /* * EraseEErow prototype: * Parameters Definition: * Page: is the 8 most significant bits of the address in EEPROM to be erased * Offset: is 16 least significant bits of the address in EEPROM to be erased * Size: is the number of words to read from EEPROM and is a value of 1, 16 or * 0xFFFF (for erasing ALL EEPROM memory) * Return Value: * Function returns ERROREE (or -1) if Size is invalid */ extern int EraseEE(int Page, int Offset, int Size); /* * WriteEErow prototype: * Parameters Definition: * Page: is the 8 most significant bits of the destination address in EEPROM * Offset: is 16 least significant bits of the destination address in EEPROM * DataIn: is the 16-bit address of the source RAM location or array * Size: is the number of words to read from EEPROM and is a value of 1 or 16 * Return Value: * Function returns ERROREE (or -1) if Size is invalid */ extern int WriteEE(int* DataIn, int Page, int Offset, int Size); /********************************************************************** * © 2005 Microchip Technology Inc. * * FileName: DataEEPROM.s * Dependencies: Header (*.inc/.h) files if applicable, see below * Processor: dsPIC30Fxxxx * Compiler: MPLAB® C30 v1.32.00 or higher * IDE: MPLAB® IDE v7.21 or later * Dev. Board Used: dsPICDEM 1.1 Development Board * Hardware Dependencies: None * * SOFTWARE LICENSE AGREEMENT: * Microchip Technology Inc. (“Microchip”) licenses this software to you * solely for use with Microchip dsPIC® digital signal controller * products. The software is owned by Microchip and is protected under * applicable copyright laws. All rights reserved. * * SOFTWARE IS PROVIDED “AS IS.” MICROCHIP EXPRESSLY DISCLAIMS ANY * WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP * BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), * ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. * * REVISION HISTORY: *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Author Date Comments on this revision *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * EB/HV 11/02/05 First release of source file * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * ADDITIONAL NOTES: **********************************************************************/ .include "p30fxxxx.inc" .equ EE_WORD_ERASE_CODE, 0x4044 .equ EE_WORD_WRITE_CODE, 0x4004 .equ EE_ROW_ERASE_CODE, 0x4045 .equ EE_ROW_WRITE_CODE, 0x4005 .equ EE_ALL_ERASE_CODE, 0x4046 .equ CONFIG_WORD_WRITE_CODE, 0x4006 .global _ReadEE .global _EraseEE .global _WriteEE .section .text /* DATA EEPROM Read Routines */ _ReadEE: push TBLPAG mov w0, TBLPAG cp w3, #1 bra z, L0 cp w3, #16 bra z, L0 mov #-1, w0 bra L1 L0: tblrdl [w1++],[w2++] dec w3, w3 bra nz, L0 L1: pop TBLPAG return /* DATA EEPROM Erase Routines */ _EraseEE: push.d w4 bclr SR, #Z mov #EE_WORD_ERASE_CODE, W4 cp w2, #1 bra z, L2 mov #EE_ROW_ERASE_CODE, W4 cp w2, #16 bra z, L2 mov #EE_ALL_ERASE_CODE, W4 mov #0xFFFF, w5 cp w2, w5 bra z, L2 mov #-1, w0 pop.d w4 return L2: push TBLPAG mov W0, NVMADRU mov W1, NVMADR mov W4, NVMCON push SR mov #0xE0, W0 ior SR mov #0x55, W0 mov W0, NVMKEY mov #0xAA, W0 mov W0, NVMKEY bset NVMCON, #WR nop nop L3: btsc NVMCON, #WR bra L3 clr w0 pop SR L4: pop TBLPAG pop.d w4 return /* DATA EEPROM Write Routines */ _WriteEE: push w4 bclr SR, #Z mov #EE_WORD_WRITE_CODE, W4 cp w3, #1 bra z, L5 mov #EE_ROW_WRITE_CODE, W4 cp w3, #16 bra z, L5 pop w4 mov #-1, w0 return L5: push TBLPAG mov W1, TBLPAG push W2 L6: tblwtl [W0++],[W2++] dec w3, w3 bra nz, L6 mov W1, NVMADRU pop W2 mov W2, NVMADR mov W4, NVMCON push SR mov #0xE0, W0 ior SR mov #0x55, W0 mov W0, NVMKEY mov #0xAA, W0 mov W0, NVMKEY bset NVMCON, #WR nop nop L7: btsc NVMCON, #WR bra L7 clr w0 pop SR pop TBLPAG pop w4 return .end // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dca.c - digital controlled attenuator // version 1.00 - 20070604 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "dca.h" #define defined_in extern // defined external #include "glob.h" // global variables extern int logvalue[]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static long dca_value = 0; // value signal static int dca_gain = 0; // value level // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void dca_run(void) // attenuation function { dca_value = (long)g_sample * (long)dca_gain; // 19 bits value g_sample = (int)(dca_value >> 7); // 19 to 12 bits } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void dca_set(int gain) // set dca gain { dca_gain = gain; // 7 bits value } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dca.h - digital controlled attenuator // version 1.00 - 20070604 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dca_run(void); // dca attenuation function void dca_set(int gain); // set attenuation value // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dco.c - digital controlled oscillator // version 1.04 - 20070612 // version 1.05 - 20070614 - pointed structs to dco and portm // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // direct digital synthesis with 18 bits accumulation // acumphase .... .... .... .... .... .... .... .... 32 bits // deltaphase xx xxxx xxxx xxxx xxxx 18 bits // wavindex xx xxxx 6 bits: 0-63 // wavindex xx xx 4 bits: 0-15 // wavindex xx x 3 bits: 0-7 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define FCY 20000000 // cycle machine frequency #include "p30f3014.h" #include "string.h" #include "dco.h" #include "buttn.h" #include "minmax.h" #define defined_in extern // defined external #include "glob.h" // global variables extern unsigned int deltaphase[20][12]; // delta table according midi note extern int sinewave[]; // sine waveform samples extern int sawtooth[]; // sawtooth waveform samples extern int triangular[]; // triangular waveform samples extern int expvalue[]; // exponential extern int logvalue[]; // logarithmic extern int portm_phnew[]; // portm member static unsigned long dco_acumph[2]; // phase acumulator static int * dco_pntwave; // pointer for waveform // public: unsigned int dco_deltph[2]; // delta of midi note int dco_treshsquare; // treshold for square width // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void dco_calc_ph(int note) // delta phase calculation { static unsigned int phase; // phase for note unsigned int relphase; // relative phase for note int octave; // octave relative number int pitch; int ntaux; // auxiliar for note // DCO1 ntaux = note + (g_o1half >> 7) - 16; // half tone shift pitch = g_o1ptch / 205; // 204.8 relphase = deltaphase[pitch][ntaux % 12]; octave = (127 - ntaux + 4) / 12; // determine octave phase = relphase >> octave; // deltaphase result portm_phnew[0] = phase; // DCO2 ntaux = note + (g_o2half >> 7) - 16; // half tone shift pitch = g_o2ptch / 205; // 204.8 relphase = deltaphase[pitch][ntaux % 12]; octave = (127 - ntaux + 4) / 12; // determine octave phase = relphase >> octave; // deltaphase result portm_phnew[1] = phase; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void dco_run(void) // runs dco and set g_sample { //#define SHFT 12 // delta phase bits - 64 samples //#define MASK 0x003F // max.index for 64 samples #define SHFT 14 // delta phase bits - 16 samples #define MASK 0x000F // max.index for 16 samples int i, j; // wavetable indexes int sample, aux; // wavetable sample int fractn; // fractional part of acumphase long linint; // linear interpolation value // DCO1 dco_acumph[0] += dco_deltph[0]; // phase advancing dco_acumph[0] &= 0x0003FFFF; // truncate over 18 bits i = dco_acumph[0] >> SHFT; // 6 bits hi for 64 samp 14 bits // linear interpolation fractn = dco_acumph[0] - (i << SHFT); // acum frac for 64 samp 14 bits j = (i + 1) & MASK; // next sample index linint = dco_pntwave[j] - dco_pntwave[i]; // interval for interpolate linint *= fractn; // fraction linint = linint >> SHFT; // convert 64 samp 14 bits sample = dco_pntwave[i] + linint; // sample value // end of linear interpolation sample = sample >> 2; // reduce 14 to 12 bits if (g_butwave == SQU) // if square { sample = sample * 4 + dco_treshsquare; sample = min(sample, 2000); sample = max(sample, -2000); } // DCO2 aux = sample; // save DCO1 sample dco_acumph[1] += dco_deltph[1]; // phase advancing dco_acumph[1] &= 0x0003FFFF; // truncate over 18 bits i = dco_acumph[1] >> SHFT; // 6 bits hi for 64 samp 14 bits // linear interpolation fractn = dco_acumph[1] - (i << SHFT); // acum frac for 64 samp 14 bits j = (i + 1) & MASK; // next sample index linint = dco_pntwave[j] - dco_pntwave[i]; // interval for interpolate linint *= fractn; // fraction linint = linint >> SHFT; // convert 64 samp 14 bits sample = dco_pntwave[i] + linint; // sample value // end of linear interpolation sample = sample >> 2; // reduce 14 to 12 bits if (g_butwave == SQU) // if square { sample = sample * 4 + dco_treshsquare; sample = min(sample, 2000); sample = max(sample, -2000); } g_sample = (g_butdco2 == DCO2ON) ? (sample + aux) >> 2 // 11 bits output : aux >> 1; // 11 bits output } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dco_set_wave(void) // set waveform { switch (g_butwave) { case SIN: dco_pntwave = sinewave; break; case SAW: dco_pntwave = sawtooth; break; case TRI: dco_pntwave = triangular; break; case SQU: dco_pntwave = triangular; break; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dco.h - digital controlled oscillator // version 1.04 - 20070612 // version 1.05 - 20070614 - pointed structs to dco and portm // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // direct digital synthesis with 18 bits accumulation // acumphase .... .... .... .... .... .... .... .... 32 bits // deltaphase xx xxxx xxxx xxxx xxxx 18 bits // wavindex xx xxxx 6 bits: 0-63 // wavindex xx xx 4 bits: 0-15 // wavindex xx x 3 bits: 0-7 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define SAW 0 #define TRI 1 #define SIN 2 #define SQU 3 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dco_calc_ph(int note); // deltaphase calculation void dco_run(void); // runs dco and set g_sample void dco_set_wave(void); // set waveform // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dsply.c - display functions for hardware version 1.03 // version 1.01 - 20070601 // version 1.07 - 20070615 - clear overrun - optimizing // display hardware is a 16 bits shift register positive clock // that controls 9 leds and a 7 segment display // clock is RD0, data is RD1 // first bits are for leds 1 to 8 // following 7 bits are for 7 segments display // last bit is for lower led // function use: dsply_write(int numb, int msg); // numb: display number DSPLWAVE, DSPLMODN, DSPLDCO2, DSPLMIDI // msg: value to be displayed 0 to F, H, t and blank // // internals // dispbuffer layout // D3= ===========D7SEG========== ======D2====== ======D1====== // d15 d14 d13 d12 d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 // L9 E D C A B F G L5 L6 L7 L8 L4 L3 L2 L1 // // characters representation in 7 segments display // ver 3 7654 3210 // dig EDC ABFG hex dig EDC ABFG hex dig EDC ABFG hex // '0' x000 0001 0x01 '8' x000 0000 0x00 'H' x010 1000 0x28 // '1' x110 1011 0x6B '9' x100 0000 0x40 'P' x011 0000 0x30 // '2' x001 0010 0x12 'A' x010 0000 0x20 't' x001 1100 0x1C // '3' x100 0010 0x42 'b' x000 1100 0x0C ' ' x111 1111 0x7F // '4' x110 1000 0x68 'C' x001 0101 0x15 // '5' x100 0100 0x44 'd' x000 1010 0x0A // '6' x000 0100 0x04 'E' x001 0100 0x14 // '7' x110 0011 0x63 'F' x011 0100 0x34 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "dsply.h" #include "buttn.h" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dsply_ini(void) // display initialization { TRISD &= 0xFFFC; // port D bits 0 & 1 as output PORTD = 0x0001; // clock high } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void dsply_write (int numb, int msg) // display write { static unsigned int dispbuffer = 0xFFFF;// all displays off static unsigned int hexchar[20] = // 0 to F, H, P, t, and ' ' { 0x01, 0x6B, 0x12, 0x42, 0x68, 0x44, 0x04, 0x63, // '0'to'7' 0x00, 0x40, 0x20, 0x0C, 0x15, 0x0A, 0x14, 0x34, // '8'to'F' 0x28, 0x30, 0x1C, 0x7F}; // 'H', 'P', 't', ' ' int i; // buffer index unsigned int savebuffer; // buffer save area unsigned int databit; // data bit to transfer switch(numb) { case DSPLWAVE: // DCO wave display 1 savebuffer = 0; for (i = 0; i < 4; i ++) // inverts bits order { savebuffer = savebuffer << 1; databit = msg & 0x0001; savebuffer |= databit; msg = msg >> 1; } msg = savebuffer; dispbuffer &= 0xFFF0; // clear nibble msg |= 0xFFF0; // clear unused message part dispbuffer |= ~msg; // load into buffer break; case DSPLMODN: // modulation display 2 dispbuffer &= 0xFF0F; // clear nibble msg = msg << 4; // positioning in nibble msg |= 0xFF0F; // clear unused message part dispbuffer |= ~msg; // load into buffer break; case DSPLDCO2: // dco on off display dispbuffer &= 0x7FFF; // clear bit if (msg == DCO2OF) // if off dispbuffer |= 0x8000; // reset bit into buffer break; case DSPLMIDI: // 7 segment display msg = hexchar[msg]; msg = msg << 8; // positioning in nibble msg &= 0x7F00; // clear low order dispbuffer &= 0x80FF; // clear nibbles dispbuffer |= msg; // load into buffer break; } savebuffer = dispbuffer; // save for (i = 0; i < 16; i ++) // serial transmission { databit = dispbuffer & 0x0001; // low order bit PORTDbits.RD0 = 0; // clock 0 PORTDbits.RD1 = databit; // data to be transmitted msg = 0; // force delay PORTDbits.RD0 = 1; // positive clock pulse dispbuffer = dispbuffer >> 1; // next bit } dispbuffer = savebuffer; // restore } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dsply.h - display functions for hardware version 1.03 // version 1.01 - 20070601 // version 1.07 - 20070615 - clear overrun - optimizing // display hardware is a 16 bits shift register positive clock // that controls 9 leds and a 7 segment display // clock is RD0, data is RD1 // first bits are for leds 1 to 8 // following 7 bits are for 7 segments display // last bit is for lower led // function use: dsply_write(int numb, int msg); // numb: display number DSPLWAVE, DSPLMODN, DSPLDCO2, DSPLMIDI // msg: value to be displayed 0 to F, H, t and clear // // internals // dispbuffer layout // D3= ===========D7SEG========== ======D2====== ======D1====== // d15 d14 d13 d12 d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 // L9 E D C A B F G L5 L6 L7 L8 L4 L3 L2 L1 // // characters representation in 7 segments display // ver 3 7654 3210 // dig EDC ABFG hex dig EDC ABFG hex dig EDC ABFG hex // '0' x000 0001 0x01 '8' x000 0000 0x00 'H' x010 1000 0x28 // '1' x110 1011 0x6B '9' x100 0000 0x40 'P' x011 0000 0x30 // '2' x001 0010 0x12 'A' x010 0000 0x20 't' x001 1100 0x1C // '3' x100 0010 0x42 'b' x000 1100 0x0C ' ' x111 1111 0x7F // '4' x110 1000 0x68 'C' x001 0101 0x15 // '5' x100 0100 0x44 'd' x000 1010 0x0A // '6' x000 0100 0x04 'E' x001 0100 0x14 // '7' x110 0011 0x63 'F' x011 0100 0x34 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define DSPLWAVE 0 #define DSPLMODN 1 #define DSPLDCO2 2 #define DSPLMIDI 3 void dsply_ini(void); // display initialization void dsply_write (int numb, int msg); // display write // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // env.c - envelopes sampled by env_adsr_run() and env_ar_run() // version 1.02 - 20070605 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "env.h" #include "minmax.h" #define defined_in extern // defined externally #include "glob.h" // global variables extern int logvalue[]; extern int expvalue[]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static int env_en1atk; // P9 env1 ar attack static int env_en1rel; // P11 env1 ar release static int env_en2atk; // P6 env2 adsr attack static int env_en2dec; // P8 env2 adsr decay static int env_en2sus; // P10 env2 adsr sustain static int env_en2rel; // P12 env2 adsr release static long env_count_adsr = 0; // value counter adsr static int env_step_adsr = 0; // state adsr static int env_notes_on = 0; // active notes counter static long env_count_ar = 0; // value counter ar static int env_step_ar = 0; // state ar // public: int env_en1swp; // P13 env1 ar sweep int env_value_ar = 0; // value shape ar int env_value_adsr; // value shape adsr // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void env_adsr_off(void) // ADSR stop { env_notes_on --; // sinalize notes active } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void env_adsr_on(void) // ADSR start { env_notes_on ++; // sinalize notes active env_step_adsr = ATK; // starts attack step } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void env_adsr_run(void) // ADSR envelope shape step { switch(env_step_adsr) // analize step { case STOP: break; // inactive case ATK: // attack env_count_adsr += env_en2atk; env_value_adsr = env_count_adsr >> 9; if (env_value_adsr >= ENVMAX) // if reach the top { env_value_adsr = ENVMAX; // ensure level env_step_adsr = DEC; // set decay status } break; case DEC: // decay env_count_adsr -= env_en2dec; env_value_adsr = env_count_adsr >> 9; if (env_value_adsr <= env_en2sus)// if reach the sustain { env_value_adsr = env_en2sus;// ensure level env_step_adsr = SUS; // set sustain status } break; case SUS: // sustain if (! env_notes_on) // if no notes active env_step_adsr = REL; // start release step break; case REL: // release env_count_adsr -= env_en2rel; env_value_adsr = env_count_adsr >> 9; if (env_value_adsr <= 0) // if reach the floor { env_value_adsr = 0; // ensure level env_count_adsr = 0; env_step_adsr = STOP; // set end status } break; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void env_adsr_set(void) // ser ADSR values { env_en2atk = expvalue[g_en2atk >> 5] + 1; // P6 env2 adsr attack env_en2dec = expvalue[g_en2dec >> 5] + 1; // P8 env2 adsr decay env_en2sus = g_en2sus >> 5; // P10 env2 adsr sustain env_en2rel = expvalue[g_en2rel >> 5] + 1; // P12 env2 adsr release } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline int env_ar_get(void) // returns AR shape value { return env_value_ar * env_en1swp / ENVMAX; // returns AR shape val } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void env_ar_on(void) // AR start { env_value_ar = 0; // trunc possible running shape env_count_ar = 0; // initialize env_step_ar = ATK; // starts attack step } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void env_ar_run(void) // AR envelope shape step { switch(env_step_ar) // analize step { case STOP: break; // inactive case ATK: // attack env_count_ar += env_en1atk; env_value_ar = env_count_ar >> 9; if (env_value_ar >= ENVMAX) // if reach the top { env_value_ar = ENVMAX; // ensure level env_step_ar = REL; // set release status } break; case REL: // release env_count_ar -= env_en1rel; env_value_ar = env_count_ar >> 9; if (env_value_ar <= 0) // if reach the floor { env_value_ar = 0; // ensure level env_count_ar = 0; env_step_ar = STOP; // set end status } break; } env_value_ar = (env_value_ar * env_en1swp) >> 7; // set AR shape } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void env_ar_set() // ser ARS values from global { env_en1atk = expvalue[g_en1atk >> 5] + 1; // P6 env2 ar attack env_en1rel = expvalue[g_en1rel >> 5] + 1; // P12 env2 ar release env_en1swp = ENVMAX - (g_en1swp >> 4); // P13 env1 ar sweep } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // env.h - envelopes sampled by timer1 at 20 KHz // version 1.02 - 20070605 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void env_adsr_off(void); // ADSR stop void env_adsr_on(void); // ADSR start void env_adsr_run(void); // ADSR envelope shape step void env_adsr_set(void); // set ADSR values from gobal void env_ar_on(void); // AR start void env_ar_run(void); // AR envelope shape step void env_ar_set(void); // set ARS values // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define STOP 0 // envelope status stop #define ATK 1 // envelope status attack #define DEC 2 // envelope status decay #define SUS 3 // envelope status sustain #define REL 4 // envelope status release #define ENVMAX 127 // maximum envelope value // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // logen - logarithmic table generator - ver.1.01 - 20070602 // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // output file name with extension: expt.c // step in db: 0.570000 // mode A:ascending D:descending: D // resolution in bits: 12 // samples quantity: 128 // resol.max.val: 4096 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unsigned int expvalue[128] = { 0x0FFF, 0x0EFA, 0x0E07, 0x0D23, 0x0C4D, 0x0B85, 0x0ACA, 0x0A1A, 0x0976, 0x08DC, 0x084C, 0x07C5, 0x0747, 0x06D0, 0x0662, 0x05FA, 0x0599, 0x053E, 0x04E8, 0x0498, 0x044E, 0x0408, 0x03C6, 0x0389, 0x034F, 0x0319, 0x02E7, 0x02B8, 0x028C, 0x0262, 0x023B, 0x0217, 0x01F5, 0x01D5, 0x01B7, 0x019B, 0x0181, 0x0169, 0x0152, 0x013C, 0x0128, 0x0115, 0x0104, 0x00F3, 0x00E4, 0x00D5, 0x00C8, 0x00BB, 0x00AF, 0x00A4, 0x0099, 0x0090, 0x0086, 0x007E, 0x0076, 0x006E, 0x0067, 0x0061, 0x005B, 0x0055, 0x004F, 0x004A, 0x0046, 0x0041, 0x003D, 0x0039, 0x0035, 0x0032, 0x002F, 0x002C, 0x0029, 0x0026, 0x0024, 0x0022, 0x001F, 0x001D, 0x001B, 0x001A, 0x0018, 0x0016, 0x0015, 0x0014, 0x0012, 0x0011, 0x0010, 0x000F, 0x000E, 0x000D, 0x000C, 0x000B, 0x000B, 0x000A, 0x0009, 0x0009, 0x0008, 0x0008, 0x0007, 0x0007, 0x0006, 0x0006, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004, 0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // filt.c - simplest IIR with resonance - fixed point arithmetic // version 1.01 - 20070603 // version 1.07 - 20070615 - clear overrun - optimizing // set feedback amount f given m and q between 0 and 1 // f = q + q/(1.0 - m); // for each sample... // y[i-1] = y[i-1] + m * (x[i] - y[i-1] + f * (y[i-1] - y[i])); // y[i] = y[i] + m * (y[i-1] - y[i]); // to symbolic pseudo-code: // y[i-1] = y1; y[i] = y0; x[i] = input; m = filt_frq; f = filt_fbk // y1 += filt_frq * (input - y1 + filt_fbk * (y1 - y0)); // y0 += filt_frq * (y1 - y0); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "filt.h" #include "minmax.h" #define defined_in extern // defined externally #include "glob.h" // global variables static unsigned int filt_frq; // IIR fracionary freq static int filt_fbk; // feedback coeficient // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void filt_run(void) // values +/- 2048 { static int y0 = 0; // sample y[i] static int y1 = 0; // sample y[i-1] long aux; int feedback; aux = filt_fbk; // prepare for aux *= (y1 - y0); // feedback calc aux = aux >> 10; // divides by 1024 aux = min(aux, 1023); // prevents saturation aux = max(aux, -1023); // prevents saturation feedback = aux; aux = filt_frq; aux *= (g_sample - y1 + feedback); aux = aux >> 10; // divides by 1024 y1 += aux; aux = filt_frq; aux *= (y1 - y0); aux = aux >> 10; // divides by 1024 y0 += aux; g_sample = y0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void filt_set(int env_ar) // frequency & resonance set { // values from 0 to 4095 #define MAXFRQ 820 long aux, fee; unsigned int q; // resonance coeficient filt_frq = g_filfrq / 5; // fract.of 1024 limit.to 819 filt_frq += env_ar; // AR modulation filt_frq = min(filt_frq, MAXFRQ); // limit the range again q = g_filres >> 2; // resonance as fract 1024 // filt_fbk = g_q + g_q / (1 - filt_frq); <- set feedback coef. fee = q; // prepare into long for fee <<= 10; // multiplying by 1024 aux = fee / (1024 - filt_frq); filt_fbk = q + aux; // feedback coef.fract 1024 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // filt.h - simplest IIR with resonance - fixed point arithmetic // version 1.01 - 20070603 // version 1.07 - 20070615 - clear overrun - optimizing // set feedback amount f given m and q between 0 and 1 // f = q + q/(1.0 - m); // for each sample... // y[i-1] = y[i-1] + m * (x[i] - y[i-1] + f * (y[i-1] - y[i])); // y[i] = y[i] + m * (y[i-1] - y[i]); // to symbolic pseudo-code: // y[i-1] = y1; y[i] = y0; x[i] = input; m = filt_frq; f = filt_fbk // y1 += filt_frq * (input - y1 + filt_fbk * (y1 - y0)); // y0 += filt_frq * (y1 - y0); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void filt_run(void); // filter function void filt_set(int env_ar); // frequency resonance setting // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // dtgen - delta phase table generator - ver.1.06 - 20070612 // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // half tone divisions: 10 // note frequ.reference (220 to 440): 330 // output file name with extension: freq.c // quantity of notes: 2 // resolution in bits: 18 // sample frequency: 25000 // resol.max.val: 262144 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unsigned int deltaphase[20][12] = { {0x6610, 0x6C22, 0x7290, 0x7960, 0x8098, 0x883D, 0x9057, 0x98EC, 0xA204, 0xABA7, 0xB5DC, 0xC0AC}, {0x66A8, 0x6CC2, 0x733A, 0x7A14, 0x8156, 0x8907, 0x912D, 0x99CF, 0xA2F5, 0xACA5, 0xB6E9, 0xC1CA}, {0x6740, 0x6D64, 0x73E5, 0x7AC9, 0x8216, 0x89D2, 0x9204, 0x9AB3, 0xA3E6, 0xADA5, 0xB7F9, 0xC2E9}, {0x67D9, 0x6E06, 0x7491, 0x7B7F, 0x82D7, 0x8A9F, 0x92DD, 0x9B99, 0xA4D9, 0xAEA7, 0xB909, 0xC40A}, {0x6873, 0x6EA9, 0x753E, 0x7C36, 0x8399, 0x8B6C, 0x93B7, 0x9C7F, 0xA5CE, 0xAFAA, 0xBA1C, 0xC52D}, {0x690E, 0x6F4D, 0x75EB, 0x7CEE, 0x845C, 0x8C3B, 0x9492, 0x9D67, 0xA6C4, 0xB0AE, 0xBB30, 0xC651}, {0x69AA, 0x6FF2, 0x769A, 0x7DA8, 0x8521, 0x8D0B, 0x956E, 0x9E51, 0xA7BB, 0xB1B4, 0xBC45, 0xC777}, {0x6A46, 0x7098, 0x774A, 0x7E62, 0x85E6, 0x8DDC, 0x964C, 0x9F3C, 0xA8B4, 0xB2BC, 0xBD5D, 0xC89F}, {0x6AE4, 0x713F, 0x77FB, 0x7F1D, 0x86AD, 0x8EAF, 0x972B, 0xA028, 0xA9AE, 0xB3C5, 0xBE75, 0xC9C9}, {0x6B82, 0x71E7, 0x78AD, 0x7FDA, 0x8774, 0x8F82, 0x980B, 0xA115, 0xAAA9, 0xB4CF, 0xBF90, 0xCAF4}, {0x6C22, 0x7290, 0x7960, 0x8098, 0x883D, 0x9057, 0x98EC, 0xA204, 0xABA7, 0xB5DC, 0xC0AC, 0xCC21}, {0x6CC2, 0x733A, 0x7A14, 0x8156, 0x8907, 0x912D, 0x99CF, 0xA2F5, 0xACA5, 0xB6E9, 0xC1CA, 0xCD50}, {0x6D64, 0x73E5, 0x7AC9, 0x8216, 0x89D2, 0x9204, 0x9AB3, 0xA3E6, 0xADA5, 0xB7F9, 0xC2E9, 0xCE80}, {0x6E06, 0x7491, 0x7B7F, 0x82D7, 0x8A9F, 0x92DD, 0x9B99, 0xA4D9, 0xAEA7, 0xB909, 0xC40A, 0xCFB2}, {0x6EA9, 0x753E, 0x7C36, 0x8399, 0x8B6C, 0x93B7, 0x9C7F, 0xA5CE, 0xAFAA, 0xBA1C, 0xC52D, 0xD0E6}, {0x6F4D, 0x75EB, 0x7CEE, 0x845C, 0x8C3B, 0x9492, 0x9D67, 0xA6C4, 0xB0AE, 0xBB30, 0xC651, 0xD21C}, {0x6FF2, 0x769A, 0x7DA8, 0x8521, 0x8D0B, 0x956E, 0x9E51, 0xA7BB, 0xB1B4, 0xBC45, 0xC777, 0xD354}, {0x7098, 0x774A, 0x7E62, 0x85E6, 0x8DDC, 0x964C, 0x9F3C, 0xA8B4, 0xB2BC, 0xBD5D, 0xC89F, 0xD48D}, {0x713F, 0x77FB, 0x7F1D, 0x86AD, 0x8EAF, 0x972B, 0xA028, 0xA9AE, 0xB3C5, 0xBE75, 0xC9C9, 0xD5C8}, {0x71E7, 0x78AD, 0x7FDA, 0x8774, 0x8F82, 0x980B, 0xA115, 0xAAA9, 0xB4CF, 0xBF90, 0xCAF4, 0xD705}, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // glob.h - global variables // version 1.00 - 20070606 // version 1.05 - 20070614 - pointed structs to dco and portm // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // buttons defined_in int g_butwave; // waveform selection defined_in int g_butmodn; // modulation defined_in int g_butdco2; // DCO2 on/off defined_in int g_butmidi; // midi channel advance defined_in int g_buttune; // tune: halftone/pitch/off // potentiometers defined_in int g_sqwide; // p1 width defined_in int g_o1half; // p1 dco1 halftone tune defined_in int g_o1ptch; // p1 dco1 pitch tune defined_in int g_portam; // p2 portamento defined_in int g_o2half; // p2 dco2 halftone tune defined_in int g_o2ptch; // p2 dco2 pitch tune defined_in int g_lfofrq; // p3 lfo frequ defined_in int g_lfolev; // p4 lfo level defined_in int g_filfrq; // p5 filter frequ defined_in int g_filres; // p7 filter resonance defined_in int g_en1atk; // p9 env1 ar attack defined_in int g_en1rel; // p11 env1 ar release defined_in int g_en1swp; // p13 env1 ar sweep defined_in int g_en2atk; // p6 env2 adsr attack defined_in int g_en2dec; // p8 env2 adsr decay defined_in int g_en2sus; // p10 env2 adsr sustain defined_in int g_en2rel; // p12 env2 adsr release defined_in int g_note; // auxiliar for midi note defined_in int g_velo; // auxiliar for midi velocity defined_in int g_sample; // output sample // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // lfo.c - oscillator sampled at 10KHz // version 1.00 - 20070603 // version 1.07 - 20070615 - clear overrun - optimizing // 20s to 10ms - 0.05 to 100hz // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "lfo.h" #define defined_in extern // defined externally #include "glob.h" // global variables extern int logvalue[]; extern int sinewave[]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static int lfo_level = 0; // lfo level static int lfo_delta; static unsigned long lfo_acum = 0; // phase acum // public: int lfo_value = 0; // value shape lfo // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void lfo_run(void) // lfo sampling { //#define SHFT 12 // delta phase bits - 64 samples //#define MASK 0x003F // max.index for 64 samples #define SHFT 14 // delta phase bits - 16 samples #define MASK 0x000F // max.index for 16 samples int i, j; // wavetable indexes int sample; // wavetable sample int fractn; // fractional part of acumphase long linint; // linear interpolation value lfo_acum += lfo_delta; // phase advancing lfo_acum &= 0x0003FFFF; // truncate over 18 bits i = lfo_acum >> SHFT; // bits hi for n samp 14 bits // linear interpolation fractn = lfo_acum - (i << SHFT); // acum frac for n samp 14 bits j = (i + 1) & MASK; // next sample index linint = sinewave[j] - sinewave[i]; // interval for interpolate linint *= fractn; // fraction linint = linint >> SHFT; // convert 64 samp 14 bits sample = sinewave[i] + linint; // sample value // end of linear interpolation sample = sample >> 2; // reduce 14 to 12 bits linint = (long)sample * (long)lfo_level; // 17 bits value lfo_value = (int)(linint >> 10); // 17 to 7 bits - 128 values } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void lfo_set(void) // set frequency and level { lfo_delta = logvalue[g_lfofrq >> 5] + 1; // avoiding zero lfo_level = g_lfolev >> 7; // 5 bits 32 levels } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // lfo.h - oscillator sampled at 10KHz // version 1.00 - 20070603 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void lfo_run(void); // lfo sampling void lfo_set(void); // set frequency and level // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // logen - logarithmic table generator - ver.1.01 - 20070602 // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // output file name with extension: logt.c // step in db: 0.570000 // mode A:ascending D:descending: A // resolution in bits: 12 // samples quantity: 128 // resol.max.val: 4096 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unsigned int logvalue[128] = { 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0004, 0x0004, 0x0004, 0x0005, 0x0005, 0x0005, 0x0006, 0x0006, 0x0007, 0x0007, 0x0008, 0x0008, 0x0009, 0x0009, 0x000A, 0x000B, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0014, 0x0015, 0x0016, 0x0018, 0x001A, 0x001B, 0x001D, 0x001F, 0x0022, 0x0024, 0x0026, 0x0029, 0x002C, 0x002F, 0x0032, 0x0035, 0x0039, 0x003D, 0x0041, 0x0046, 0x004A, 0x004F, 0x0055, 0x005B, 0x0061, 0x0067, 0x006E, 0x0076, 0x007E, 0x0086, 0x0090, 0x0099, 0x00A4, 0x00AF, 0x00BB, 0x00C8, 0x00D5, 0x00E4, 0x00F3, 0x0104, 0x0115, 0x0128, 0x013C, 0x0152, 0x0169, 0x0181, 0x019B, 0x01B7, 0x01D5, 0x01F5, 0x0217, 0x023B, 0x0262, 0x028C, 0x02B8, 0x02E7, 0x0319, 0x034F, 0x0389, 0x03C6, 0x0408, 0x044E, 0x0498, 0x04E8, 0x053E, 0x0599, 0x05FA, 0x0662, 0x06D0, 0x0747, 0x07C5, 0x084C, 0x08DC, 0x0976, 0x0A1A, 0x0ACA, 0x0B85, 0x0C4D, 0x0D23, 0x0E07, 0x0EFA, 0x0FFF, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // midi.c - functions for MIDI messages received from UART // version 1.00 - 20070525 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define FCY 20000000 // cycle machine frequency #define NOTE_ON 0x0090 // midi command note on #define NOTE_OFF 0x0080 // midi command note off // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "midi.h" #define defined_in extern // defined externally #include "glob.h" // global variables // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void midi_ini(void) // midi initialization { U1MODEbits.UARTEN = 1; // enable UART1 U1MODEbits.ALTIO = 1; // alternate RX to pin 16 U1BRG = 0; U1BRG = ((FCY / 31250) / 16) - 1; // calculate baud register IEC0bits.U1RXIE = 0; // disable reception interrupt U1MODEbits.PDSEL = 0; // parity bits 2 and 1 U1MODEbits.STSEL = 0; // stop bits bit 0 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline int // return 0 if not available midi_parse( // MIDI messages parsing int inbyte) // byte received from UART { static unsigned char note_temp; // auxiliar note number static unsigned char midi_state = 0; // parser automata state unsigned char aux_command; // midi command aux_command = inbyte & 0x00F0; // clear midi channel if ((g_butmidi) // if not all channels && (inbyte & 0x0080) // and is command && ((inbyte & 0x000F) != g_butmidi)) // and is not selected return 0; // ignore message if (aux_command == NOTE_ON) // midi command parsing { midi_state = 1; // first byte processed return 0; // no message complete } if (aux_command == NOTE_OFF) // midi command parsing { midi_state = 4; // first byte note off proces return 0; // no message complete } if ((midi_state == 1) // midi note number parsing || (midi_state == 4)) // for both note on and off { midi_state ++; // appoint to next state note_temp = inbyte; // saves note number return 0; // no message complete } if (midi_state == 2) // velocity value parsing { midi_state = 0; // reset to initial state g_note = note_temp; // returns note g_velo = inbyte; // velocity value received } if (midi_state == 5) // velocity for note off { midi_state = 0; // reset to initial state g_note = note_temp; // returns note g_velo = 0; // for note off assume 0 } return 1; // return values available } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // midi.c - functions for MIDI messages received from UART // version 1.00 - 20070525 // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define NOTE_ON 0x0090 // midi command note on #define NOTE_OFF 0x0080 // midi command note off // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void midi_ini(void); // midi initialization int midi_parse(int inbyte); // midi parser // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifndef MINMAX_H #define MINMAX_H // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // nano.c - main program nanosynth // version 1.01 - 20070611 // version 1.05 - 20070614 - pointed structs to dco and portm // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define FCY 20000000 // cycle machine frequency #include "p30f3014.h" #include "adcon.h" #include "buttn.h" #include "dacon.h" #include "dca.h" #include "dco.h" #include "dsply.h" #include "env.h" #include "filt.h" #include "lfo.h" #include "minmax.h" #include "midi.h" #include "pers.h" #include "portm.h" #include "timer.h" #include "freq.c" // frequency table #include "wave.c" // wave table #define defined_in // defined here the #include "glob.h" // global variables #include "logt.c" // log table #include "expt.c" // exp table _FOSC(CSW_FSCM_OFF & HS2_PLL8) // 20 MHz Xtal = 20 Mips _FWDT(WDT_OFF) // watchdog timer off _FBORPOR(MCLR_DIS & PBOR_OFF & BORV_45) _FGS(CODE_PROT_OFF) // code protection off extern unsigned int dco_deltph[]; extern int buttn_change; extern int dco_treshsquare; extern int env_value_adsr; extern int env_value_ar; extern int lfo_value; void __attribute__((interrupt)) _T1Interrupt(void); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int main(void) { int i, r; adcon_ini(); // AD converters initialize buttn_ini(); // buttons initialization dacon_ini(); // DA converter init dsply_ini(); // display initialization midi_ini(); // midi initialization pers_read(); // read persistent settings buttn_show(); // shows initial selection timer_1_ini_i(453); // int timer1 init 44052.8 Hz // timer_1_ini_i(624); // int timer1 init 32000 Hz // timer_1_ini_i(799); // int timer1 init 25000 Hz // timer_2_ini(1999); // timer 2 init at 10000 Hz timer_2_ini(3999); // timer 2 init at 5000 Hz // load buttons ee status dco_set_wave(); // set waveform while (1) { if (U1STAbits.URXDA) // if MIDI data byte available { i = U1RXREG; // receive message byte r = midi_parse(i); // MIDI parsing if (r) // if message available { if (g_velo) // if NOTE ON message { dco_calc_ph(g_note);// calc phase for portm portm_set_ph(); // load deltaphase env_adsr_on(); // starts ADSR envelope env_ar_on(); // starts AR envelope } else env_adsr_off(); // stops ADSR } } if (IFS0bits.T2IF) // if timer2 triggered { env_adsr_run(); // runs adsr envelope env_ar_run(); // runs ar envelope filt_set(env_value_ar); // set filter frequ and reson lfo_run(); // runs lfo portm_run(); // portamento sampling dca_set(env_value_adsr); // REDUNDANT ...! if (g_butmodn == MODFRQ) // frequence modulation { // updates delta phase dco_deltph[0] += lfo_value << 2; // upd dco_deltph[1] += lfo_value << 2; // upd } (g_butmodn == MODAMP) // amplitude modulation ? dca_set(env_value_adsr + (lfo_value >> 1)) : dca_set(env_value_adsr); if (g_butmodn == MODWID) // pulse width from lfo dco_treshsquare = (lfo_value << 6) + g_sqwide; else if (g_butmodn == MODWAR) // pulse width from ar dco_treshsquare = (env_value_ar << 5) + g_sqwide; else dco_treshsquare = g_sqwide; IFS0bits.T2IF = 0; // reset interruption flag } buttn_run(); // buttons scan r = adcon_read(); // if analog data available if (r) { lfo_set(); // set values for lfo env_ar_set(); // set ars values env_adsr_set(); // set adsr values portm_set_tm(); // loads portamento value if (g_buttune == TNHALFT) // set halftone tune value { dco_calc_ph(g_note); // calc phase for portm portm_set_ph(); // load deltaphase } if (g_buttune == TNPITCH) // set pitch in fractions { dco_calc_ph(g_note); // calc phase for portm portm_set_ph(); // load deltaphase } } if (buttn_change) // buttons events { buttn_change = 0; pers_write(); // write persistent settings dco_set_wave(); // set waveform } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void) { dco_run(); // dco procedure filt_run(); // filter procedure dca_run(); // dca - adsr running /* g_sample = min(g_sample, 2047); // saturation hi g_sample = max(g_sample, -2047); // saturation lo */ dacon_write(); // write output sample IFS0bits.T1IF = 0; // reset timer 1 interrupt flag } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pers.c - persistence in eeprom // version 1.02 - 20070611 - optimizing buttons debounce // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "DataEE.h" #include "buttn.h" #include "dsply.h" #define defined_in extern #include "glob.h" int _EEDATA(32) buttn_ee[16] = // eeprom save area {0, 0, 1, 0, 0, 2000, 2000, 2000, 2100, 0, 0, 0, 0, 0, 0, 0}; // 0 1 2 3 4 5 6 7 8 9 A B C D E F static int pers_save[16]; // ram shadow eeprom // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void pers_read(void) // read from eeprom { ReadEE( // EEPROM loading in ram __builtin_tblpage(buttn_ee), __builtin_tbloffset(buttn_ee), pers_save, ROW); g_butwave = pers_save[0]; g_butmodn = pers_save[1]; g_butdco2 = pers_save[2]; g_butmidi = pers_save[3]; g_buttune = pers_save[4]; g_o1half = pers_save[5]; // p1 dco1 halftone tune g_o1ptch = pers_save[6]; // p1 dco1 pitch tune g_o2half = pers_save[7]; // p2 dco2 halftone tune g_o2ptch = pers_save[8]; // p2 dco2 pitch tune } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void pers_write(void) // write values in eeprom { pers_save[0] = g_butwave; pers_save[1] = g_butmodn; pers_save[2] = g_butdco2; pers_save[3] = g_butmidi; pers_save[4] = g_buttune; pers_save[5] = g_o1half; // p1 dco1 halftone tune pers_save[6] = g_o1ptch; // p1 dco1 pitch tune pers_save[7] = g_o2half; // p2 dco2 halftone tune pers_save[8] = g_o2ptch; // p2 dco2 pitch tune EraseEE( // erase values in eeprom __builtin_tblpage(buttn_ee), __builtin_tbloffset(buttn_ee), ROW); WriteEE(pers_save, // write values in eeprom __builtin_tblpage(buttn_ee), __builtin_tbloffset(buttn_ee), ROW); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pers.h - persistence in eeprom // version 1.02 - 20070611 - optimizing buttons debounce // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void pers_read(void); // buttons initialization void pers_write(void); // write values in eeprom // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // portm.c - portamento sampled at 10KHz // version 1.00 - 20070603 // version 1.05 - 20070614 - pointed structs to dco and portm // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include "p30f3014.h" #include "portm.h" #define defined_in extern // defined externally #include "glob.h" // global variables extern int logvalue[]; extern unsigned int dco_deltph[]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static int portm_phinc[2]; // phase increment static int portm_time = 0; // portamento time // public: int portm_phnew[2]; // new delta phase // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void portm_run(void) // portamento sampling { static unsigned int timer = 1; if (! portm_time) return; // no portamento timer --; // prescaler if (timer) return; timer = portm_time; // reloads timer if ((dco_deltph[0] == portm_phnew[0]) && (dco_deltph[1] == portm_phnew[1])) return; dco_deltph[0] += portm_phinc[0]; if (portm_phinc[0] > 0) { if (dco_deltph[0] > portm_phnew[0]) dco_deltph[0] = portm_phnew[0]; } else { if (dco_deltph[0] < portm_phnew[0]) dco_deltph[0] = portm_phnew[0]; } dco_deltph[1] += portm_phinc[1]; if (portm_phinc[1] > 0) { if (dco_deltph[1] > portm_phnew[1]) dco_deltph[1] = portm_phnew[1]; } else { if (dco_deltph[1] < portm_phnew[1]) dco_deltph[1] = portm_phnew[1]; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void portm_set_ph(void) // set actual midi note phase { portm_phinc[0] = (int)(portm_phnew[0] - dco_deltph[0]) / 20; if (! portm_phinc[0]) portm_phinc[0] = 1; // prevents zero increment portm_phinc[1] = (int)(portm_phnew[1] - dco_deltph[1]) / 20; if (! portm_phinc[1]) portm_phinc[1] = 1; // prevents zero increment } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void portm_set_tm(void) // set portamento time { // portm_time = time >> 4; // loads time value (slow) portm_time = g_portam >> 5; // loads time value if (! portm_time) // if no portamento { dco_deltph[0] = portm_phnew[0]; // set imediately new value dco_deltph[1] = portm_phnew[1]; // set imediately new value } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // portm.h - portamento sampled at 10KHz // version 1.00 - 20070603 // version 1.05 - 20070614 - pointed structs to dco and portm // version 1.06 - 20070614 - dual dco and portm // version 1.07 - 20070615 - clear overrun - optimizing // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void portm_run(void); // portamento sampling void portm_set_ph(void); // set actual midi note phase void portm_set_tm(void); // set portamento time // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // timer.c - timers functions of initialization // version 1.00 - 20070525 // version 1.07 - 20070615 - clear overrun - optimizing // T(measured) = (PRx + 1) * FCY * TMRx prescale = // 4000 * (1/20000000) * 1 = 200 us F = 5000.0 Hz // 2000 * (1/20000000) * 1 = 100 us F = 10000.0 Hz // 1024 * (1/20000000) * 1 = 51.2 us F = 19531.3 Hz // 1000 * (1/20000000) * 1 = 50.0 us F = 20000.0 Hz // 800 * (1/20000000) * 1 = 40.0 us F = 25000.0 Hz // 625 * (1/20000000) * 1 = 31.3 us F = 32000.0 Hz // 512 * (1/20000000) * 1 = 25.6 us F = 39062.5 Hz // 455 * (1/20000000) * 1 = 22.75 us F = 43956.0 Hz // 454 * (1/20000000) * 1 = 22.70 us F = 44052.8 Hz // 400 * (1/20000000) * 1 = 20.00 us F = 50000.0 Hz // 256 * (1/20000000) * 1 = 12.80 us F = 78125.0 Hz // 213 * (1/20000000) * 1 = 10.65 us F = 93896.7 Hz // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #define FCY 20000000 // cycle machine frequency #include "p30f3014.h" #include "timer.h" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void timer_1_ini_i(int period) // int timer 1 initialization { T1CONbits.TON = 0; // timer on control 0=stop T1CONbits.TCKPS = 0; // input clock prescale 0=1:1 T1CONbits.TCS = 0; // timer ck src 0=internal(fosc/4) PR1 = period; // period register IPC0bits.T1IP = 7; // int. priority 7 (highest) IEC0bits.T1IE = 1; // timer 1 interrupt enable T1CONbits.TON = 1; // timer on control 1=start } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void timer_2_ini(int period) // timer 2 initialization { T2CONbits.TON = 0; // timer on control 0=stop T2CONbits.TCKPS = 0; // input clock prescale 0=1:1 T2CONbits.TCS = 0; // timer ck src 0=internal(fosc/4) PR2 = period; // period register IPC1bits.T2IP = 3; // int. priority 3 (medium) IEC0bits.T2IE = 0; // timer 2 interrupt disable T2CONbits.TON = 1; // timer on control 1=start } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void timer_2_ini_i(int period) // int timer 2 initialization { timer_2_ini(period); T2CONbits.TON = 0; // timer on control 0=stop IEC0bits.T2IE = 1; // timer 2 interrupt enable T2CONbits.TON = 1; // timer on control 1=start } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // timer.h - timers initialization functions // version 1.00 - 20070525 // version 1.07 - 20070615 - clear overrun - optimizing // T(measured) = (PRx + 1) * FCY * TMRx prescale = // 4000 * (1/20000000) * 1 = 200 us F = 5000.0 Hz // 2000 * (1/20000000) * 1 = 100 us F = 10000.0 Hz // 1024 * (1/20000000) * 1 = 51.2 us F = 19531.3 Hz // 1000 * (1/20000000) * 1 = 50.0 us F = 20000.0 Hz // 800 * (1/20000000) * 1 = 40.0 us F = 25000.0 Hz // 625 * (1/20000000) * 1 = 31.3 us F = 32000.0 Hz // 512 * (1/20000000) * 1 = 25.6 us F = 39062.5 Hz // 455 * (1/20000000) * 1 = 22.75 us F = 43956.0 Hz // 454 * (1/20000000) * 1 = 22.70 us F = 44052.8 Hz // 400 * (1/20000000) * 1 = 20.00 us F = 50000.0 Hz // 256 * (1/20000000) * 1 = 12.80 us F = 78125.0 Hz // 213 * (1/20000000) * 1 = 10.65 us F = 93896.7 Hz // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void timer_1_ini_i(int period); // int timer 1 initialization void timer_2_ini(int period); // timer 2 initialization void timer_2_ini_i(int period); // int timer 2 initialization // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // wave table generator wavgn.cpp - ver.1.05 - 20070609 // Copyright (C) 2007 miguel angel labolida // This program is under the terms of the GNU General Public License // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // output file name with extension: wave.c // resolution in bits: 14 // samples quantity: 16 // resol.max.val: 16384 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int sinewave[16] = { 0x0000, 0x0C3E, 0x16A0, 0x1D90, 0x1FFF, 0x1D90, 0x16A0, 0x0C3E, 0x0000, 0xF3C1, 0xE95F, 0xE26F, 0xE000, 0xE26F, 0xE95F, 0xF3C1, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int sawtooth[16] = { 0xE000, 0xE400, 0xE800, 0xEC00, 0xF000, 0xF400, 0xF800, 0xFC00, 0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int triangular[16] = { 0xE000, 0xE7FF, 0xEFFF, 0xF7FF, 0xFFFF, 0x07FF, 0x0FFF, 0x17FF, 0x1FFF, 0x17FF, 0x0FFF, 0x07FF, 0xFFFF, 0xF7FF, 0xEFFF, 0xE7FF, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -