wefwe
Dependencies: mbed C12832 DogM163 FatFileSystem
Revision 28:19aac2daf669, committed 2019-05-08
- Comitter:
- JostBaus
- Date:
- Wed May 08 13:48:54 2019 +0000
- Parent:
- 27:6e5cc34fb952
- Commit message:
- Wavspiller using RiceGulumb
Changed in this revision
diff -r 6e5cc34fb952 -r 19aac2daf669 DogM163.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DogM163.lib Wed May 08 13:48:54 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/FrankWeissenborn/code/DogM163/#1e693c7d1389
diff -r 6e5cc34fb952 -r 19aac2daf669 FatFileSystem.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem.lib Wed May 08 13:48:54 2019 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/p07gbar/code/FatFileSystem/#e869ee8f3c3d
diff -r 6e5cc34fb952 -r 19aac2daf669 SDFileSystem.lib --- a/SDFileSystem.lib Sat Apr 20 17:12:05 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/neilt6/code/SDFileSystem/#e4d2567200db
diff -r 6e5cc34fb952 -r 19aac2daf669 SDHCFileSystem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDHCFileSystem.cpp Wed May 08 13:48:54 2019 +0000 @@ -0,0 +1,494 @@ +/* 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(25000000/*1000000*/); // 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; +}
diff -r 6e5cc34fb952 -r 19aac2daf669 SDHCFileSystem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDHCFileSystem.h Wed May 08 13:48:54 2019 +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
diff -r 6e5cc34fb952 -r 19aac2daf669 WavPlayer.lib --- a/WavPlayer.lib Sat Apr 20 17:12:05 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://os.mbed.com/users/JostBaus/code/WavPlayer/#b0186c8dca92
diff -r 6e5cc34fb952 -r 19aac2daf669 _bitio.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/_bitio.cpp Wed May 08 13:48:54 2019 +0000 @@ -0,0 +1,67 @@ +#include "mbed.h" +#include "string" +#include "_bitio.h" + + +FILE *infp, *outfp; +int getcount, putcount; +Uint bitbuf; + +void init_bit_o(void) +{ + putcount = 8; bitbuf = 0; +} + +void init_bit_i(void) +{ + getcount = 0; bitbuf = 0; +} + + +Uint getbit(void) +{ + int flag; + if (--getcount >= 0) return (bitbuf >> getcount) & 1U; + getcount = 7; + if((flag = fgetc(infp))==EOF)return OVERRUN; + else bitbuf = flag; + return (bitbuf >> 7) & 1U; +} + +Uint getbits(int n) +{ + Uint x = 0; + if (n < 1 || 25 < n) return 0; + while (n > getcount) { + n -= getcount; + x |= rightbits(getcount, bitbuf) << n; + bitbuf = fgetc(infp); getcount = 8; + } + getcount -= n; + return x | rightbits(n, bitbuf >> getcount); +} + + +void putbit(Uint bit) +{ + putcount--; + if (bit != 0) bitbuf |= (1 << putcount); + if (putcount == 0) { + if (fputc(bitbuf, outfp) == EOF) error("can't write\r\n"); + bitbuf = 0; putcount = 8; + } +} + + +void putbits(int n, Uint x) +{ + if (n < 1 || 25 < n) return; + while (n >= putcount) { + n -= putcount; + bitbuf |= rightbits(putcount, x >> n); + if (fputc(bitbuf, outfp) == EOF) error("cant write\r\n"); + bitbuf = 0U; putcount = 8; + } + putcount -= n; + bitbuf |= rightbits(n, x) << putcount; +}
diff -r 6e5cc34fb952 -r 19aac2daf669 _bitio.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/_bitio.h Wed May 08 13:48:54 2019 +0000 @@ -0,0 +1,33 @@ +#ifndef ___BITIO_H__ +#define ___BITIO_H__ +/* +#define TRUE 1 +#define FALSE 0 +*/ +#define rightbits(n, x) ((x) & ((1U << (n)) - 1U)) + +#define OVERRUN 0xffff +#define k 0x0b // k:0x09 to 0x0b? + +typedef unsigned int Uint; +typedef unsigned char Uchar; + +extern FILE *infp, *outfp; +extern int getcount, putcount; +extern Uint bitbuf; + +/* Rice Golomb en-decoding */ +extern void decode(void); +extern void encode(long int n); + + +void init_bit_o(void); +void init_bit_i(void); +Uint getbit(void); +Uint getbits(int n); +void putbit(Uint bit); +void putbits(int n, Uint x); + + + +#endif \ No newline at end of file
diff -r 6e5cc34fb952 -r 19aac2daf669 main.cpp --- a/main.cpp Sat Apr 20 17:12:05 2019 +0000 +++ b/main.cpp Wed May 08 13:48:54 2019 +0000 @@ -3,28 +3,36 @@ #include "stdio.h" #include "math.h" #include "C12832.h" -#include "WavPlayer.h" -#include "SDFileSystem.h" +#include "SDHCFileSystem.h" +#include "_bitio.h" #include <string> using namespace std; //Communication\interfaces Serial pc(USBTX,USBRX); //USB serial -C12832 lcd(p5, p7, p6, p8, p11); //LCD +C12832 lcd(p5, p7, p6, p8, p9); //LCD +DigitalIn RW(p10); SDFileSystem sd(p11, p12, p13, p15, "sd"); //SDCard DigitalIn sdDetect(p14); //CardDetect //in- and outputs -DigitalIn PauseBtn(p21); -DigitalIn StopBtn(p22); +DigitalIn PauseBtn(p19); +DigitalIn StopBtn(p20); +DigitalIn UpBtn(p18); +DigitalIn DownBtn(p17); -//joystick -BusIn joy(p19,p17,p18,p20); -DigitalIn joyBtn(p14); +DigitalOut led1(LED1); +DigitalOut led2(LED2); + //DAC output -WavPlayer waver; //set up DAC to use wave player library +// BU9480F define +//SPI bu9480f(p23,p24,p21); +//DigitalOut LRCLK(p22); +// BU9480F define.end +//ticker- sampling +Ticker tick; //timer Timer dur; @@ -33,23 +41,35 @@ void read_file_names(char *dir); //SDCard read file names void menu(); void PlaySong(int m); -void PauseSong(); void StopSong(); +void dac_out(); +void encode(long int n); +void decode(void); //variables int m = 1; //index of choosen songs int i = 0; //index of files from folder -int Paused = 0; //Is the song paused? +int Paused = 0;//Is the song paused? int Stopped = 0; //Is the song stopped? char* songs[5]; +// a FIFO for the DAC +#define TXFIFO_FULL 1 +#define RAM_LENGTH 8192//8192 +#define RAM_LIMIT (RAM_LENGTH - 1) +volatile short DAC_fifo[RAM_LENGTH]; +volatile short DAC_wptr=0; +volatile short DAC_rptr=0; +volatile short DAC_on; +volatile short DAC_diff=0; + int main() { while(sdDetect == 0) { - lcd.locate(0,0); lcd.printf("Insert SD Card!"); wait(0.5); } + pc.printf("going out of main"); menu(); } @@ -59,14 +79,14 @@ sd.disk_initialize(); read_file_names("/sd/Music"); while(1) { - lcd.locate(0,0); + lcd.cls(); lcd.printf("Please select a song"); - if(joy == 1) { + if(UpBtn == 1) { m++; if(m == 5) { m = 0; } - } else if(joy == 2) { + } else if(DownBtn == 1) { m--; if(m == -1) { m = 4; @@ -74,7 +94,8 @@ } lcd.locate(0,15); lcd.printf("%s", (songs[m])); - if(joyBtn == 1) { + if(PauseBtn == 1) { + pc.printf("going to play song"); PlaySong(m); } wait(0.1); @@ -83,6 +104,7 @@ void read_file_names(char *dir) // function that reads in file names from sd cards { + pc.printf("found files"); DIR *dp; struct dirent *dirp; dp = opendir(dir); @@ -98,53 +120,155 @@ string songname = songs[m]; string a = "/sd/Music/"; string fname = a + songname; //retrieves the file name - FILE *wave_file; + FILE *infp; dur.start(); lcd.cls(); lcd.locate(0,0); lcd.printf("Now playing"); - wave_file = fopen(fname.c_str(),"r"); //opens the music file - waver.open(&wave_file); - waver.play(); //plays the music file - lcd.locate(0,10); - lcd.printf("%s", (songs[m])); - while(Stopped == 0) { - if(StopBtn == 1) { - StopSong(); - } - if(PauseBtn == 1) { - PauseSong(); - } - lcd.locate(0,20); - lcd.printf("%2.f s", dur.read()); - } - fclose(wave_file); - Stopped = 0; + infp = fopen(fname.c_str(),"rb"); //opens the music file + // bu9480f init + //bu9480f.format(16,0); + //bu9480f.frequency(16000000); //16MHz + // bu9480f init.end + tick.attach_us(&dac_out, 41); //set 24.4kHz sampling data + decode(); + //plays the music file + + tick.detach(); + fclose( infp ); menu(); } -void PauseSong() -{ - while(1) { - if(Paused == 0) { - string songname = songs[m]; - unsigned index = songname.find(".wav"); - songname = songname.substr(0,index); - lcd.printf(songname.c_str()); - dur.stop(); - Paused = 1; - } else if(StopBtn == 1) { - StopSong(); - } else { - Paused = 0; - dur.start(); - } - } -} - void StopSong() { + pc.printf("stopped"); lcd.cls(); dur.reset(); - Stopped = 1; + tick.detach(); + menu(); +} + +void dac_out() +{ + pc.printf("playing"); + if(StopBtn == 1) { + StopSong(); + } + if(PauseBtn == 1) { + dur.stop(); + if(Paused == 1) { + Paused = 0; + dur.start(); + } else { + Paused = 1; + } + } + if(Paused == 0) { + lcd.locate(0,10); + lcd.printf("%s", (songs[m])); + // printf("\t%d\r\n",DAC_diff); + if (DAC_diff > 1) { + led2 = 0; + + //LRCLK = 0; + //bu9480f.write(DAC_fifo[DAC_rptr++]); + DAC_rptr &= RAM_LIMIT; + + //LRCLK = 1; + //bu9480f.write(DAC_fifo[DAC_rptr++]); + DAC_rptr &= RAM_LIMIT; + + DAC_diff-=2; + + } else led2 = 1; + lcd.locate(0,20); + lcd.printf("%2.f s", dur.read()); + } else { + lcd.printf("PAUSED"); + } } + +void encode(long int n) +{ + pc.printf("encoding"); + int zero_shift = 0; + + if(n < 0) { + putbit(0); // sign (put 0:if n as negative) + n = -n; // n = abs(n) + //printf("\t 0"); + } else { + putbit(1); // sign (put 1:if n as positive) + //printf("\t 1"); + } + zero_shift = (n >> (k)); + //printf("\t shift= %d",zero_shift); + while(zero_shift > 0) { + + zero_shift--; + putbit(0); + } // put n/(2^k) 0's + + putbit(1); // terminating "1" + putbits(k,rightbits(k,n)); + //printf("\t finish= %d \r\n",(n & ((1U<<k)-1))); +} + + + +void decode(void) +{ + pc.printf("decoding"); + //short dac_data; + long int decode_buff; + short diff,diff2; + unsigned int buff_sign,zero_shift; + //char flag; + + diff = 0; + diff2 = 0; + // get sign(1 for positive, 0 for negative) + while(1) { + + if((buff_sign = getbit())==OVERRUN)break; + zero_shift = 0; + while(getbit()==0)zero_shift++; + + decode_buff = (signed int)((1U << k)*zero_shift); + decode_buff += (getbits(k)); + + if(!buff_sign)decode_buff =- decode_buff; + /* return decode_buff; */ + diff =(diff + decode_buff); + DAC_fifo[DAC_wptr++]=(short)diff; + DAC_wptr &= RAM_LIMIT; + //DAC_diff++; + while (DAC_diff > RAM_LIMIT) { + led1 = 1; + } //wait + led1=0; + + if((buff_sign = getbit())==OVERRUN)break; + zero_shift = 0; + while(getbit()==0)zero_shift++; + + decode_buff = (signed int)((1U << k)*zero_shift); + decode_buff += (getbits(k)); + + if(!buff_sign)decode_buff =- decode_buff; + /* return decode_buff; */ + diff2 =(diff2 + decode_buff); + + DAC_fifo[DAC_wptr++]=(short)diff2; + DAC_wptr &= RAM_LIMIT; + DAC_diff+=2; + + while (DAC_diff > RAM_LIMIT) { + led1 = 1; + } //wait + led1=0; + + + + } +}