Wave-Player with TLV320
Dependencies: FatFileSystemCpp I2SSlave TLV320 mbed
Revision 0:3087f1924901, committed 2015-12-09
- Comitter:
- HB9GAA
- Date:
- Wed Dec 09 20:58:55 2015 +0000
- Commit message:
- Wave-Player with TLV320
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystemCpp.lib Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/igorsk/code/FatFileSystemCpp/#88f22c32a456
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/I2SSlave.lib Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/d_worrall/code/I2SSlave/#aa3e863920d2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD/LCD.cpp Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,186 @@ +/* mbed LCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2012, hb9gaa + */ + +#include "LCD.h" +#include "mbed.h" + +TextLCD::TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, PinName d2, PinName d3, LCDType type) : _rs(rs), _rw(rw), _e(e), _d(d0, d1, d2, d3), _type(type) + { + _e = 1; + _rw = 0; + _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_ms(1.64); // this command takes 1.64ms, so wait for it + } + writeByte(0x2); // 4-bit mode + wait_ms(0.1); // most instructions take 100us + + 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_ms(4.1); // This command takes 4.1 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.0001); // most instructions take 100us + _e = 0; + wait(0.0001); + _e = 1; + _d = value >> 0; + wait(0.0001); + _e = 0; + wait(0.0001); + _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; + } + } + + +void TextLCD::buildChar(unsigned char *p) + { + unsigned char i, j; + + for(j=0;j<8;j++) //CGRAM Adresse + { + writeCommand(0x40+(j*8)); //Write to CGRAM + for(i=0;i<8;i++) + writeData(p[i+(j*8)]); //Write the character pattern to CGRAM + } + writeCommand(0x80); //shift back to DDRAM location 0 + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD/LCD.h Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,67 @@ +/* mbed LCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2012, hb9gaa + */ + +#ifndef MBED_LCD_H +#define MBED_LCD_H + +#include "mbed.h" + +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 d0-d3 Data lines + * @param type Sets the panel size/addressing mode (default = LCD16x2) + */ + TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, PinName d2, PinName d3, LCDType type = LCD16x2); + + /** Write a character to the LCD + * @param c The character to write to the display + */ + int putc(int c); + + /** 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); + void buildChar(unsigned char *p); + + /** 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, _rw, _e; + BusOut _d; + LCDType _type; + + int _column; + int _row; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDHC_FileSystem/SDHCFileSystem.cpp Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,495 @@ +/* mbed SDFileSystem Library, for providing file access to SD cards + * Copyright (c) 2008-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. + */ + +/* Introduction + * ------------ + * SD and MMC cards support a number of interfaces, but common to them all + * is one based on SPI. This is the one I'm implmenting because it means + * it is much more portable even though not so performant, and we already + * have the mbed SPI Interface! + * + * The main reference I'm using is Chapter 7, "SPI Mode" of: + * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf + * + * SPI Startup + * ----------- + * The SD card powers up in SD mode. The SPI interface mode is selected by + * asserting CS low and sending the reset command (CMD0). The card will + * respond with a (R1) response. + * + * CMD8 is optionally sent to determine the voltage range supported, and + * indirectly determine whether it is a version 1.x SD/non-SD card or + * version 2.x. I'll just ignore this for now. + * + * ACMD41 is repeatedly issued to initialise the card, until "in idle" + * (bit 0) of the R1 response goes to '0', indicating it is initialised. + * + * You should also indicate whether the host supports High Capicity cards, + * and check whether the card is high capacity - i'll also ignore this + * + * SPI Protocol + * ------------ + * The SD SPI protocol is based on transactions made up of 8-bit words, with + * the host starting every bus transaction by asserting the CS signal low. The + * card always responds to commands, data blocks and errors. + * + * The protocol supports a CRC, but by default it is off (except for the + * first reset CMD0, where the CRC can just be pre-calculated, and CMD8) + * I'll leave the CRC off I think! + * + * Standard capacity cards have variable data block sizes, whereas High + * Capacity cards fix the size of data block to 512 bytes. I'll therefore + * just always use the Standard Capacity cards with a block size of 512 bytes. + * This is set with CMD16. + * + * You can read and write single blocks (CMD17, CMD25) or multiple blocks + * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When + * the card gets a read command, it responds with a response token, and then + * a data token or an error. + * + * SPI Command Format + * ------------------ + * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC. + * + * +---------------+------------+------------+-----------+----------+--------------+ + * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 | + * +---------------+------------+------------+-----------+----------+--------------+ + * + * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95) + * + * All Application Specific commands shall be preceded with APP_CMD (CMD55). + * + * SPI Response Format + * ------------------- + * The main response format (R1) is a status byte (normally zero). Key flags: + * idle - 1 if the card is in an idle state/initialising + * cmd - 1 if an illegal command code was detected + * + * +-------------------------------------------------+ + * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle | + * +-------------------------------------------------+ + * + * R1b is the same, except it is followed by a busy signal (zeros) until + * the first non-zero byte when it is ready again. + * + * Data Response Token + * ------------------- + * Every data block written to the card is acknowledged by a byte + * response token + * + * +----------------------+ + * | xxx | 0 | status | 1 | + * +----------------------+ + * 010 - OK! + * 101 - CRC Error + * 110 - Write Error + * + * Single Block Read and Write + * --------------------------- + * + * Block transfers have a byte header, followed by the data, followed + * by a 16-bit CRC. In our case, the data will always be 512 bytes. + * + * +------+---------+---------+- - - -+---------+-----------+----------+ + * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] | + * +------+---------+---------+- - - -+---------+-----------+----------+ + */ + + /* + * Comment: Changes for SDHC support till 32GB + * Name: KB + * Date: 07/24/2010 + * Release: 0.1 + */ + +#include "SDHCFileSystem.h" + +#define DEBUG +#define SD_COMMAND_TIMEOUT 5000 + + +SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) : + FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) { + _cs = 1; +} + +#define R1_IDLE_STATE (1 << 0) +#define R1_ERASE_RESET (1 << 1) +#define R1_ILLEGAL_COMMAND (1 << 2) +#define R1_COM_CRC_ERROR (1 << 3) +#define R1_ERASE_SEQUENCE_ERROR (1 << 4) +#define R1_ADDRESS_ERROR (1 << 5) +#define R1_PARAMETER_ERROR (1 << 6) + +// Types +// - v1.x Standard Capacity +// - v2.x Standard Capacity +// - v2.x High Capacity +// - Not recognised as an SD Card + +#define SDCARD_FAIL 0 +#define SDCARD_V1 1 +#define SDCARD_V2 2 +#define SDCARD_V2HC 3 + +int SDFileSystem::initialise_card() { + // Set to 100kHz for initialisation, and clock card with cs = 1 + _spi.frequency(100000); + _cs = 1; + for(int i=0; i<16; i++) { + _spi.write(0xFF); + } + + // send CMD0, should return with all zeros except IDLE STATE set (bit 0) + if(_cmd(0, 0) != R1_IDLE_STATE) { + fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n"); + return SDCARD_FAIL; + } + + // send CMD8 to determine whther it is ver 2.x + int r = _cmd8(); + if(r == R1_IDLE_STATE) { + return initialise_card_v2(); + } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { + return initialise_card_v1(); + } else { + fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n"); + return SDCARD_FAIL; + } +} + +int SDFileSystem::initialise_card_v1() { + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + _cmd(55, 0); + if(_cmd(41, 0) == 0) { + cdv = 512; + #ifdef DEBUG + printf("\n\rInit: SEDCARD_V1\n\r"); + #endif + return SDCARD_V1; + } + } + + fprintf(stderr, "Timeout waiting for v1.x card\n"); + return SDCARD_FAIL; +} + +int SDFileSystem::initialise_card_v2() { + + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + wait_ms(50); + _cmd58(); + _cmd(55, 0); + if(_cmd(41, 0x40000000) == 0) { + _cmd58(); + #ifdef DEBUG + printf("\n\rInit: SDCARD_V2\n\r"); + #endif + cdv = 1; + return SDCARD_V2; + } + } + + fprintf(stderr, "Timeout waiting for v2.x card\n"); + return SDCARD_FAIL; +} + +int SDFileSystem::disk_initialize() { + + int i = initialise_card(); + #ifdef DEBUG + printf("init card = %d\n", i); + #endif + _sectors = _sd_sectors(); + + // Set block length to 512 (CMD16) + if(_cmd(16, 512) != 0) { + fprintf(stderr, "Set 512-byte block timed out\n"); + return 1; + } + + _spi.frequency(16000000); // Set to 1MHz for data transfer + return 0; +} + +int SDFileSystem::disk_write(const char *buffer, int block_number) { + // set write address for single block (CMD24) + if(_cmd(24, block_number * cdv) != 0) { + return 1; + } + + // send the data block + _write(buffer, 512); + return 0; +} + +int SDFileSystem::disk_read(char *buffer, int block_number) { + // set read address for single block (CMD17) + if(_cmd(17, block_number * cdv) != 0) { + return 1; + } + + // receive the data + _read(buffer, 512); + return 0; +} + +int SDFileSystem::disk_status() { return 0; } +int SDFileSystem::disk_sync() { return 0; } +int SDFileSystem::disk_sectors() { return _sectors; } + +// PRIVATE FUNCTIONS + +int SDFileSystem::_cmd(int cmd, int arg) { + _cs = 0; + + // send a command + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} +int SDFileSystem::_cmdx(int cmd, int arg) { + _cs = 0; + + // send a command + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + + +int SDFileSystem::_cmd58() { + _cs = 0; + int arg = 0; + + // send a command + _spi.write(0x40 | 58); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + int ocr = _spi.write(0xFF) << 24; + ocr |= _spi.write(0xFF) << 16; + ocr |= _spi.write(0xFF) << 8; + ocr |= _spi.write(0xFF) << 0; +// printf("OCR = 0x%08X\n", ocr); + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + +int SDFileSystem::_cmd8() { + _cs = 0; + + // send a command + _spi.write(0x40 | 8); // CMD8 + _spi.write(0x00); // reserved + _spi.write(0x00); // reserved + _spi.write(0x01); // 3.3v + _spi.write(0xAA); // check pattern + _spi.write(0x87); // crc + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) { + char response[5]; + response[0] = _spi.write(0xFF); + if(!(response[0] & 0x80)) { + for(int j=1; j<5; j++) { + response[i] = _spi.write(0xFF); + } + _cs = 1; + _spi.write(0xFF); + return response[0]; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + +int SDFileSystem::_read(char *buffer, int length) { + _cs = 0; + + // read until start byte (0xFF) + while(_spi.write(0xFF) != 0xFE); + + // read data + for(int i=0; i<length; i++) { + buffer[i] = _spi.write(0xFF); + } + _spi.write(0xFF); // checksum + _spi.write(0xFF); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +int SDFileSystem::_write(const char *buffer, int length) { + _cs = 0; + + // indicate start of block + _spi.write(0xFE); + + // write the data + for(int i=0; i<length; i++) { + _spi.write(buffer[i]); + } + + // write the checksum + _spi.write(0xFF); + _spi.write(0xFF); + + // check the repsonse token + if((_spi.write(0xFF) & 0x1F) != 0x05) { + _cs = 1; + _spi.write(0xFF); + return 1; + } + + // wait for write to finish + while(_spi.write(0xFF) == 0); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +static int ext_bits(char *data, int msb, int lsb) { + int bits = 0; + int size = 1 + msb - lsb; + for(int i=0; i<size; i++) { + int position = lsb + i; + int byte = 15 - (position >> 3); + int bit = position & 0x7; + int value = (data[byte] >> bit) & 1; + bits |= value << i; + } + return bits; +} + +int SDFileSystem::_sd_sectors() { + + int c_size, c_size_mult, read_bl_len; + int block_len, mult, blocknr, capacity; + int blocks, hc_c_size; + uint64_t hc_capacity; + + // CMD9, Response R2 (R1 byte + 16-byte block read) + if(_cmdx(9, 0) != 0) { + fprintf(stderr, "Didn't get a response from the disk\n"); + return 0; + } + + char csd[16]; + if(_read(csd, 16) != 0) { + fprintf(stderr, "Couldn't read csd response from disk\n"); + return 0; + } + + // csd_structure : csd[127:126] + // c_size : csd[73:62] + // c_size_mult : csd[49:47] + // read_bl_len : csd[83:80] - the *maximum* read block length + + int csd_structure = ext_bits(csd, 127, 126); + + #ifdef DEBUG + printf("\n\rCSD_STRUCT = %d\n", csd_structure); + #endif + + switch (csd_structure){ + case 0: + cdv = 512; + c_size = ext_bits(csd, 73, 62); + c_size_mult = ext_bits(csd, 49, 47); + read_bl_len = ext_bits(csd, 83, 80); + + block_len = 1 << read_bl_len; + mult = 1 << (c_size_mult + 2); + blocknr = (c_size + 1) * mult; + capacity = blocknr * block_len; + blocks = capacity / 512; + #ifdef DEBUG + printf("\n\rSDCard\n\rc_size: %.4X \n\rcapacity: %.ld \n\rsectors: %d\n\r", c_size, capacity, blocks); + #endif + break; + + case 1: + cdv = 1; + hc_c_size = ext_bits(csd, 63, 48); + int hc_read_bl_len = ext_bits(csd, 83, 80); + hc_capacity = hc_c_size+1; + blocks = (hc_c_size+1)*1024; + #ifdef DEBUG + printf("\n\rSDHC Card \n\rhc_c_size: %.4X \n\rcapacity: %.lld \n\rsectors: %d\n\r", hc_c_size, hc_capacity*512*1024, blocks); + #endif + break; + + default: + fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n"); + return 0; + break; + }; + return blocks; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDHC_FileSystem/SDHCFileSystem.h Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,86 @@ +/* mbed SDFileSystem Library, for providing file access to SD cards + * Copyright (c) 2008-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_SDHCFILESYSTEM_H +#define MBED_SDHCFILESYSTEM_H + +#include "mbed.h" +#include "FATFileSystem.h" + +/* Double Words */ +typedef unsigned long long uint64_t; +typedef long long sint64_t; + +/** Access the filesystem on an SD Card using SPI + * + * @code + * #include "mbed.h" + * #include "SDFileSystem.h" + * + * SDFileSystem sd(p5, p6, p7, p12, "sd"); // mosi, miso, sclk, cs + * + * int main() { + * FILE *fp = fopen("/sd/myfile.txt", "w"); + * fprintf(fp, "Hello World!\n"); + * fclose(fp); + * } + */ +class SDFileSystem : public FATFileSystem { +public: + + /** Create the File System for accessing an SD Card using SPI + * + * @param mosi SPI mosi pin connected to SD Card + * @param miso SPI miso pin conencted to SD Card + * @param sclk SPI sclk pin connected to SD Card + * @param cs DigitalOut pin used as SD Card chip select + * @param name The name used to access the virtual filesystem + */ + SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name); + virtual int disk_initialize(); + virtual int disk_write(const char *buffer, int block_number); + virtual int disk_read(char *buffer, int block_number); + virtual int disk_status(); + virtual int disk_sync(); + virtual int disk_sectors(); + +protected: + + int _cmd(int cmd, int arg); + int _cmdx(int cmd, int arg); + int _cmd8(); + int _cmd58(); + int initialise_card(); + int initialise_card_v1(); + int initialise_card_v2(); + + int _read(char *buffer, int length); + int _write(const char *buffer, int length); + int _sd_sectors(); + int _sectors; + + SPI _spi; + DigitalOut _cs; + int cdv; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TLV320.lib Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/d_worrall/code/TLV320/#7e76c6f56169
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,204 @@ +//------------------------------------------------------------------------------------------------------------ +// Demoprogramm 6 für die Audio-Ausgabe über das AudioCODEC Board (RS Product Code 754-1965) +//------------------------------------------------------------------------------------------------------------ +//(c) Roland Elmiger, ELcon Consulting & Engineering, Switzerland +// +// Version 1.0A +// +// Enwickelt am : 22.11.2015 +// Letzter Update : 06.12.2015 +//------------------------------------------------------------------------------------------------------------ +// Jedes WAV-Files mit den Bedingungen 44100Hz, 16-bit, Stereo sollte funktionieren. +// +// Beschaltung: +// +// AudioCODEC Board mbed NXP LPC1768 +// --------------------- --------------------- +// GND | 1 <-------> 1 | GND (0V) +// LRCOUT | 2 | +// DOUT | 3 | +// BCLK | 4 <-------- 7 | P7 (SCLK) +// DIN | 5 <-------- 5 | P5 (MOSI) +// LCRIN | 6 <-------- 6 | P6 (MISO) +// /CS | 7 <-------> 1 | GND (0V) +// MODE | 8 <-------> 1 | GND (0V) +// SDIN | 9 <-------- 9 | P9 (SDA) +// SCLK |10 <--------10 | P10 (SCL) +// +3.3V |11 <------->40 | Vout (3.3V) +// --------------------- --------------------- + + +//------------------------------------------------------------------------------------------------------------ + +#include "mbed.h" +#include "TLV320.h" +#include "SDHCFileSystem.h" +#include "LCD.h" + + +DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); +Serial pc(USBTX, USBRX); + +TextLCD lcd(p26, p25, p24, p23, p22, p20, p19, TextLCD::LCD20x4); // RS, RW, E, D0, D1, D2, D3, Typ +TLV320 audio(p9, p10, 0x34, p5, p6, p7, p8, p29); //Objekt I2S Codec + +SDFileSystem sd(p11, p12, p13, p14, "sd"); //Objekt SD-Karte (MOSI, MISO, SCLK, CS, "SD-Kartenname") + +FILE *fp; //Zeiger auf die Audiodatei + +AnalogIn aIn(p15); //Lautstärke + +#define DEBOUNCING_INTERVAL 20 //Debouncing Interval (in Millisekunden) + +// Variablen +//--------------------------------------------------------------------------------------------------------------------------------------- +int RingBuffer[4096]; //Ringspeicher +volatile int ReadPointer = 0; +volatile int Theta = 0; + +/* Wav file header data, for setting up the transfer protocol */ +short Channels; //Kanalzahl (2 = Stereo, 1 = Mono) +long SampleRate; //Abtastrate +short WordWidth; //Bit-Anzahl der Daten (z.B. 16 Bit) + +bool AnsagePlay = false; // +char AnsageNr = 0; //Nr. der Ansage + +// Texte für die Anzeigen und die Audio-Dateiauswahl +//--------------------------------------------------------------------------------------------------------------------------------------- +const char AnsageAudio[5][40] = { + {"/sd/Bahnhof1.wav"}, + {"/sd/Bahnhof2.wav"}, + {"/sd/Bahnhof3.wav"}, + {"/sd/Bahnhof4.wav"}, + {"/sd/Bahnhof5.wav"} }; + +const char AnzeigeText[5][40] = { + {"Bahnhof 1\n\nEndstation\nRestaurant"}, + {"Bahnhof 2\n\nLoewengehege"}, + {"Bahnhof 3\n\nRegenwald"}, + {"Bahnhof 4\n\nSchweizer-Tiere"}, + {"Bahnhof 5\n\nEndstation\nStreichel-Zoo"} }; + +InterruptIn Reed1(p16); //Eingänge der Reed-Kontakte (LOW aktiv) +InterruptIn Reed2(p17); +InterruptIn Reed3(p18); +InterruptIn Reed4(p28); +InterruptIn Reed5(p30); + + +// Funktion zum lesen des Potentiometerwerts und setzten der Ausgangslautstärke +//------------------------------------------------------------------------------------------------------------ +void SetVolume(void) + { + audio.outputVolume(1-aIn, 1-aIn); + } + + +// Funktion zum lesen des Zirkular-Speichers und zum senden der Daten zum TLV320 +//------------------------------------------------------------------------------------------------------------ +void isr_audio(void) + { + audio.write(RingBuffer, ReadPointer, 8); + ReadPointer += 8; + ReadPointer &= 0xfff; + Theta -= 8; + } + + +// Funktion um den Zirkular-Speicher von der SD Karte zu laden +//------------------------------------------------------------------------------------------------------------ +void FillBuffer(void) + { + while(!feof(fp)) + { //füllt den Zirkularspeicher bis zum Ende des Files + static volatile int WritePointer = 0; + if(Theta < 4096) + { + fread(&RingBuffer[WritePointer], 4, 4, fp); //liest 4 integer Werte auf einmal in den Zirzularspeicher + Theta += 4; + WritePointer += 4; + WritePointer &= 0xfff; + } + } + } + + +// Interruptroutine für die Abfrage der Reed Kontakte (LOW aktiv) +//------------------------------------------------------------------------------------------------------------ +void ReedClosed() + { + wait_ms(DEBOUNCING_INTERVAL); + { + if((Reed1 == 0 || Reed2 == 0 || Reed3 == 0 || Reed4 == 0 || Reed5 == 0) && (AnsagePlay == false)) + { + AnsagePlay = true; //eine Ansage ist zum abspielen bereit + + if(Reed1 == 0) AnsageNr = 0; //Ansage Nr 1 Endstation Restaurant + else if(Reed2 == 0) AnsageNr = 1; //Ansage Nr 2 Löwengehege + else if(Reed3 == 0) AnsageNr = 2; //Ansage Nr 3 Regenwald + else if(Reed4 == 0) AnsageNr = 3; //Ansage Nr 4 Schweizer Tiere + else if(Reed5 == 0) AnsageNr = 4; //Ansage Nr 5 Endstation Streichelzoo + + pc.printf("%s\n",AnzeigeText[AnsageNr]);//zur Kontrolle den Text auch auf der serielle Schnittstelle ausgeben + lcd.cls(); //LC-Display löschen + lcd.printf("%s",AnzeigeText[AnsageNr]); //Bahnhoftext auf LCD ausgeben + } + } + } + + +// Hauptprogramm (hier beginnt der Programmablauf, "main" muss immer existieren) +//--------------------------------------------------------------------------------------------------------------------------------------- +int main(int argc, char *argv[]) + { + pc.baud(115200); + + audio.power(0x02); //Mikrofon aus + audio.inputVolume(0.2, 0.2); //Eingangspegel 0.0 bis 1.0 (leftVolumeIn, rightVolumeIn) + audio.outputVolume(0.5, 0.5); //Ausgangspegel 0.0 bis 1.0 (leftVolumeOut, rightVolumeOut) + audio.frequency(44100); //8kHz, 8.021kHz, 32kHz, 44.1kHz, 48kHz, 88.2kHz, 96kHz -> Default ist 44.1kHz + audio.attach(&isr_audio); //Interrupt für die I2SxxFIFOs + + Reed1.mode(PullUp); Reed1.fall(ReedClosed); + Reed2.mode(PullUp); Reed2.fall(ReedClosed); + Reed3.mode(PullUp); Reed3.fall(ReedClosed); + Reed4.mode(PullUp); Reed4.fall(ReedClosed); + Reed5.mode(PullUp); Reed5.fall(ReedClosed); + + pc.printf("--------------------\nSTART\n--------------------\n\n"); // "START" auf erste Zeile schreiben + wait(2); // 2s warten + +// t.start(); //Timer start + + while(1) + { + if (AnsagePlay == true) + { +// audio.start(TRANSMIT); //Interrupt starten (NONE, nur TRANSMIT, nur RECEIVE, BOTH) + pc.printf("%s\n\n",AnsageAudio[AnsageNr]); + + fp = fopen(AnsageAudio[AnsageNr],"rb"); + + if(!fp) return(printf("File Error\n")); + + fseek(fp, 22, SEEK_SET); fread(&Channels, 2, 1, fp); //Parse WAV File Header + fseek(fp, 24, SEEK_SET); fread(&SampleRate, 4, 1, fp); + fseek(fp, 34, SEEK_SET); fread(&WordWidth, 2, 1, fp); + audio.format(WordWidth, (2-Channels)); //setzen des Transferprotokoll + + for(int j = 0; j < 4096; ++j) //RingSpeicher löschen + { + RingBuffer[j] = 0; //Zirkularspeicher löschen + } + + SetVolume(); //Ausgangspegel vom Potentiometer lesen (leftVolumeOut, rightVolumeOut) + audio.start(TRANSMIT); //Interrupt kommt nur vom I2STXFIFO + FillBuffer(); //kontinuierlich den Zirkularspeicher füllen + audio.stop(); + fclose(fp); + AnsagePlay = false; + } + } + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Dec 09 20:58:55 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e