school project
Dependencies: PololuLedStrip mbed
Revision 0:5ddd4b0f64f8, committed 2017-01-26
- Comitter:
- taptoneesarm
- Date:
- Thu Jan 26 11:00:15 2017 +0000
- Commit message:
- schooll led proiject
Changed in this revision
diff -r 000000000000 -r 5ddd4b0f64f8 ADC_full/adc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADC_full/adc.cpp Thu Jan 26 11:00:15 2017 +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); +}
diff -r 000000000000 -r 5ddd4b0f64f8 ADC_full/adc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADC_full/adc.h Thu Jan 26 11:00:15 2017 +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
diff -r 000000000000 -r 5ddd4b0f64f8 PololuLedStrip.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PololuLedStrip.lib Thu Jan 26 11:00:15 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/taptoneesarm/code/PololuLedStrip/#8dc878594d24
diff -r 000000000000 -r 5ddd4b0f64f8 TextLCD.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.cpp Thu Jan 26 11:00:15 2017 +0000 @@ -0,0 +1,159 @@ +/* mbed TextLCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2010, sford, http://mbed.org + * + * 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. + */ + +#include "TextLCD.h" +#include "mbed.h" + +TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5, + PinName d6, PinName d7, LCDType type) : _rs(rs), + _e(e), _d(d4, d5, d6, d7), + _type(type) { + + _e = 1; + _rs = 0; // command mode + + wait(0.015); // Wait 15ms to ensure powered up + + // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) + for (int i=0; i<3; i++) { + writeByte(0x3); + wait(0.00164); // this command takes 1.64ms, so wait for it + } + writeByte(0x2); // 4-bit mode + wait(0.000040f); // most instructions take 40us + + writeCommand(0x28); // Function set 001 BW N F - - + writeCommand(0x0C); + writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes + cls(); +} + +void TextLCD::character(int column, int row, int c) { + int a = address(column, row); + writeCommand(a); + writeData(c); +} + +void TextLCD::cls() { + writeCommand(0x01); // cls, and set cursor to 0 + wait(0.00164f); // This command takes 1.64 ms + locate(0, 0); +} + +void TextLCD::locate(int column, int row) { + _column = column; + _row = row; +} + +int TextLCD::_putc(int value) { + if (value == '\n') { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } else { + character(_column, _row, value); + _column++; + if (_column >= columns()) { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } + } + return value; +} + +int TextLCD::_getc() { + return -1; +} + +void TextLCD::writeByte(int value) { + _d = value >> 4; + wait(0.000040f); // most instructions take 40us + _e = 0; + wait(0.000040f); + _e = 1; + _d = value >> 0; + wait(0.000040f); + _e = 0; + wait(0.000040f); // most instructions take 40us + _e = 1; +} + +void TextLCD::writeCommand(int command) { + _rs = 0; + writeByte(command); +} + +void TextLCD::writeData(int data) { + _rs = 1; + writeByte(data); +} + +int TextLCD::address(int column, int row) { + switch (_type) { + case LCD20x4: + switch (row) { + case 0: + return 0x80 + column; + case 1: + return 0xc0 + column; + case 2: + return 0x94 + column; + case 3: + return 0xd4 + column; + } + case LCD16x2B: + return 0x80 + (row * 40) + column; + case LCD16x2: + case LCD20x2: + default: + return 0x80 + (row * 0x40) + column; + } +} + +int TextLCD::columns() { + switch (_type) { + case LCD20x4: + case LCD20x2: + return 20; + case LCD16x2: + case LCD16x2B: + default: + return 16; + } +} + +int TextLCD::rows() { + switch (_type) { + case LCD20x4: + return 4; + case LCD16x2: + case LCD16x2B: + case LCD20x2: + default: + return 2; + } +}
diff -r 000000000000 -r 5ddd4b0f64f8 TextLCD.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.h Thu Jan 26 11:00:15 2017 +0000 @@ -0,0 +1,111 @@ +/* mbed TextLCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2010, sford, http://mbed.org + * + * 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_TEXTLCD_H +#define MBED_TEXTLCD_H + +#include "mbed.h" + +/** A TextLCD interface for driving 4-bit HD44780-based LCDs + * + * Currently supports 16x2, 20x2 and 20x4 panels + * + * @code + * #include "mbed.h" + * #include "TextLCD.h" + * + * TextLCD lcd(p10, p12, p15, p16, p29, p30); // rs, e, d4-d7 + * + * int main() { + * lcd.printf("Hello World!\n"); + * } + * @endcode + */ +class TextLCD : public Stream { +public: + + /** LCD panel format */ + enum LCDType { + LCD16x2 /**< 16x2 LCD panel (default) */ + , LCD16x2B /**< 16x2 LCD panel alternate addressing */ + , LCD20x2 /**< 20x2 LCD panel */ + , LCD20x4 /**< 20x4 LCD panel */ + }; + + /** Create a TextLCD interface + * + * @param rs Instruction/data control line + * @param e Enable line (clock) + * @param d4-d7 Data lines for using as a 4-bit interface + * @param type Sets the panel size/addressing mode (default = LCD16x2) + */ + TextLCD(PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7, LCDType type = LCD16x2); + +#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(); + + int rows(); + int columns(); + +protected: + + // Stream implementation functions + virtual int _putc(int value); + virtual int _getc(); + + int address(int column, int row); + void character(int column, int row, int c); + void writeByte(int value); + void writeCommand(int command); + void writeData(int data); + + DigitalOut _rs, _e; + BusOut _d; + LCDType _type; + + int _column; + int _row; +}; + +#endif
diff -r 000000000000 -r 5ddd4b0f64f8 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Jan 26 11:00:15 2017 +0000 @@ -0,0 +1,570 @@ +#include "mbed.h" +#include "PololuLedStrip.h" +#include <iostream> + +#define LED_COUNT 60 + +Serial pc(USBTX, USBRX); // tx, rx + +PololuLedStrip ledStrip(p11); + +rgb_color colors[LED_COUNT]; + +Timer timer; + +int aMajor[6] = {0,2,2,2,0,-1}; +int bMajor[6] = {2,4,4,4,2,-1}; +int cMajor[6] = {0,1,0,2,3,-1}; +int dMajor[6] = {2,3,2,0,-1,-1}; +int eMajor[6] = {0,0,1,2,2,0}; +int fMajor[6] = {1,-1,2,3,3,1}; +int gMajor[6] = {3,0,0,0,2,3}; + +int aMinor[6] = {0,1,2,2,0,-1}; +int bMinor[6] = {2,3,4,4,2,-1}; +int cMinor[6] = {3,4,5,5,3,-1}; +int dMinor[6] = {1,3,2,0,-1,-1}; +int eMinor[6] = {0,0,0,2,2,0}; +int fMinor[6] = {1,1,1,3,3,1}; +int gMinor[6] = {-1,-1,-1,-1,0,0}; +int gMinorActual[6] = {3,3,3,5,5,3}; + +int aSharpMajor[6] = {1,3,3,3,1,-1}; +int cSharpMajor[6] = {1,2,1,3,4,-1}; +int fSharpMajor[6] = {2,-1,3,4,4,2}; +int gSharpMajor[6] = {4,1,1,1,3,4}; + +int aSharpMinor[6] = {1,2,3,3,1,-1}; +int fSharpMinor[6] = {2,2,2,4,4,2}; + +/* + Above are the various arrays which represent the location of the string + played in a given fret to achieve a certain chord. The layout + of this arrangement helps the mBed light up the correct pattern + of LEDs on the LED strip. Not all of the chords can be played as the + Solo only includes the first six frets. +*/ + +int chordCode = 0; +int testResult = 0; +int interpretedChordCode = 0; + +using namespace std; + +int ledMapping(int fret, int str) +{ + int result; + // Initialise a variable that represents the specific number of the LED + // that is to be lit up + if(fret != -1) + { + if(fret%2 != 0) + // If the fret number is odd... + { + result = 6*fret + str - 1; + // ...then the LED number for that fret corresponds to the above formula + } else + // Otherwise if the fret number is even... + { + result = 6*(fret + 1) - str; + // ...then the LED number for that fret corresponds to the above formula + } + return result; + } + return -1; + // Output the LED number as a return value so that other parts of the code can + // use it when this function is called for a specific chord. +} + +/* + * The decoder takes a char value that represents a chord, whether it is sharp or natural and whether + * it is major or minor. The inputted value for chord is either a capital (major) or lowercase letter (minor). + * Also assigned is a sharp value (either 0 or 1, where 0 is a natural note and 1 is a sharp) + */ + +int decoder(string typed) +{ + int ascii = int(typed[0]); + // Convert the first character in the array 's' and find its + // hexadecimal code as a reference + int chordValue; + // Initialise a variable associated with the result so we can + // assess it later + if (65 <= ascii && ascii <= 71) + // If its hexadecimal number corresponds to a uppercase letter + // such that it is a major chord and... + { + if (typed.size() == 1) + // ...if the input is only one letter/symbol... + { + chordValue = ascii - 65; + // ...then offset the hexadecimal code of that letter by 65 + // to map it back to the original list of non-sharp major chords and + // store that value. + } + else + // ...if the input is more than one letter/symbol then assume + // a hash (#) was entered to indicate a sharp value so... + { + chordValue = ascii - 51; + // ...offset the hexadecimal code by 51 to map it back to + // the original list of sharp major chords and store that value. + } + } + else if (97 <= ascii && ascii <= 103) + // If its hexadecimal number corresponds to a lowercase letter + // such that it is a minor chord and... + { + if (typed.size() == 1) + // ...if the input is only one letter/symbol... + { + chordValue = ascii - 90; + // ...then offset the hexadecimal code by 90 to map it back to + // the original list of non-sharp minor chords and store that value. + } + else + // ...if the input is more than one letter/symbol then assume + // a hash (#) was entered to indicate a sharp value so... + { + chordValue = ascii - 76; + // ...offset the hexadecimal code by 51 to map it back to + // the original list of sharp minor chords and store that value. + } + } + else + // If the typed character does not correspond to an existing chord then... + { + pc.printf("Incorrect input\n"); + // Output an error message that indicates an incorrect input by the + // user and... + return(-99); + // ...output -99 to indicate an error has occured to other parts of + // the code. + } + + if (typed.size() > 2) + // If the user input is greater than two characters then... + { + pc.printf("Incorrect input\n"); + // Output an error message that indicates an incorrect input by the + // user and... + return(-99); + // ...output -99 to indicate an error has occured to other parts of + // the code. + } + + if (chordValue != 15 && chordValue != 17 && chordValue != 18 && chordValue != 22 && chordValue != 23 && chordValue != 24 && chordValue != 25 && chordValue != 27) + // If the obtained chord value corresponds to a chord that can actually be + // played by Solo then... + { + return chordValue; + // ...output that chord value + } + else + // If the chord value corresponds to a chord that cannot be played by Solo or + // is not even in the original table of chords then... + { + pc.printf("This chord will not be played by the Solo\n"); + // Output an error message that indicates a chord that cannot be played by the + // Solo and... + return -1; + // ...output -1 to indicate an error with the input + } +} + +void illuminator (int position, int colour) +{ + //pc.printf ("Position: %d Colour: %d\n",position,colour); + if (position != -1) + { + if (colour == -1) + { + colors[position] = (rgb_color){40,0,0}; + } + else if (colour == 0) + { + colors[position] = (rgb_color){40,40,40}; + } + else if (colour == 1) + { + colors[position] = (rgb_color){0,40,0}; + } + else + { + pc.printf ("Error: invalid colour number in illuminator\n"); + } + } +} + +void feedback(int colour) +{ + if (colour == 1) + { + pc.printf("Great Job!\n"); + } + else if (colour == 0) + { + pc.printf("Processing...\n"); + } + else if (colour == -1) + { + pc.printf("You suck!\n"); + } + else + { + pc.printf("Error: Colour input incorrect"); + } +} + +void identifier(int shape) +{ + int list; + // Initialise an integer variable 'result' that represents the list a chord belongs to. + int position; + // Initialise an integer variable 'position' that represents the chord's relative position + // in its allocated list. + const char* letter; + // Intialise a character variable 'letter' that will store the letter of the chord (A to G) + string type; + // Initialise a string (sentence) variable 'type' that will store the type of the chord + // e.g. "Sharp Minor" or "Major" etc. + + list = int(shape/7); + // Set the value of the 'list' variable to correspond to the list to which + // the chord (represented by 'shape') belongs to. Each list holds 7 chords + // relating to the first 7 letters of the alphabet (A to G). Therefore the list + // a chord originates from can be determined by interpreting the integer value + // the chord rounds down to, when its value is divided by seven. For example... + + if (list == 0) + // ...if the chord comes from list '0', then it must be... + { + type = "Major"; + // ... a Major chord. + } else if (list == 1) + // ...if the chord comes from list '1', then it must be... + { + type = "Minor"; + // ... a Minor chord. + } else if (list == 2) + // ...if the chord comes from list '2', then it must be... + { + type = "Sharp Major"; + // ... a Sharp Major chord. + } else if (list == 3) + // ...if the chord comes from list '3', then it must be... + { + type = "Sharp Minor"; + // ... a Sharp Minor chord. + } + + position = 7*(list + 1) - shape; + // Set the value of the 'position' as an indication of the position in the given list, + // that is to say that higher chord values in the same list will have a lower + // 'letter' due to the layout of the equation above. Irrespective of the list in + // which it occurs... + + if (position == 1) + // ...if the position value is 1, then it must be... + { + letter = "G"; + // ... a G chord. + } else if (position == 2) + // ...if the position value is 2, then it must be... + { + letter = "F"; + // ... an F chord. + } else if (position == 3) + // ...if the position value is 2, then it must be... + { + letter = "E"; + // ... an E chord. + } else if (position == 4) + // ...if the position value is 4, then it must be... + { + letter = "D"; + // ... a D chord. + } else if (position == 5) + // ...if the position value is 5, then it must be... + { + letter = "C"; + // ... a C chord. + } else if (position == 6) + // ...if the position value is 6, then it must be... + { + letter = "B"; + // ... a B chord. + } else if (position == 7) + // ...if the position value is 7, then it must be... + { + letter = "A"; + // ... an A chord. + } + pc.printf("%s %s\n",letter,type.c_str()); + // Output the letter of the chord, followed by its type separated by a + // space such that the full name of the chord is displayed. +} + +//TODO fix return values +//Change to a case/switch structure +int shaper (int shape, int colour) +{ + if (shape == 0) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(aMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 1) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(bMajor[i],i+1), colour); + } + feedback(colour); + + } + else if (shape == 2) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(cMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 3) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(dMajor[i],i+1), colour); + } + feedback(colour); + } + + else if (shape == 4) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(eMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 5) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(fMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 6) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(gMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 7) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(aMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 8) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(bMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 9) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(cMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 10) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(dMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 11) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(eMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 12) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(fMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 13) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(gMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 14) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(aSharpMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 16) + { + for(int i = 0; i<6; i++) + { + illuminator (ledMapping(cSharpMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 19) + { + for(int i = 0; i<6; i++) + { + illuminator(ledMapping(fSharpMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 20) + { + for(int i = 0; i<6; i++) + { + illuminator(ledMapping(gSharpMajor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 21) + { + for(int i = 0; i<6; i++) + { + illuminator(ledMapping(aSharpMinor[i],i+1), colour); + } + feedback(colour); + } + else if (shape == 26) + { + for(int i = 0; i<6; i++) + { + illuminator(ledMapping(fSharpMinor[i],i+1), colour); + } + feedback(colour); + } + else + { + //this point should never be reached; there are no other chords + pc.printf ("Error: shaper failed\n"); + } + // Send the colors to the LED strip. + ledStrip.write(colors, LED_COUNT); + if(colour == 1) + { + wait(0.5); + for(int i=0; i < LED_COUNT ; i++) + { + colors[i] = (rgb_color){ 0, 0, 0 }; + } + ledStrip.write(colors, LED_COUNT); + } + + return (0); +} + +int tester (int testChord, int requestChord) +{ + /* if (testChord == 0 || requestChord == 0) + { + return (99); + } + */ + if (testChord == requestChord) + { + return (1); + } + else + { + return (-1); + } +} + +int interpreter(int requestedCode) +{ +/* int r = 0; + int chord = 0; + + r = rand() % 10; + chord = rand() % 24; + if(chord == 0) chord=1; + + if(r>1) return(requestedCode); + else return(chord); */ +} + + +int main() +{ + pc.baud (921600); + string chord; + char typed[20]; + while(1) + { + pc.printf("Type in the chord you would like to use \n"); + pc.scanf("%s",typed); + chordCode = decoder(typed); + if (chordCode != -99 && chordCode != -1) + { + identifier(chordCode); + shaper(chordCode, 0); + interpretedChordCode = interpreter(chordCode); + testResult = tester(interpretedChordCode, chordCode); + + while(1) + { + if(testResult == -1) + { + wait(2); + shaper(chordCode, testResult); + wait(0.5); + shaper(chordCode, 0); + wait(1); + interpretedChordCode = interpreter(chordCode); + testResult = tester(interpretedChordCode, chordCode); + } + else if(testResult == 1) + { + wait(2); + shaper(chordCode, testResult); + wait(0.5); + break; + } + else if(testResult == 99) + { + pc.printf("Error"); + break; + } + } + wait_ms(10); + } + } +} \ No newline at end of file
diff -r 000000000000 -r 5ddd4b0f64f8 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Jan 26 11:00:15 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/6c34061e7c34 \ No newline at end of file