Andrew Durand
/
GT_Tuner
Simple guitar tuner
Revision 0:490e67fb09c2, committed 2011-10-24
- Comitter:
- adurand
- Date:
- Mon Oct 24 23:03:27 2011 +0000
- Child:
- 1:ae7d0cf78b3e
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADC_full/adc.cpp Mon Oct 24 23:03:27 2011 +0000 @@ -0,0 +1,439 @@ +/* mbed Library - ADC + * Copyright (c) 2010, sblandford + * released under MIT license http://mbed.org/licence/mit + */ +#include "mbed.h" +#include "adc.h" + + +ADC *ADC::instance; + +ADC::ADC(int sample_rate, int cclk_div) + { + + int i, adc_clk_freq, pclk, clock_div, max_div=1; + + //Work out CCLK + adc_clk_freq=CLKS_PER_SAMPLE*sample_rate; + int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1; + int n = (LPC_SC->PLL0CFG >> 16) + 1; + int cclkdiv = LPC_SC->CCLKCFG + 1; + int Fcco = (2 * m * XTAL_FREQ) / n; + int cclk = Fcco / cclkdiv; + + //Power up the ADC + LPC_SC->PCONP |= (1 << 12); + //Set clock at cclk / 1. + LPC_SC->PCLKSEL0 &= ~(0x3 << 24); + switch (cclk_div) { + case 1: + LPC_SC->PCLKSEL0 |= 0x1 << 24; + break; + case 2: + LPC_SC->PCLKSEL0 |= 0x2 << 24; + break; + case 4: + LPC_SC->PCLKSEL0 |= 0x0 << 24; + break; + case 8: + LPC_SC->PCLKSEL0 |= 0x3 << 24; + break; + default: + fprintf(stderr, "Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n", + cclk_div); + fprintf(stderr, "Defaulting to 1.\n"); + LPC_SC->PCLKSEL0 |= 0x1 << 24; + break; + } + pclk = cclk / cclk_div; + clock_div=pclk / adc_clk_freq; + + if (clock_div > 0xFF) { + fprintf(stderr, "Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n", + clock_div); + clock_div=0xFF; + } + if (clock_div == 0) { + fprintf(stderr, "Warning: Clock division is 0. Re-Setting to 1.\n"); + clock_div=1; + } + + _adc_clk_freq=pclk / clock_div; + if (_adc_clk_freq > MAX_ADC_CLOCK) { + fprintf(stderr, "Warning: Actual ADC sample rate of %u which is above %u limit\n", + _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE); + while ((pclk / max_div) > MAX_ADC_CLOCK) max_div++; + fprintf(stderr, "Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE); + } + + LPC_ADC->ADCR = + ((clock_div - 1 ) << 8 ) | //Clkdiv + ( 1 << 21 ); //A/D operational + + //Default no channels enabled + LPC_ADC->ADCR &= ~0xFF; + //Default NULL global custom isr + _adc_g_isr = NULL; + //Initialize arrays + for (i=7; i>=0; i--) { + _adc_data[i] = 0; + _adc_isr[i] = NULL; + } + + + //* Attach IRQ + instance = this; + NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr); + + //Disable global interrupt + LPC_ADC->ADINTEN &= ~0x100; + +}; + +void ADC::_adcisr(void) +{ + instance->adcisr(); +} + + +void ADC::adcisr(void) +{ + uint32_t stat; + int chan; + + // Read status + stat = LPC_ADC->ADSTAT; + //Scan channels for over-run or done and update array + if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0; + if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1; + if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2; + if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3; + if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4; + if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5; + if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6; + if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7; + + // Channel that triggered interrupt + chan = (LPC_ADC->ADGDR >> 24) & 0x07; + //User defined interrupt handlers + if (_adc_isr[chan] != NULL) + _adc_isr[chan](_adc_data[chan]); + if (_adc_g_isr != NULL) + _adc_g_isr(chan, _adc_data[chan]); + return; +} + +int ADC::_pin_to_channel(PinName pin) { + int chan; + switch (pin) { + case p15://=p0.23 of LPC1768 + default: + chan=0; + break; + case p16://=p0.24 of LPC1768 + chan=1; + break; + case p17://=p0.25 of LPC1768 + chan=2; + break; + case p18://=p0.26 of LPC1768 + chan=3; + break; + case p19://=p1.30 of LPC1768 + chan=4; + break; + case p20://=p1.31 of LPC1768 + chan=5; + break; + } + return(chan); +} + +PinName ADC::channel_to_pin(int chan) { + const PinName pin[8]={p15, p16, p17, p18, p19, p20, p15, p15}; + + if ((chan < 0) || (chan > 5)) + fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan); + return(pin[chan & 0x07]); +} + + +int ADC::channel_to_pin_number(int chan) { + const int pin[8]={15, 16, 17, 18, 19, 20, 0, 0}; + + if ((chan < 0) || (chan > 5)) + fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan); + return(pin[chan & 0x07]); +} + + +uint32_t ADC::_data_of_pin(PinName pin) { + //If in burst mode and at least one interrupt enabled then + //take all values from _adc_data + if (burst() && (LPC_ADC->ADINTEN & 0x3F)) { + return(_adc_data[_pin_to_channel(pin)]); + } else { + //Return current register value or last value from interrupt + switch (pin) { + case p15://=p0.23 of LPC1768 + default: + return(LPC_ADC->ADINTEN & 0x01?_adc_data[0]:LPC_ADC->ADDR0); + case p16://=p0.24 of LPC1768 + return(LPC_ADC->ADINTEN & 0x02?_adc_data[1]:LPC_ADC->ADDR1); + case p17://=p0.25 of LPC1768 + return(LPC_ADC->ADINTEN & 0x04?_adc_data[2]:LPC_ADC->ADDR2); + case p18://=p0.26 of LPC1768: + return(LPC_ADC->ADINTEN & 0x08?_adc_data[3]:LPC_ADC->ADDR3); + case p19://=p1.30 of LPC1768 + return(LPC_ADC->ADINTEN & 0x10?_adc_data[4]:LPC_ADC->ADDR4); + case p20://=p1.31 of LPC1768 + return(LPC_ADC->ADINTEN & 0x20?_adc_data[5]:LPC_ADC->ADDR5); + } + } +} + +//Enable or disable an ADC pin +void ADC::setup(PinName pin, int state) { + int chan; + chan=_pin_to_channel(pin); + if ((state & 1) == 1) { + switch(pin) { + case p15://=p0.23 of LPC1768 + default: + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); + LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14; + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); + LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14; + break; + case p16://=p0.24 of LPC1768 + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); + LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16; + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); + LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16; + break; + case p17://=p0.25 of LPC1768 + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); + LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18; + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); + LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18; + break; + case p18://=p0.26 of LPC1768: + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); + LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20; + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); + LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20; + break; + case p19://=p1.30 of LPC1768 + LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); + LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28; + LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); + LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28; + break; + case p20://=p1.31 of LPC1768 + LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); + LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30; + LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); + LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30; + break; + } + //Only one channel can be selected at a time if not in burst mode + if (!burst()) LPC_ADC->ADCR &= ~0xFF; + //Select channel + LPC_ADC->ADCR |= (1 << chan); + } + else { + switch(pin) { + case p15://=p0.23 of LPC1768 + default: + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); + break; + case p16://=p0.24 of LPC1768 + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); + break; + case p17://=p0.25 of LPC1768 + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); + break; + case p18://=p0.26 of LPC1768: + LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); + LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); + break; + case p19://=p1.30 of LPC1768 + LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); + LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); + break; + case p20://=p1.31 of LPC1768 + LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); + LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); + break; + } + LPC_ADC->ADCR &= ~(1 << chan); + } +} +//Return channel enabled/disabled state +int ADC::setup(PinName pin) { + int chan; + + chan = _pin_to_channel(pin); + return((LPC_ADC->ADCR & (1 << chan)) >> chan); +} + +//Select channel already setup +void ADC::select(PinName pin) { + int chan; + + //Only one channel can be selected at a time if not in burst mode + if (!burst()) LPC_ADC->ADCR &= ~0xFF; + //Select channel + chan = _pin_to_channel(pin); + LPC_ADC->ADCR |= (1 << chan); +} + +//Enable or disable burst mode +void ADC::burst(int state) { + if ((state & 1) == 1) { + if (startmode(0) != 0) + fprintf(stderr, "Warning. startmode is %u. Must be 0 for burst mode.\n", startmode(0)); + LPC_ADC->ADCR |= (1 << 16); + } + else + LPC_ADC->ADCR &= ~(1 << 16); +} +//Return burst mode state +int ADC::burst(void) { + return((LPC_ADC->ADCR & (1 << 16)) >> 16); +} + +//Set startmode and edge +void ADC::startmode(int mode, int edge) { + int lpc_adc_temp; + + //Reset start mode and edge bit, + lpc_adc_temp = LPC_ADC->ADCR & ~(0x0F << 24); + //Write with new values + lpc_adc_temp |= ((mode & 7) << 24) | ((edge & 1) << 27); + LPC_ADC->ADCR = lpc_adc_temp; +} + +//Return startmode state according to mode_edge=0: mode and mode_edge=1: edge +int ADC::startmode(int mode_edge){ + switch (mode_edge) { + case 0: + default: + return((LPC_ADC->ADCR >> 24) & 0x07); + case 1: + return((LPC_ADC->ADCR >> 27) & 0x01); + } +} + +//Start ADC conversion +void ADC::start(void) { + startmode(1,0); +} + + +//Set interrupt enable/disable for pin to state +void ADC::interrupt_state(PinName pin, int state) { + int chan; + + chan = _pin_to_channel(pin); + if (state == 1) { + LPC_ADC->ADINTEN &= ~0x100; + LPC_ADC->ADINTEN |= 1 << chan; + /* Enable the ADC Interrupt */ + NVIC_EnableIRQ(ADC_IRQn); + } else { + LPC_ADC->ADINTEN &= ~( 1 << chan ); + //Disable interrrupt if no active pins left + if ((LPC_ADC->ADINTEN & 0xFF) == 0) + NVIC_DisableIRQ(ADC_IRQn); + } +} + +//Return enable/disable state of interrupt for pin +int ADC::interrupt_state(PinName pin) { + int chan; + + chan = _pin_to_channel(pin); + return((LPC_ADC->ADINTEN >> chan) & 0x01); +} + + +//Attach custom interrupt handler replacing default +void ADC::attach(void(*fptr)(void)) { + //* Attach IRQ + NVIC_SetVector(ADC_IRQn, (uint32_t)fptr); +} + +//Restore default interrupt handler +void ADC::detach(void) { + //* Attach IRQ + instance = this; + NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr); +} + + +//Append interrupt handler for pin to function isr +void ADC::append(PinName pin, void(*fptr)(uint32_t value)) { + int chan; + + chan = _pin_to_channel(pin); + _adc_isr[chan] = fptr; +} + +//Append interrupt handler for pin to function isr +void ADC::unappend(PinName pin) { + int chan; + + chan = _pin_to_channel(pin); + _adc_isr[chan] = NULL; +} + +//Unappend global interrupt handler to function isr +void ADC::append(void(*fptr)(int chan, uint32_t value)) { + _adc_g_isr = fptr; +} + +//Detach global interrupt handler to function isr +void ADC::unappend() { + _adc_g_isr = NULL; +} + +//Set ADC offset +void offset(int offset) { + LPC_ADC->ADTRM &= ~(0x07 << 4); + LPC_ADC->ADTRM |= (offset & 0x07) << 4; +} + +//Return current ADC offset +int offset(void) { + return((LPC_ADC->ADTRM >> 4) & 0x07); +} + +//Return value of ADC on pin +int ADC::read(PinName pin) { + //Reset DONE and OVERRUN flags of interrupt handled ADC data + _adc_data[_pin_to_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30)); + //Return value + return((_data_of_pin(pin) >> 4) & 0xFFF); +} + +//Return DONE flag of ADC on pin +int ADC::done(PinName pin) { + return((_data_of_pin(pin) >> 31) & 0x01); +} + +//Return OVERRUN flag of ADC on pin +int ADC::overrun(PinName pin) { + return((_data_of_pin(pin) >> 30) & 0x01); +} + +int ADC::actual_adc_clock(void) { + return(_adc_clk_freq); +} + +int ADC::actual_sample_rate(void) { + return(_adc_clk_freq / CLKS_PER_SAMPLE); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADC_full/adc.h Mon Oct 24 23:03:27 2011 +0000 @@ -0,0 +1,131 @@ +/* mbed Library - ADC + * Copyright (c) 2010, sblandford + * released under MIT license http://mbed.org/licence/mit + */ + +#ifndef MBED_ADC_H +#define MBED_ADC_H + +#include "mbed.h" +#define XTAL_FREQ 12000000 +#define MAX_ADC_CLOCK 13000000 +#define CLKS_PER_SAMPLE 64 + +class ADC { +public: + + //Initialize ADC with ADC maximum sample rate of + //sample_rate and system clock divider of cclk_div + //Maximum recommened sample rate is 184000 + ADC(int sample_rate, int cclk_div); + + //Enable/disable ADC on pin according to state + //and also select/de-select for next conversion + void setup(PinName pin, int state); + + //Return enabled/disabled state of ADC on pin + int setup(PinName pin); + + //Enable/disable burst mode according to state + void burst(int state); + + //Select channel already setup + void select(PinName pin); + + //Return burst mode enabled/disabled + int burst(void); + + /*Set start condition and edge according to mode: + 0 - No start (this value should be used when clearing PDN to 0). + 1 - Start conversion now. + 2 - Start conversion when the edge selected by bit 27 occurs on the P2.10 / EINT0 / NMI pin. + 3 - Start conversion when the edge selected by bit 27 occurs on the P1.27 / CLKOUT / + USB_OVRCRn / CAP0.1 pin. + 4 - Start conversion when the edge selected by bit 27 occurs on MAT0.1. Note that this does + not require that the MAT0.1 function appear on a device pin. + 5 - Start conversion when the edge selected by bit 27 occurs on MAT0.3. Note that it is not + possible to cause the MAT0.3 function to appear on a device pin. + 6 - Start conversion when the edge selected by bit 27 occurs on MAT1.0. Note that this does + not require that the MAT1.0 function appear on a device pin. + 7 - Start conversion when the edge selected by bit 27 occurs on MAT1.1. Note that this does + not require that the MAT1.1 function appear on a device pin. + When mode >= 2, conversion is triggered by edge: + 0 - Rising edge + 1 - Falling edge + */ + void startmode(int mode, int edge); + + //Return startmode state according to mode_edge=0: mode and mode_edge=1: edge + int startmode(int mode_edge); + + //Start ADC conversion + void start(void); + + //Set interrupt enable/disable for pin to state + void interrupt_state(PinName pin, int state); + + //Return enable/disable state of interrupt for pin + int interrupt_state(PinName pin); + + //Attach custom interrupt handler replacing default + void attach(void(*fptr)(void)); + + //Restore default interrupt handler + void detach(void); + + //Append custom interrupt handler for pin + void append(PinName pin, void(*fptr)(uint32_t value)); + + //Unappend custom interrupt handler for pin + void unappend(PinName pin); + + //Append custom global interrupt handler + void append(void(*fptr)(int chan, uint32_t value)); + + //Unappend custom global interrupt handler + void unappend(void); + + //Set ADC offset to a value 0-7 + void offset(int offset); + + //Return current ADC offset + int offset(void); + + //Return value of ADC on pin + int read(PinName pin); + + //Return DONE flag of ADC on pin + int done(PinName pin); + + //Return OVERRUN flag of ADC on pin + int overrun(PinName pin); + + //Return actual ADC clock + int actual_adc_clock(void); + + //Return actual maximum sample rate + int actual_sample_rate(void); + + //Return pin ID of ADC channel + PinName channel_to_pin(int chan); + + //Return pin number of ADC channel + int channel_to_pin_number(int chan); + + +private: + int _pin_to_channel(PinName pin); + uint32_t _data_of_pin(PinName pin); + + int _adc_clk_freq; + void adcisr(void); + static void _adcisr(void); + static ADC *instance; + + uint32_t _adc_data[8]; + void(*_adc_isr[8])(uint32_t value); + void(*_adc_g_isr)(int chan, uint32_t value); + void(*_adc_m_isr)(void); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NokiaLCD/NokiaLCD.cpp Mon Oct 24 23:03:27 2011 +0000 @@ -0,0 +1,458 @@ +/* mbed Nokia LCD Library + * Copyright (c) 2007-2010, sford + */ + +#include "NokiaLCD.h" + +#include "mbed.h" + +#define NOKIALCD_ROWS 16 +#define NOKIALCD_COLS 16 +#define NOKIALCD_WIDTH 130 +#define NOKIALCD_HEIGHT 132 +#define NOKIALCD_FREQUENCY 5000000 + +NokiaLCD::NokiaLCD(PinName mosi, PinName sclk, PinName cs, PinName rst, LCDType type) + : _spi(mosi, NC, sclk) + , _rst(rst) + , _cs(cs) { + + _type = type; + + _row = 0; + _column = 0; + _foreground = 0x00FFFFFF; + _background = 0x00000000; + + reset(); +} + +void NokiaLCD::reset() { + + // setup the SPI interface and bring display out of reset + _cs = 1; + _rst = 0; + _spi.format(9); + _spi.frequency(NOKIALCD_FREQUENCY); + wait_ms(1); + _rst = 1; + wait_ms(1); + + _cs = 0; + + switch (_type) { + case LCD6100: + command(0xCA); // display control + data(0); + data(32); + data(0); + command(0xBB); + data(1); + command(0xD1); // oscillator on + command(0x94); // sleep out + command(0x20); // power control + data(0x0F); + command(0xA7); // invert display + command(0x81); // Voltage control + data(39); // contrast setting: 0..63 + data(3); // resistance ratio + wait_ms(1); + command(0xBC); + data(0); + data(1); + data(4); + command(0xAF); // turn on the display + break; + + case LCD6610: + command(0xCA); // display control + data(0); + data(32); + data(0); + command(0xBB); + data(1); + command(0xD1); // oscillator on + command(0x94); // sleep out + command(0x20); // power control + data(0x0F); + command(0xA7); // invert display + command(0x81); // Voltage control + data(39); // contrast setting: 0..63 + data(3); // resistance ratio + wait_ms(1); + command(0xBC); + data(0); + data(0); + data(2); + command(0xAF); // turn on the display + break; + + case PCF8833: + command(0x11); // sleep out + command(0x3A); // column mode + data(0x05); + command(0x36); // madctl + data(0x60); // vertical RAM, flip x + command(0x25); // setcon + data(0x30);// contrast 0x30 + wait_ms(2); + command(0x29);//DISPON + command(0x03);//BSTRON + break; + } + + _cs = 1; + + cls(); +} + +void NokiaLCD::command(int value) { + _spi.write(value & 0xFF); +} + +void NokiaLCD::data(int value) { + _spi.write(value | 0x100); +} + +void NokiaLCD::_window(int x, int y, int width, int height) { + int x1 = x + 0; + int y1 = y + 0; + int x2 = x1 + width - 1; + int y2 = y1 + height - 1; + + switch (_type) { + case LCD6100: + case LCD6610: + command(0x15); // column + data(x1); + data(x2); + command(0x75); // row + data(y1); + data(y2); + command(0x5C); // start write to ram + break; + case PCF8833: + command(0x2A); // column + data(x1); + data(x2); + command(0x2B); // row + data(y1); + data(y2); + command(0x2C); // start write to ram + break; + } +} + +void NokiaLCD::_putp(int colour) { + int gr = ((colour >> 20) & 0x0F) + | ((colour >> 8 ) & 0xF0); + int nb = ((colour >> 4 ) & 0x0F); + data(nb); + data(gr); +} + +const unsigned char FONT8x8[97][8] = { + 0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, // columns, rows, num_bytes_per_char + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // space 0x20 + 0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // ! + 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // " + 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // # + 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $ + 0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00, // % + 0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00, // & + 0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00, // ' + 0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // ( + 0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // ) + 0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // * + 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // + + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // , + 0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // - + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // . + 0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00, // / (forward slash) + 0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00, // 0 0x30 + 0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00, // 1 + 0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00, // 2 + 0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00, // 3 + 0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00, // 4 + 0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00, // 5 + 0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00, // 6 + 0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00, // 7 + 0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00, // 8 + 0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00, // 9 + 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // : + 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ; + 0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, // < + 0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // = + 0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00, // > + 0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00, // ? + 0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00, // @ 0x40 + 0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00, // A + 0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00, // B + 0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00, // C + 0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00, // D + 0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00, // E + 0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00, // F + 0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00, // G + 0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00, // H + 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I + 0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // J + 0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00, // K + 0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00, // L + 0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00, // M + 0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00, // N + 0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00, // O + 0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00, // P 0x50 + 0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00, // Q + 0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00, // R + 0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00, // S + 0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00, // T + 0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00, // U + 0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00, // V + 0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00, // W + 0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00, // X + 0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y + 0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00, // Z + 0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [ + 0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00, // \ (back slash) + 0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ] + 0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00, // ^ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _ + 0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // ` 0x60 + 0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00, // a + 0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00, // b + 0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00, // c + 0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00, // d + 0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00, // e + 0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00, // f + 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C, // g + 0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00, // h + 0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i + 0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j + 0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00, // k + 0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l + 0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00, // m + 0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00, // n + 0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00, // o + 0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78, // p + 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F, // q + 0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00, // r + 0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00, // s + 0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00, // t + 0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00, // u + 0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00, // v + 0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00, // w + 0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00, // x + 0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C, // y + 0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z + 0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // { + 0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00, // | + 0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // } + 0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00, // ~ + 0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00 +}; // DEL + +void NokiaLCD::locate(int column, int row) { + _column = column; + _row = row; +} + +void NokiaLCD::newline() { + _column = 0; + _row++; + if (_row >= _rows) { + _row = 0; + } +} + +int NokiaLCD::_putc(int value) { + int x = _column * 8; // FIXME: Char sizes + int y = _row * 8; + bitblit(x + 1, y + 1, 8, 8, (char*)&(FONT8x8[value - 0x1F][0])); + + _column++; + + if (_column >= NOKIALCD_COLS) { + _row++; + _column = 0; + } + + if (_row >= NOKIALCD_ROWS) { + _row = 0; + } + + return value; +} + +void NokiaLCD::cls() { + fill(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT, _background); + _row = 0; + _column = 0; +} + + +void NokiaLCD::window(int x, int y, int width, int height) { + _cs = 0; + _window(x, y, width, height); + _cs = 1; +} + +void NokiaLCD::putp(int colour) { + _cs = 0; + _putp(colour); + _cs = 1; +} + +void NokiaLCD::pixel(int x, int y, int colour) { + _cs = 0; + _window(x, y, 1, 1); + switch (_type) { + case LCD6100: + case PCF8833: + + _putp(colour); + + break; + case LCD6610: + + int r4 = (colour >> (16 + 4)) & 0xF; + int g4 = (colour >> (8 + 4)) & 0xF; + int b4 = (colour >> (0 + 4)) & 0xF; + int d1 = (r4 << 4) | g4; + int d2 = (b4 << 4) | r4; + int d3 = (g4 << 4) | b4; + data(d1); + data(d2); + data(d3); + + break; + } + _cs = 1; +} + +void NokiaLCD::fill(int x, int y, int width, int height, int colour) { + _cs = 0; + _window(x, y, width, height); + switch (_type) { + case LCD6100: + case PCF8833: + for (int i=0; i<width*height; i++) { + _putp(colour); + } + break; + case LCD6610: + for (int i=0; i<width*height/2; i++) { + int r4 = (colour >> (16 + 4)) & 0xF; + int g4 = (colour >> (8 + 4)) & 0xF; + int b4 = (colour >> (0 + 4)) & 0xF; + int d1 = (r4 << 4) | g4; + int d2 = (b4 << 4) | r4; + int d3 = (g4 << 4) | b4; + data(d1); + data(d2); + data(d3); + } + break; + } + _window(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT); + _cs = 1; +} + +void NokiaLCD::blit(int x, int y, int width, int height, const int* colour) { + _cs = 0; + _window(x, y, width, height); + + switch (_type) { + case LCD6100: + case PCF8833: + for (int i=0; i<width*height; i++) { + _putp(colour[i]); + } + break; + case LCD6610: + for (int i=0; i<width*height/2; i++) { + int r41 = (colour[i*2] >> (16 + 4)) & 0xF; + int g41 = (colour[i*2] >> (8 + 4)) & 0xF; + int b41 = (colour[i*2] >> (0 + 4)) & 0xF; + + int r42 = (colour[i*2+1] >> (16 + 4)) & 0xF; + int g42 = (colour[i*2+1] >> (8 + 4)) & 0xF; + int b42 = (colour[i*2+1] >> (0 + 4)) & 0xF; + int d1 = (r41 << 4) | g41; + int d2 = (b41 << 4) | r42; + int d3 = (g42 << 4) | b42; + data(d1); + data(d2); + data(d3); + } + break; + } + _window(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT); + _cs = 1; +} + +void NokiaLCD::bitblit(int x, int y, int width, int height, const char* bitstream) { + _cs = 0; + _window(x, y, width, height); + + switch (_type) { + case LCD6100: + case PCF8833: + for (int i=0; i<height*width; i++) { + int byte = i / 8; + int bit = i % 8; + int colour = ((bitstream[byte] << bit) & 0x80) ? _foreground : _background; + _putp(colour); + } + break; + case LCD6610: + for(int i=0; i<height*width/2; i++) { + int byte1 = (i*2) / 8; + int bit1 = (i*2) % 8; + int colour1 = ((bitstream[byte1] << bit1) & 0x80) ? _foreground : _background; + int byte2 = (i*2+1) / 8; + int bit2 = (i*2+1) % 8; + int colour2 = ((bitstream[byte2] << bit2) & 0x80) ? _foreground : _background; + + int r41 = (colour1 >> (16 + 4)) & 0xF; + int g41 = (colour1 >> (8 + 4)) & 0xF; + int b41 = (colour1 >> (0 + 4)) & 0xF; + + int r42 = (colour2 >> (16 + 4)) & 0xF; + int g42 = (colour2 >> (8 + 4)) & 0xF; + int b42 = (colour2 >> (0 + 4)) & 0xF; + int d1 = (r41 << 4) | g41; + int d2 = (b41 << 4) | r42; + int d3 = (g42 << 4) | b42; + data(d1); + data(d2); + data(d3); + } + break; + } + _window(0, 0, _width, _height); + _cs = 1; +} + +void NokiaLCD::foreground(int c) { + _foreground = c; +} + +void NokiaLCD::background(int c) { + _background = c; +} + +int NokiaLCD::width() { + return NOKIALCD_WIDTH; +} + +int NokiaLCD::height() { + return NOKIALCD_HEIGHT; +} + +int NokiaLCD::columns() { + return NOKIALCD_COLS; +} + +int NokiaLCD::rows() { + return NOKIALCD_ROWS; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NokiaLCD/NokiaLCD.h Mon Oct 24 23:03:27 2011 +0000 @@ -0,0 +1,151 @@ +/* mbed NokiaLCD Library, for a 130x130 Nokia colour LCD + * Copyright (c) 2007-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MBED_NOKIALCD_H +#define MBED_NOKIALCD_H + +#include "mbed.h" + +/** An interface for the 130x130 Nokia Mobile phone screens + * + * @code + * #include "mbed.h" + * #include "NokiaLCD.h" + * + * NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::6610); // mosi, sclk, cs, rst, type + * + * int main() { + * lcd.printf("Hello World!"); + * } + * @endcode + */ +class NokiaLCD : public Stream { + +public: + /** LCD panel format */ + enum LCDType { + LCD6100 /**< Nokia 6100, as found on sparkfun board (default) */ + , LCD6610 /**< Nokia 6610, as found on olimex board */ + , PCF8833 + }; + + /** Create and Nokia LCD interface, using a SPI and two DigitalOut interfaces + * + * @param mosi SPI data out + * @param sclk SPI clock + * @param cs Chip Select (DigitalOut) + * @param rst Reset (DigitalOut) + * @param type The LCDType to select driver chip variants + */ + NokiaLCD(PinName mosi, PinName sclk, PinName cs, PinName rst, LCDType type = LCD6100); + +#if DOXYGEN_ONLY + /** Write a character to the LCD + * + * @param c The character to write to the display + */ + int putc(int c); + + /** Write a formated string to the LCD + * + * @param format A printf-style format string, followed by the + * variables to use in formating the string. + */ + int printf(const char* format, ...); +#endif + + /** Locate to a screen column and row + * + * @param column The horizontal position from the left, indexed from 0 + * @param row The vertical position from the top, indexed from 0 + */ + void locate(int column, int row); + + /** Clear the screen and locate to 0,0 */ + void cls(); + + /** Set a pixel on te screen + * + * @param x horizontal position from left + * @param y vertical position from top + * @param colour 24-bit colour in format 0x00RRGGBB + */ + void pixel(int x, int y, int colour); + + /** Fill an area of the screen + * + * @param x horizontal position from left + * @param y vertical position from top + * @param width width in pixels + * @param height height in pixels + * @param colour 24-bit colour in format 0x00RRGGBB + */ + void fill(int x, int y, int width, int height, int colour); + + void blit(int x, int y, int width, int height, const int* colour); + void bitblit(int x, int y, int width, int height, const char* bitstream); + + int width(); + int height(); + int columns(); + int rows(); + + void reset(); + + /** Set the foreground colour + * + * @param c 24-bit colour + */ + void foreground(int c); + + /** Set the background colour + * + * @param c 24-bit colour + */ + void background(int c); + +protected: + virtual void _window(int x, int y, int width, int height); + virtual void _putp(int colour); + + void command(int value); + void data(int value); + + void newline(); + virtual int _putc(int c); + virtual int _getc() { + return 0; + } + void putp(int v); + void window(int x, int y, int width, int height); + + SPI _spi; + DigitalOut _rst; + DigitalOut _cs; + + LCDType _type; + int _row, _column, _rows, _columns, _foreground, _background, _width, _height; +}; + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Oct 24 23:03:27 2011 +0000 @@ -0,0 +1,177 @@ + ////////////////////////////////////////// + // // +// Guitar Tuner via Goertzel's Algorithm // +// Created by: Andrew Durand // + // // + ////////////////////////////////////////// + +#include "mbed.h" +#include "adc.h" +#include "NokiaLCD.h" + +#define PI 3.1415 +#define SAMPLE_RATE 24000 + +DigitalOut led_low(LED1); +DigitalOut led_ok(LED2); +DigitalOut led_high(LED4); +InterruptIn button1(p12); + +//LCD and Other Random Variables +NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type +int string_select = 0; +float high, high1, high2, high3, high4, high5, high6, high7, high8, in_tune, in_tune1, in_tune2, in_tune3, +low, low1, low2, low3, low4, low5, low6, low7, low8, note; +char* key; +int Counter = 0; +int Buffer[6000]; + +float goertzelFilter(int samples[], float freq, int N) { + float s_prev = 0.0; + float s_prev2 = 0.0; + float coeff,normalizedfreq,power,s,k; + int i; + normalizedfreq = freq / SAMPLE_RATE; + coeff = 2*cos(2*PI*normalizedfreq); + for (i=0; i<N; i++) { + s = samples[i] + coeff * s_prev - s_prev2; + s_prev2 = s_prev; + s_prev = s; + } + power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2; + return power; +} + +ADC adc(SAMPLE_RATE, 1); + +void sample_audio(int chan, uint32_t value) { + Buffer[Counter] = adc.read(p20); + Counter += 1; +} + +void button1_pressed() { + string_select++; + if (string_select > 5) string_select = 0; +} + +int main() { + //Interupt for Switching Strings + button1.mode(PullDown); + button1.rise(&button1_pressed); + + //Setup LCD + lcd.background(0xF0000F); + lcd.cls(); + + while (1) { + + switch (string_select) { + case 0: + note = 82; + key= "E2"; + break; + case 1: + note = 110; + key= "A2"; + break; + case 2: + note = 147; + key= "D3"; + break; + case 3: + note = 196; + key= "G3"; + break; + case 4: + note = 247; + key= "B3"; + break; + case 5: + note = 330; + key= "E4"; + break; + } + + //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford + adc.append(sample_audio); + adc.startmode(0,0); + adc.burst(1); + adc.setup(p20,1); + + //start the interrupt and wait for about 4096 samples + adc.interrupt_state(p20,1); + wait(.2); + + //Finsh up - Unset pin 20 + adc.interrupt_state(p20,0); + adc.setup(p20,0); + int actual_rate = adc.actual_sample_rate(); + + //for debugging tell the terminal sample rate and how many samples we took + printf("Requested max sample rate is %u, actual max sample rate is %u.\n", + SAMPLE_RATE, actual_rate); + printf("We did %i samples\n",Counter); + + high1 = goertzelFilter(Buffer, (note+18), Counter); + high2 = goertzelFilter(Buffer, (note+16), Counter); + high3 = goertzelFilter(Buffer, (note+14), Counter); + high4 = goertzelFilter(Buffer, (note+12), Counter); + high5 = goertzelFilter(Buffer, (note+10), Counter); + high6 = goertzelFilter(Buffer, (note+8), Counter); + high7 = goertzelFilter(Buffer, (note+6), Counter); + high8 = goertzelFilter(Buffer, (note+4), Counter); + in_tune1 = goertzelFilter(Buffer, (note+0.5), Counter); + in_tune2 = goertzelFilter(Buffer, note, Counter); + in_tune3 = goertzelFilter(Buffer, (note-0.5), Counter); + low1 = goertzelFilter(Buffer, (note-4), Counter); + low2 = goertzelFilter(Buffer, (note-6), Counter); + low3 = goertzelFilter(Buffer, (note-8), Counter); + low4 = goertzelFilter(Buffer, (note-10), Counter); + low5 = goertzelFilter(Buffer, (note-12), Counter); + low6 = goertzelFilter(Buffer, (note-14), Counter); + low7 = goertzelFilter(Buffer, (note-16), Counter); + low8 = goertzelFilter(Buffer, (note-18), Counter); + + in_tune = (in_tune1 + in_tune2 + in_tune3)/3; + high = (high1 + high2 + high3 + high4 + high5 + high6 + high7 + high8)/8; + low = (low1 + low2 + low3 + low4 + low5 + low6 + low7 + low8)/8; + + if ((in_tune > high) && (in_tune > low)) { + led_high = 0; + led_ok = 1; + led_low = 0; + } else if (high > in_tune) { + led_high = 1; + led_ok = 0; + led_low = 0; + } else if (low > in_tune) { + led_high = 0; + led_ok = 0; + led_low = 1; + } else { + led_high = 0; + led_ok = 0; + led_low = 0; + + } + + // Display on the LCD + lcd.locate(0,1); + lcd.printf("::Guitar Tuner::"); + lcd.locate(0,3); + lcd.printf("Tuning String: %i", (6-string_select)); + lcd.locate(0,5); + lcd.printf("%s at %i Hz",key, (int) note); + lcd.locate(5,7); + if (led_ok) lcd.printf("In Tune!"); + else if (led_low) lcd.printf("Too Low "); + else if (led_high) lcd.printf("Too High"); + else lcd.printf("~~~~~"); + + Counter = 0; + + } + + + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Oct 24 23:03:27 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0