├── VS1053 ├── rtmidistart_plg.h ├── rtmidistart_plg.c ├── VS1053.h ├── VS1053.cpp └── examples │ └── hello.ino ├── README.md ├── PCD8544_mod ├── PCD8544_mod.h ├── PCD8544_mod.cpp └── charset.cpp └── Arduino_WebRadio_player.ino /VS1053/rtmidistart_plg.h: -------------------------------------------------------------------------------- 1 | #define RTMIDI_PLUGIN_SIZE 28 2 | extern const uint16_t rtmidi_plugin[28]; 3 | -------------------------------------------------------------------------------- /VS1053/rtmidistart_plg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "rtmidistart_plg.h" 3 | const uint16_t rtmidi_plugin[RTMIDI_PLUGIN_SIZE] PROGMEM = { /* Compressed plugin */ 4 | 0x0007, 0x0001, 0x8050, 0x0006, 0x0014, 0x0030, 0x0715, 0xb080, /* 0 */ 5 | 0x3400, 0x0007, 0x9255, 0x3d00, 0x0024, 0x0030, 0x0295, 0x6890, /* 8 */ 6 | 0x3400, 0x0030, 0x0495, 0x3d00, 0x0024, 0x2908, 0x4d40, 0x0030, /* 10 */ 7 | 0x0200, 0x000a, 0x0001, 0x0050, 8 | }; 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino WebRadio player 2 | ======================= 3 | 4 | Arduino webradio player that can plays WebRadio stations up to 64-kbps. 5 | 6 | The hardware 7 | ======================= 8 | - ENC28J60 ethernet module 9 | - VS1053B mp3, aac, wma decoder 10 | - Nokia LCD 5110 module 11 | - and an Arduino Pro mini compatible board 12 | 13 | Additional libraries 14 | ======================= 15 | - The ENC28J60 uses the [EtherCard][F] library that is extremely fast! 16 | - [TimerOne][A] Interrupt utility 17 | 18 | 19 | More information on my web site [www.serasidis.gr][B] 20 | 21 | 22 | [A]:https://github.com/devalfrz/TimerOne 23 | [B]:http://www.serasidis.gr/circuits/Arduino_WebRadio_player/Arduino_WebRadio_player.htm 24 | [F]:https://github.com/jcw/ethercard 25 | 26 | 27 | -------------------------------------------------------------------------------- /PCD8544_mod/PCD8544_mod.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PCD8544 - Interface with Philips PCD8544 (or compatible) LCDs. 3 | * 4 | * Copyright (c) 2010 Carlos Rodrigues 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | 24 | Modified by Vassilis Serasidis for working with 3X6 pixels font 25 | Now the LCD can display up to 21 characters per line (total 6 lines). 26 | 27 | */ 28 | 29 | 30 | #ifndef PCD8544_mod_H 31 | #define PCD8544_mod_H 32 | 33 | 34 | #if ARDUINO < 100 35 | #include 36 | #else 37 | #include 38 | #endif 39 | 40 | 41 | // Chip variants supported... 42 | #define CHIP_PCD8544 0 43 | #define CHIP_ST7576 1 44 | 45 | 46 | class PCD8544: public Print { 47 | public: 48 | // All the pins can be changed from the default values... 49 | PCD8544(unsigned char sclk = 3, /* clock (display pin 2) */ 50 | unsigned char sdin = 4, /* data-in (display pin 3) */ 51 | unsigned char dc = 5, /* data select (display pin 4) */ 52 | unsigned char reset = 2, /* reset (display pin 8) */ 53 | unsigned char sce = 7 ); /* enable (display pin 5) */ 54 | 55 | // Display initialization (dimensions in pixels)... 56 | void begin(unsigned char width=84, unsigned char height=48, unsigned char model=CHIP_PCD8544); 57 | void stop(); 58 | 59 | // Erase everything on the display... 60 | void clear(); 61 | void clearLine(); // ...or just the current line 62 | 63 | // Control the display's power state... 64 | void setPower(bool on); 65 | 66 | // For compatibility with the LiquidCrystal library... 67 | void display(); 68 | void noDisplay(); 69 | 70 | // Activate white-on-black mode (whole display)... 71 | void setInverse(bool inverse); 72 | 73 | // Place the cursor at the start of the current line... 74 | void home(); 75 | 76 | // Place the cursor at position (column, line)... 77 | void setCursor(unsigned char column, unsigned char line); 78 | 79 | // Assign a user-defined glyph (5x8) to an ASCII character (0-31)... 80 | void createChar(unsigned char chr, const unsigned char *glyph); 81 | 82 | // Write an ASCII character at the current cursor position (7-bit)... 83 | #if ARDUINO < 100 84 | virtual void write(uint8_t chr); 85 | #else 86 | virtual size_t write(uint8_t chr); 87 | #endif 88 | 89 | // Draw a bitmap at the current cursor position... 90 | void drawBitmap(const unsigned char *data, unsigned char columns, unsigned char lines); 91 | 92 | // Draw a chart element at the current cursor position... 93 | void drawColumn(unsigned char lines, unsigned char value); 94 | 95 | private: 96 | unsigned char pin_sclk; 97 | unsigned char pin_sdin; 98 | unsigned char pin_dc; 99 | unsigned char pin_reset; 100 | unsigned char pin_sce; 101 | 102 | // The size of the display, in pixels... 103 | unsigned char width; 104 | unsigned char height; 105 | 106 | // Current cursor position... 107 | unsigned char column; 108 | unsigned char line; 109 | 110 | // User-defined glyphs (below the ASCII space character)... 111 | const unsigned char *custom[' ']; 112 | 113 | // Send a command or data to the display... 114 | void send(unsigned char type, unsigned char data); 115 | }; 116 | 117 | 118 | #endif /* PCD8544_H */ 119 | 120 | 121 | /* vim: set expandtab ts=4 sw=4: */ 122 | -------------------------------------------------------------------------------- /VS1053/VS1053.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | #ifndef __VS1053_H__ 10 | #define __VS1053_H__ 11 | 12 | // STL headers 13 | // C headers 14 | // Framework headers 15 | #if ARDUINO < 100 16 | #include 17 | #else 18 | #include 19 | #endif 20 | // Library headers 21 | // Project headers 22 | #include "rtmidistart_plg.h" 23 | 24 | /** 25 | * Driver for VS1053 - Ogg Vorbis / MP3 / AAC / WMA / FLAC / MIDI Audio Codec Chip 26 | * 27 | * See http://www.vlsi.fi/en/products/vs1053.html 28 | */ 29 | 30 | class VS1053 31 | { 32 | private: 33 | uint8_t cs_pin; /**< Pin where CS line is connected */ 34 | uint8_t dcs_pin; /**< Pin where DCS line is connected */ 35 | uint8_t dreq_pin; /**< Pin where DREQ line is connected */ 36 | uint8_t reset_pin; /**< Pin where RESET line is connected */ 37 | uint8_t my_SPCR; /**< Value of the SPCR register how we like it. */ 38 | uint8_t my_SPSR; /**< Value of the SPSR register how we like it. */ 39 | protected: 40 | inline void await_data_request(void) const 41 | { 42 | while ( !digitalRead(dreq_pin) ); 43 | } 44 | 45 | inline void control_mode_on(void) const 46 | { 47 | digitalWrite(dcs_pin,HIGH); 48 | digitalWrite(cs_pin,LOW); 49 | } 50 | 51 | inline void control_mode_off(void) const 52 | { 53 | digitalWrite(cs_pin,HIGH); 54 | } 55 | 56 | inline void data_mode_on(void) const 57 | { 58 | digitalWrite(cs_pin,HIGH); 59 | digitalWrite(dcs_pin,LOW); 60 | } 61 | 62 | inline void data_mode_off(void) const 63 | { 64 | digitalWrite(dcs_pin,HIGH); 65 | } 66 | inline void save_our_spi(void) 67 | { 68 | my_SPSR = SPSR; 69 | my_SPCR = SPCR; 70 | } 71 | inline void set_our_spi(void) 72 | { 73 | SPSR = my_SPSR; 74 | SPCR = my_SPCR; 75 | } 76 | uint16_t read_register(uint8_t _reg) const; 77 | void write_register(uint8_t _reg,uint16_t _value) const; 78 | void sdi_send_buffer(const uint8_t* data,size_t len); 79 | void sdi_send_zeroes(size_t length); 80 | void print_byte_register(uint8_t reg) const; 81 | 82 | /** 83 | * Load a user code plugin 84 | * 85 | * @param buf Location of memory (in PROGMEM) where the code is 86 | * @param len Number of words to load 87 | */ 88 | void loadUserCode(const uint16_t* buf, size_t len) const; 89 | 90 | public: 91 | /** 92 | * Constructor 93 | * 94 | * Only sets pin values. Doesn't do touch the chip. Be sure to call begin()! 95 | */ 96 | VS1053( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin); 97 | 98 | /** 99 | * Begin operation 100 | * 101 | * Sets pins correctly, and prepares SPI bus. 102 | */ 103 | void begin(void); 104 | 105 | /** 106 | * Prepare to start playing 107 | * 108 | * Call this each time a new song starts. 109 | */ 110 | void startSong(void); 111 | 112 | /** 113 | * Play a chunk of data. Copies the data to the chip. Blocks until complete. 114 | * 115 | * @param data Pointer to where the data lives 116 | * @param len How many bytes of data to play 117 | */ 118 | void playChunk(const uint8_t* data, size_t len); 119 | 120 | /** 121 | * Finish playing a song. 122 | * 123 | * Call this after the last playChunk call. 124 | */ 125 | void stopSong(void); 126 | 127 | /** 128 | * Print configuration details 129 | * 130 | * Dumps all registers to stdout. Be sure to have stdout configured first 131 | * (see fdevopen() in avr/io.h). 132 | */ 133 | void printDetails(void) const; 134 | 135 | /** 136 | * Set the player volume 137 | * 138 | * @param vol Volume level from 0-255, lower is louder. 139 | */ 140 | void setVolume(uint8_t vol) const; 141 | 142 | 143 | void modeSwitch(void); 144 | 145 | /** 146 | * Play real-time MIDI. Useful for using the VS1053 to make an 147 | * instrument. Note that this implementation uses the SDI for 148 | * rtmidi commands. 149 | */ 150 | class RtMidi 151 | { 152 | private: 153 | VS1053& player; 154 | uint8_t buffer[6]; 155 | protected: 156 | /** 157 | * Write a single MIDI command out via SDI 158 | * 159 | * @param a First value (command byte) 160 | * @param b Second value (operand byte) 161 | * @param c Third value (optional 2nd operand) 162 | */ 163 | void write(uint8_t a, uint8_t b, uint8_t c = 0) 164 | { 165 | buffer[1] = a; 166 | buffer[3] = b; 167 | buffer[5] = c; 168 | player.playChunk(buffer,sizeof(buffer)); 169 | } 170 | public: 171 | /** 172 | * Construct from a VS1053 player 173 | * 174 | * @param _player Player which will play the MIDI notes 175 | */ 176 | RtMidi(VS1053& _player): player(_player) 177 | { 178 | memset(buffer,0,6); 179 | } 180 | /** 181 | * Enable the real-time MIDI mode. Only call this when you now want 182 | * to send rtmidi, not raw music data 183 | */ 184 | void begin(void) 185 | { 186 | player.loadUserCode(rtmidi_plugin,RTMIDI_PLUGIN_SIZE); 187 | } 188 | /** 189 | * Begin playing a note 190 | * 191 | * @param channel Which channel to play on 192 | * @param note Which note to play 193 | * @param volume How loud 194 | */ 195 | void noteOn(uint8_t channel, uint8_t note, uint8_t volume) 196 | { 197 | write(channel | 0x90, note, volume); 198 | } 199 | /** 200 | * Stop playing a note 201 | * 202 | * @param channel Which channel to afffect 203 | * @param note Which note to stop 204 | */ 205 | void noteOff(uint8_t channel, uint8_t note) 206 | { 207 | write(channel | 0x80, note, 0x45); 208 | } 209 | /** 210 | * Choose the drums instrument 211 | * 212 | * @param channel Which channel to play the drums on 213 | */ 214 | void selectDrums(uint8_t channel) 215 | { 216 | write(0xB0 | channel, 0, 0x78); 217 | write(0xC0 | channel ,30); 218 | } 219 | }; 220 | }; 221 | 222 | #endif // __VS1053_H__ 223 | // vim:cin:ai:sts=2 sw=2 ft=cpp 224 | -------------------------------------------------------------------------------- /PCD8544_mod/PCD8544_mod.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PCD8544 - Interface with Philips PCD8544 (or compatible) LCDs. 3 | * 4 | * Copyright (c) 2010 Carlos Rodrigues 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include "PCD8544_mod.h" 27 | 28 | #if ARDUINO < 100 29 | #include 30 | #else 31 | #include 32 | #endif 33 | 34 | #include 35 | 36 | 37 | #define PCD8544_CMD LOW 38 | #define PCD8544_DATA HIGH 39 | 40 | 41 | /* 42 | * If this was a ".h", it would get added to sketches when using 43 | * the "Sketch -> Import Library..." menu on the Arduino IDE... 44 | */ 45 | #include "charset.cpp" 46 | 47 | 48 | PCD8544::PCD8544(unsigned char sclk, unsigned char sdin, 49 | unsigned char dc, unsigned char reset, 50 | unsigned char sce): 51 | pin_sclk(sclk), 52 | pin_sdin(sdin), 53 | pin_dc(dc), 54 | pin_reset(reset), 55 | pin_sce(sce) 56 | {} 57 | 58 | 59 | void PCD8544::begin(unsigned char width, unsigned char height, unsigned char model) 60 | { 61 | this->width = width; 62 | this->height = height; 63 | 64 | this->column = 0; 65 | this->line = 0; 66 | 67 | // Sanitize the custom glyphs... 68 | memset(this->custom, 0, sizeof(this->custom)); 69 | 70 | // All pins are outputs (these displays cannot be read)... 71 | pinMode(this->pin_sclk, OUTPUT); 72 | pinMode(this->pin_sdin, OUTPUT); 73 | pinMode(this->pin_dc, OUTPUT); 74 | pinMode(this->pin_reset, OUTPUT); 75 | pinMode(this->pin_sce, OUTPUT); 76 | 77 | // Reset the controller state... 78 | digitalWrite(this->pin_reset, HIGH); 79 | digitalWrite(this->pin_sce, HIGH); 80 | digitalWrite(this->pin_reset, LOW); 81 | delay(100); 82 | digitalWrite(this->pin_reset, HIGH); 83 | 84 | // Set the LCD parameters... 85 | this->send(PCD8544_CMD, 0x21); // extended instruction set control (H=1) 86 | this->send(PCD8544_CMD, 0x13); // bias system (1:48) 87 | 88 | if (model == CHIP_ST7576) { 89 | this->send(PCD8544_CMD, 0xe0); // higher Vop, too faint at default 90 | this->send(PCD8544_CMD, 0x05); // partial display mode 91 | } else { 92 | this->send(PCD8544_CMD, 0xc2); // default Vop (3.06 + 66 * 0.06 = 7V) 93 | } 94 | 95 | this->send(PCD8544_CMD, 0x20); // extended instruction set control (H=0) 96 | this->send(PCD8544_CMD, 0x09); // all display segments on 97 | 98 | // Clear RAM contents... 99 | this->clear(); 100 | 101 | // Activate LCD... 102 | this->send(PCD8544_CMD, 0x08); // display blank 103 | this->send(PCD8544_CMD, 0x0c); // normal mode (0x0d = inverse mode) 104 | delay(100); 105 | 106 | // Place the cursor at the origin... 107 | this->send(PCD8544_CMD, 0x80); 108 | this->send(PCD8544_CMD, 0x40); 109 | } 110 | 111 | 112 | void PCD8544::stop() 113 | { 114 | this->clear(); 115 | this->setPower(false); 116 | } 117 | 118 | 119 | void PCD8544::clear() 120 | { 121 | this->setCursor(0, 0); 122 | 123 | for (unsigned short i = 0; i < this->width * (this->height/8); i++) { 124 | this->send(PCD8544_DATA, 0x00); 125 | } 126 | 127 | this->setCursor(0, 0); 128 | } 129 | 130 | 131 | void PCD8544::clearLine() 132 | { 133 | this->setCursor(0, this->line); 134 | 135 | for (unsigned char i = 0; i < this->width; i++) { 136 | this->send(PCD8544_DATA, 0x00); 137 | } 138 | 139 | this->setCursor(0, this->line); 140 | } 141 | 142 | 143 | void PCD8544::setPower(bool on) 144 | { 145 | this->send(PCD8544_CMD, on ? 0x20 : 0x24); 146 | } 147 | 148 | 149 | inline void PCD8544::display() 150 | { 151 | this->setPower(true); 152 | } 153 | 154 | 155 | inline void PCD8544::noDisplay() 156 | { 157 | this->setPower(false); 158 | } 159 | 160 | 161 | void PCD8544::setInverse(bool inverse) 162 | { 163 | this->send(PCD8544_CMD, inverse ? 0x0d : 0x0c); 164 | } 165 | 166 | 167 | void PCD8544::home() 168 | { 169 | this->setCursor(0, this->line); 170 | } 171 | 172 | 173 | void PCD8544::setCursor(unsigned char column, unsigned char line) 174 | { 175 | this->column = (column % this->width); 176 | this->line = (line % (this->height/9 + 1)); 177 | 178 | this->send(PCD8544_CMD, 0x80 | this->column); 179 | this->send(PCD8544_CMD, 0x40 | this->line); 180 | } 181 | 182 | 183 | void PCD8544::createChar(unsigned char chr, const unsigned char *glyph) 184 | { 185 | // ASCII 0-31 only... 186 | if (chr >= ' ') { 187 | return; 188 | } 189 | 190 | this->custom[chr] = glyph; 191 | } 192 | 193 | 194 | #if ARDUINO < 100 195 | void PCD8544::write(uint8_t chr) 196 | #else 197 | size_t PCD8544::write(uint8_t chr) 198 | #endif 199 | { 200 | // ASCII 7-bit only... 201 | if (chr >= 0x80) { 202 | #if ARDUINO < 100 203 | return; 204 | #else 205 | return 0; 206 | #endif 207 | } 208 | 209 | const unsigned char *glyph; 210 | unsigned char pgm_buffer[3]; 211 | 212 | if (chr > 'Z') { 213 | //Lowercase letters are replaced with capital letters (a -> A, b -> B, ...) 214 | memcpy_P(pgm_buffer, &charset[chr - ('@')], sizeof(pgm_buffer)); 215 | glyph = pgm_buffer; 216 | } 217 | else 218 | if (chr >= ' ') { 219 | // Regular ASCII characters are kept in flash to save RAM... 220 | memcpy_P(pgm_buffer, &charset[chr - ' '], sizeof(pgm_buffer)); 221 | glyph = pgm_buffer; 222 | } else { 223 | // Custom glyphs, on the other hand, are stored in RAM... 224 | if (this->custom[chr]) { 225 | glyph = this->custom[chr]; 226 | } else { 227 | // Default to a space character if unset... 228 | memcpy_P(pgm_buffer, &charset[0], sizeof(pgm_buffer)); 229 | glyph = pgm_buffer; 230 | } 231 | } 232 | 233 | // Output one column at a time... 234 | for (unsigned char i = 0; i < 3; i++) { 235 | this->send(PCD8544_DATA, glyph[i]); 236 | } 237 | 238 | // One column between characters... 239 | this->send(PCD8544_DATA, 0x00); 240 | 241 | // Update the cursor position... 242 | this->column = (this->column + 6) % this->width; 243 | 244 | if (this->column == 0) { 245 | this->line = (this->line + 1) % (this->height/9 + 1); 246 | } 247 | 248 | #if ARDUINO >= 100 249 | return 1; 250 | #endif 251 | } 252 | 253 | 254 | void PCD8544::drawBitmap(const unsigned char *data, unsigned char columns, unsigned char lines) 255 | { 256 | unsigned char scolumn = this->column; 257 | unsigned char sline = this->line; 258 | 259 | // The bitmap will be clipped at the right/bottom edge of the display... 260 | unsigned char mx = (scolumn + columns > this->width) ? (this->width - scolumn) : columns; 261 | unsigned char my = (sline + lines > this->height/8) ? (this->height/8 - sline) : lines; 262 | 263 | for (unsigned char y = 0; y < my; y++) { 264 | this->setCursor(scolumn, sline + y); 265 | 266 | for (unsigned char x = 0; x < mx; x++) { 267 | this->send(PCD8544_DATA, data[y * columns + x]); 268 | } 269 | } 270 | 271 | // Leave the cursor in a consistent position... 272 | this->setCursor(scolumn + columns, sline); 273 | } 274 | 275 | 276 | void PCD8544::drawColumn(unsigned char lines, unsigned char value) 277 | { 278 | unsigned char scolumn = this->column; 279 | unsigned char sline = this->line; 280 | 281 | // Keep "value" within range... 282 | if (value > lines*8) { 283 | value = lines*8; 284 | } 285 | 286 | // Find the line where "value" resides... 287 | unsigned char mark = (lines*8 - 1 - value)/8; 288 | 289 | // Clear the lines above the mark... 290 | for (unsigned char line = 0; line < mark; line++) { 291 | this->setCursor(scolumn, sline + line); 292 | this->send(PCD8544_DATA, 0x00); 293 | } 294 | 295 | // Compute the byte to draw at the "mark" line... 296 | unsigned char b = 0xff; 297 | for (unsigned char i = 0; i < lines*8 - mark*8 - value; i++) { 298 | b <<= 1; 299 | } 300 | 301 | this->setCursor(scolumn, sline + mark); 302 | this->send(PCD8544_DATA, b); 303 | 304 | // Fill the lines below the mark... 305 | for (unsigned char line = mark + 1; line < lines; line++) { 306 | this->setCursor(scolumn, sline + line); 307 | this->send(PCD8544_DATA, 0xff); 308 | } 309 | 310 | // Leave the cursor in a consistent position... 311 | this->setCursor(scolumn + 1, sline); 312 | } 313 | 314 | 315 | void PCD8544::send(unsigned char type, unsigned char data) 316 | { 317 | digitalWrite(this->pin_dc, type); 318 | 319 | digitalWrite(this->pin_sce, LOW); 320 | shiftOut(this->pin_sdin, this->pin_sclk, MSBFIRST, data); 321 | digitalWrite(this->pin_sce, HIGH); 322 | } 323 | 324 | 325 | /* vim: set expandtab ts=4 sw=4: */ 326 | -------------------------------------------------------------------------------- /VS1053/VS1053.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | 8 | 9 | 29 May 2015 :: Added by Vassilis Serasidis a function for defective LC Technology VS1053B boards. 10 | 11 | */ 12 | 13 | // STL headers 14 | // C headers 15 | #include 16 | // Framework headers 17 | // Library headers 18 | #include 19 | // Project headers 20 | // This component's header 21 | #include 22 | 23 | const uint8_t vs1053_chunk_size = 32; 24 | 25 | #undef PROGMEM 26 | #define PROGMEM __attribute__ ((section (".progmem.data"))) 27 | #undef PSTR 28 | #define PSTR(s) (__extension__({static char __c[] PROGMEM = (s); &__c[0];})) 29 | 30 | /****************************************************************************/ 31 | 32 | // SCI Registers 33 | 34 | const uint8_t SCI_MODE = 0x0; 35 | const uint8_t SCI_STATUS = 0x1; 36 | const uint8_t SCI_BASS = 0x2; 37 | const uint8_t SCI_CLOCKF = 0x3; 38 | const uint8_t SCI_DECODE_TIME = 0x4; 39 | const uint8_t SCI_AUDATA = 0x5; 40 | const uint8_t SCI_WRAM = 0x6; 41 | const uint8_t SCI_WRAMADDR = 0x7; 42 | const uint8_t SCI_HDAT0 = 0x8; 43 | const uint8_t SCI_HDAT1 = 0x9; 44 | const uint8_t SCI_AIADDR = 0xa; 45 | const uint8_t SCI_VOL = 0xb; 46 | const uint8_t SCI_AICTRL0 = 0xc; 47 | const uint8_t SCI_AICTRL1 = 0xd; 48 | const uint8_t SCI_AICTRL2 = 0xe; 49 | const uint8_t SCI_AICTRL3 = 0xf; 50 | const uint8_t SCI_num_registers = 0xf; 51 | 52 | // SCI_MODE bits 53 | 54 | const uint8_t SM_DIFF = 0; 55 | const uint8_t SM_LAYER12 = 1; 56 | const uint8_t SM_RESET = 2; 57 | const uint8_t SM_OUTOFWAV = 3; 58 | const uint8_t SM_EARSPEAKER_LO = 4; 59 | const uint8_t SM_TESTS = 5; 60 | const uint8_t SM_STREAM = 6; 61 | const uint8_t SM_EARSPEAKER_HI = 7; 62 | const uint8_t SM_DACT = 8; 63 | const uint8_t SM_SDIORD = 9; 64 | const uint8_t SM_SDISHARE = 10; 65 | const uint8_t SM_SDINEW = 11; 66 | const uint8_t SM_ADPCM = 12; 67 | const uint8_t SM_ADCPM_HP = 13; 68 | const uint8_t SM_LINE_IN = 14; 69 | const uint8_t SM_CLK_RANGE = 15; 70 | 71 | // Register names 72 | 73 | char reg_name_MODE[] PROGMEM = "MODE"; 74 | char reg_name_STATUS[] PROGMEM = "STATUS"; 75 | char reg_name_BASS[] PROGMEM = "BASS"; 76 | char reg_name_CLOCKF[] PROGMEM = "CLOCKF"; 77 | char reg_name_DECODE_TIME[] PROGMEM = "DECODE_TIME"; 78 | char reg_name_AUDATA[] PROGMEM = "AUDATA"; 79 | char reg_name_WRAM[] PROGMEM = "WRAM"; 80 | char reg_name_WRAMADDR[] PROGMEM = "WRAMADDR"; 81 | char reg_name_HDAT0[] PROGMEM = "HDAT0"; 82 | char reg_name_HDAT1[] PROGMEM = "HDAT1"; 83 | char reg_name_AIADDR[] PROGMEM = "AIADDR"; 84 | char reg_name_VOL[] PROGMEM = "VOL"; 85 | char reg_name_AICTRL0[] PROGMEM = "AICTRL0"; 86 | char reg_name_AICTRL1[] PROGMEM = "AICTRL1"; 87 | char reg_name_AICTRL2[] PROGMEM = "AICTRL2"; 88 | char reg_name_AICTRL3[] PROGMEM = "AICTRL3"; 89 | 90 | static PGM_P register_names[] PROGMEM = 91 | { 92 | reg_name_MODE, 93 | reg_name_STATUS, 94 | reg_name_BASS, 95 | reg_name_CLOCKF, 96 | reg_name_DECODE_TIME, 97 | reg_name_AUDATA, 98 | reg_name_WRAM, 99 | reg_name_WRAMADDR, 100 | reg_name_HDAT0, 101 | reg_name_HDAT1, 102 | reg_name_AIADDR, 103 | reg_name_VOL, 104 | reg_name_AICTRL0, 105 | reg_name_AICTRL1, 106 | reg_name_AICTRL2, 107 | reg_name_AICTRL3, 108 | }; 109 | 110 | /****************************************************************************/ 111 | 112 | /** 113 | * Spi saver 114 | * 115 | * Easy way to pop the SPI config registers onto the stack and pop 116 | * them off again 117 | */ 118 | struct spi_saver_t 119 | { 120 | uint8_t saved_SPCR; 121 | uint8_t saved_SPSR; 122 | 123 | spi_saver_t(void) 124 | { 125 | saved_SPCR = SPCR; 126 | saved_SPSR = SPSR; 127 | } 128 | ~spi_saver_t() 129 | { 130 | SPCR = saved_SPCR; 131 | SPSR = saved_SPSR; 132 | } 133 | }; 134 | 135 | /****************************************************************************/ 136 | 137 | uint16_t VS1053::read_register(uint8_t _reg) const 138 | { 139 | uint16_t result; 140 | control_mode_on(); 141 | delayMicroseconds(1); // tXCSS 142 | SPI.transfer(B11); // Read operation 143 | SPI.transfer(_reg); // Which register 144 | result = SPI.transfer(0xff) << 8; // read high byte 145 | result |= SPI.transfer(0xff); // read low byte 146 | delayMicroseconds(1); // tXCSH 147 | await_data_request(); 148 | control_mode_off(); 149 | return result; 150 | } 151 | 152 | /****************************************************************************/ 153 | 154 | void VS1053::write_register(uint8_t _reg,uint16_t _value) const 155 | { 156 | control_mode_on(); 157 | delayMicroseconds(1); // tXCSS 158 | SPI.transfer(B10); // Write operation 159 | SPI.transfer(_reg); // Which register 160 | SPI.transfer(_value >> 8); // Send hi byte 161 | SPI.transfer(_value & 0xff); // Send lo byte 162 | delayMicroseconds(1); // tXCSH 163 | await_data_request(); 164 | control_mode_off(); 165 | } 166 | 167 | /****************************************************************************/ 168 | 169 | void VS1053::sdi_send_buffer(const uint8_t* data, size_t len) 170 | { 171 | data_mode_on(); 172 | while ( len ) 173 | { 174 | await_data_request(); 175 | delayMicroseconds(3); 176 | 177 | size_t chunk_length = min(len,vs1053_chunk_size); 178 | len -= chunk_length; 179 | while ( chunk_length-- ) 180 | SPI.transfer(*data++); 181 | } 182 | data_mode_off(); 183 | } 184 | 185 | /****************************************************************************/ 186 | 187 | void VS1053::sdi_send_zeroes(size_t len) 188 | { 189 | data_mode_on(); 190 | while ( len ) 191 | { 192 | await_data_request(); 193 | 194 | size_t chunk_length = min(len,vs1053_chunk_size); 195 | len -= chunk_length; 196 | while ( chunk_length-- ) 197 | SPI.transfer(0); 198 | } 199 | data_mode_off(); 200 | } 201 | 202 | /****************************************************************************/ 203 | 204 | VS1053::VS1053( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin): 205 | cs_pin(_cs_pin), dcs_pin(_dcs_pin), dreq_pin(_dreq_pin), reset_pin(_reset_pin) 206 | { 207 | } 208 | 209 | /****************************************************************************/ 210 | 211 | void VS1053::begin(void) 212 | { 213 | spi_saver_t spi_saver; 214 | 215 | // Keep the chip in reset until we are ready 216 | pinMode(reset_pin,OUTPUT); 217 | digitalWrite(reset_pin,LOW); 218 | 219 | // The SCI and SDI will start deselected 220 | pinMode(cs_pin,OUTPUT); 221 | digitalWrite(cs_pin,HIGH); 222 | pinMode(dcs_pin,OUTPUT); 223 | digitalWrite(dcs_pin,HIGH); 224 | 225 | // DREQ is an input 226 | pinMode(dreq_pin,INPUT); 227 | 228 | // Boot VS1053D 229 | printf_P(PSTR("Booting VS1053...\r\n")); 230 | 231 | //Mp3PutInReset(); 232 | //Done above 233 | 234 | //Delay(1); 235 | delay(1); 236 | 237 | //InitSPI(); 238 | SPI.setClockDivider(SPI_CLOCK_DIV64); // Slow! 239 | 240 | /* Un-reset MP3 chip */ 241 | //Mp3DeselectControl(); 242 | //Mp3DeselectData(); 243 | //These are done above. 244 | 245 | //Mp3ReleaseFromReset(); 246 | digitalWrite(reset_pin,HIGH); 247 | 248 | //Mp3SetVolume(0xff,0xff); //Declick: Immediately switch analog off 249 | write_register(SCI_VOL,0xffff); // VOL 250 | 251 | /* Declick: Slow sample rate for slow analog part startup */ 252 | //Mp3WriteRegister(SPI_AUDATA, 0, 10); /* 10 Hz */ 253 | write_register(SCI_AUDATA,10); 254 | 255 | //Delay(100); 256 | delay(100); 257 | 258 | /* Switch on the analog parts */ 259 | //Mp3SetVolume(0xfe,0xfe); 260 | write_register(SCI_VOL,0xfefe); // VOL 261 | 262 | printf_P(PSTR("VS1053 still booting\r\n")); 263 | 264 | //Mp3WriteRegister (SPI_AUDATA, 31, 64); /* 8kHz */ 265 | write_register(SCI_AUDATA,44101); // 44.1kHz stereo 266 | 267 | //Mp3SetVolume(20,20); // Set initial volume (20 = -10dB) 268 | write_register(SCI_VOL,0x2020); // VOL 269 | 270 | //Mp3SoftReset(); 271 | write_register(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_RESET)); 272 | delay(1); 273 | await_data_request(); 274 | write_register(SCI_CLOCKF,0xB800); // Experimenting with higher clock settings 275 | delay(1); 276 | await_data_request(); 277 | 278 | //SPISetFastClock(); // Now you can set high speed SPI clock 279 | SPI.setClockDivider(SPI_CLOCK_DIV4); // Fastest available 280 | 281 | printf_P(PSTR("VS1053 Set\r\n")); 282 | printDetails(); 283 | printf_P(PSTR("VS1053 OK\r\n")); 284 | 285 | // Having set up our SPI state just the way we like it, save it for next time 286 | save_our_spi(); 287 | } 288 | 289 | /****************************************************************************/ 290 | 291 | void VS1053::setVolume(uint8_t vol) const 292 | { 293 | uint16_t value = vol; 294 | value <<= 8; 295 | value |= vol; 296 | 297 | write_register(SCI_VOL,value); // VOL 298 | } 299 | 300 | /****************************************************************************/ 301 | 302 | void VS1053::startSong(void) 303 | { 304 | spi_saver_t spi_saver; 305 | set_our_spi(); 306 | sdi_send_zeroes(10); 307 | } 308 | 309 | /****************************************************************************/ 310 | 311 | void VS1053::playChunk(const uint8_t* data, size_t len) 312 | { 313 | spi_saver_t spi_saver; 314 | set_our_spi(); 315 | sdi_send_buffer(data,len); 316 | } 317 | 318 | /****************************************************************************/ 319 | 320 | void VS1053::stopSong(void) 321 | { 322 | spi_saver_t spi_saver; 323 | set_our_spi(); 324 | sdi_send_zeroes(2048); 325 | } 326 | 327 | /****************************************************************************/ 328 | 329 | void VS1053::print_byte_register(uint8_t reg) const 330 | { 331 | const char *name = reinterpret_cast(pgm_read_word( register_names + reg )); 332 | char extra_tab = strlen_P(name) < 5 ? '\t' : 0; 333 | printf_P(PSTR("%02x %S\t%c = 0x%02x\r\n"),reg,name,extra_tab,read_register(reg)); 334 | } 335 | 336 | /****************************************************************************/ 337 | 338 | void VS1053::printDetails(void) const 339 | { 340 | spi_saver_t spi_saver; 341 | printf_P(PSTR("VS1053 Configuration:\r\n")); 342 | int i = 0; 343 | while ( i <= SCI_num_registers ) 344 | print_byte_register(i++); 345 | } 346 | 347 | /****************************************************************************/ 348 | void VS1053::modeSwitch(void) 349 | { 350 | //GPIO_DDR 351 | write_register(SCI_WRAMADDR, 0xc017); 352 | write_register(SCI_WRAM, 0x0003); 353 | //GPIO_ODATA 354 | write_register(SCI_WRAMADDR, 0xc019); 355 | write_register(SCI_WRAM, 0x0000); 356 | 357 | delay(1); 358 | write_register(SCI_MODE, (1< 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | 24 | Modified by Vassilis Serasidis for working with 3X6 pixels font 25 | Now the LCD can display up to 21 characters per line (total 6 lines). 26 | 27 | */ 28 | 29 | 30 | #include 31 | 32 | // 3X6 font library. 33 | // fonts3x6.h 34 | 35 | const PROGMEM unsigned char charset[][3] = { 36 | {0x00,0x00,0x00}, //space 37 | {0x00,0x5C,0x00}, //! 38 | {0x0C,0x00,0x0C}, //" 39 | {0x7C,0x28,0x7C}, //# 40 | {0x7C,0x44,0x7C}, //$ 41 | {0x24,0x10,0x48}, //% 42 | {0x28,0x54,0x08}, //& 43 | {0x00,0x0C,0x00}, //' 44 | {0x38,0x44,0x00}, //( 45 | {0x44,0x38,0x00}, //) 46 | {0x28,0x10,0x28}, //* 47 | {0x10,0x38,0x10}, //+ 48 | {0x80,0x40,0x00}, //, 49 | {0x10,0x10,0x10}, //- 50 | {0x00,0x40,0x00}, //. 51 | {0x20,0x10,0x08}, /// 52 | {0x7c,0x44,0x7c}, //0 53 | {0x00,0x7C,0x00}, //1 54 | {0x74,0x54,0x5c}, //2 55 | {0x54,0x54,0x7c}, //3 56 | {0x1C,0x10,0x7C}, //4 57 | {0x5c,0x54,0x74}, //5 58 | {0x7c,0x54,0x74}, //6 59 | {0x04,0x74,0x0C}, //7 60 | {0x7c,0x54,0x7c}, //8 61 | {0x5c,0x54,0x7c}, //9 62 | {0x00,0x50,0x00}, //: 63 | {0x80,0x50,0x00}, //// 64 | {0x10,0x28,0x44}, //< 65 | {0x28,0x28,0x28}, //= 66 | {0x44,0x28,0x10}, //> 67 | {0x04,0x54,0x08}, //? 68 | {0x38,0x4C,0x5C}, //@ 69 | {0x78,0x14,0x78}, //A 70 | {0x7C,0x54,0x28}, //B 71 | {0x38,0x44,0x44}, //C 72 | {0x7C,0x44,0x38}, //D 73 | {0x7C,0x54,0x44}, //E 74 | {0x7C,0x14,0x04}, //F 75 | {0x38,0x44,0x34}, //G 76 | {0x7C,0x10,0x7C}, //H 77 | {0x00,0x7C,0x00}, //I 78 | {0x20,0x40,0x3C}, //J 79 | {0x7C,0x10,0x6C}, //K 80 | {0x7C,0x40,0x40}, //L 81 | {0x7C,0x08,0x7C}, //M 82 | {0x7C,0x04,0x7C}, //N 83 | {0x7C,0x44,0x7C}, //O 84 | {0x7C,0x14,0x08}, //P 85 | {0x38,0x44,0x78}, //Q 86 | {0x7C,0x14,0x68}, //R 87 | {0x48,0x54,0x24}, //S 88 | {0x04,0x7C,0x04}, //T 89 | {0x7C,0x40,0x7C}, //U 90 | {0x3C,0x40,0x3C}, //V 91 | {0x7C,0x20,0x7C}, //W 92 | {0x6C,0x10,0x6C}, //X 93 | {0x1C,0x60,0x1C}, //Y 94 | {0x64,0x54,0x4C}, //Z 95 | {0x7C,0x44,0x00}, // [ 96 | {0x08,0x10,0x20}, // \ 97 | {0x44,0x7C,0x00}, // ] 98 | {0x08,0x04,0x08}, // ^ 99 | {0x80,0x80,0x80}, // _ 100 | {0x04,0x08,0x00} // ` 0x60 101 | }; 102 | /* 103 | {0x00,0x00,0x00}, // empty character 104 | {0x78,0x14,0x78}, //A 105 | {0x7C,0x54,0x28}, //B 106 | {0x38,0x44,0x44}, //C 107 | {0x7C,0x44,0x38}, //D 108 | {0x7C,0x54,0x44}, //E 109 | {0x7C,0x14,0x04}, //F 110 | {0x38,0x44,0x34}, //G 111 | {0x7C,0x10,0x7C}, //H 112 | {0x00,0x7C,0x00}, //I 113 | {0x20,0x40,0x3C}, //J 114 | {0x7C,0x10,0x6C}, //K 115 | {0x7C,0x40,0x40}, //L 116 | {0x7C,0x08,0x7C}, //M 117 | {0x7C,0x04,0x7C}, //N 118 | {0x7C,0x44,0x7C}, //O 119 | {0x7C,0x14,0x08}, //P 120 | {0x38,0x44,0x78}, //Q 121 | {0x7C,0x14,0x68}, //R 122 | {0x48,0x54,0x24}, //S 123 | {0x04,0x7C,0x04}, //T 124 | {0x7C,0x40,0x7C}, //U 125 | {0x3C,0x40,0x3C}, //V 126 | {0x7C,0x20,0x7C}, //W 127 | {0x6C,0x10,0x6C}, //X 128 | {0x1C,0x60,0x1C}, //Y 129 | {0x64,0x54,0x4C}, //Z 130 | {0x28,0x54,0x00}, // '{' 131 | {0x00,0x7C,0x00}, // '|' 132 | {0x00,0x54,0x28}, // '}' 133 | {0x20,0x30,0x10}, // '~' 134 | }; 135 | /* 136 | const PROGMEM unsigned char charset[][3] = { 137 | {0x00,0x00,0x00}, //space 138 | {0x00,0x5C,0x00}, //! 139 | {0x0C,0x00,0x0C}, //" 140 | {0x7C,0x28,0x7C}, //# 141 | {0x7C,0x44,0x7C}, //$ 142 | {0x24,0x10,0x48}, //% 143 | {0x28,0x54,0x08}, //& 144 | {0x00,0x0C,0x00}, //' 145 | {0x38,0x44,0x00}, //( 146 | {0x44,0x38,0x00}, //) 147 | {0x20,0x10,0x08}, /// 148 | {0x10,0x38,0x10}, //+ 149 | {0x80,0x40,0x00}, //, 150 | {0x10,0x10,0x10}, //- 151 | {0x00,0x40,0x00}, //. 152 | {0x20,0x10,0x08}, /// 153 | {0x7c,0x44,0x7c}, //0 154 | {0x00,0x7C,0x00}, //1 155 | {0x74,0x54,0x5c}, //2 156 | {0x54,0x54,0x7c}, //3 157 | {0x1C,0x10,0x7C}, //4 158 | {0x5c,0x54,0x74}, //5 159 | {0x7c,0x54,0x74}, //6 160 | {0x04,0x74,0x0C}, //7 161 | {0x7c,0x54,0x7c}, //8 162 | {0x5c,0x54,0x7c}, //9 163 | {0x00,0x50,0x00}, //: 164 | {0x80,0x50,0x00}, //// 165 | {0x10,0x28,0x44}, //< 166 | {0x28,0x28,0x28}, //= 167 | {0x44,0x28,0x10}, //> 168 | {0x04,0x54,0x08}, //? 169 | {0x38,0x4C,0x5C}, //@ 170 | {0x78,0x14,0x78}, //A 171 | {0x7C,0x54,0x28}, //B 172 | {0x38,0x44,0x44}, //C 173 | {0x7C,0x44,0x38}, //D 174 | {0x7C,0x54,0x44}, //E 175 | {0x7C,0x14,0x04}, //F 176 | {0x38,0x44,0x34}, //G 177 | {0x7C,0x10,0x7C}, //H 178 | {0x00,0x7C,0x00}, //I 179 | {0x20,0x40,0x3C}, //J 180 | {0x7C,0x10,0x6C}, //K 181 | {0x7C,0x40,0x40}, //L 182 | {0x7C,0x08,0x7C}, //M 183 | {0x7C,0x04,0x7C}, //N 184 | {0x7C,0x44,0x7C}, //O 185 | {0x7C,0x14,0x08}, //P 186 | {0x38,0x44,0x78}, //Q 187 | {0x7C,0x14,0x68}, //R 188 | {0x48,0x54,0x24}, //S 189 | {0x04,0x7C,0x04}, //T 190 | {0x7C,0x40,0x7C}, //U 191 | {0x3C,0x40,0x3C}, //V 192 | {0x7C,0x20,0x7C}, //W 193 | {0x6C,0x10,0x6C}, //X 194 | {0x1C,0x60,0x1C}, //Y 195 | {0x64,0x54,0x4C}, //Z 196 | {0x7C,0x44,0x00}, // [ 197 | {0x08,0x10,0x20}, // \ 198 | {0x44,0x7C,0x00}, // ] 199 | {0x08,0x04,0x08}, // ^ 200 | {0x80,0x80,0x80}, // _ 201 | {0x04,0x08,0x00}, // ` 0x60 202 | {0x00,0x00,0x00}, // empty character 203 | {0x30,0x48,0x70}, // 'a' 204 | {0x7C,0x50,0x70}, // 'b' 205 | {0x70,0x50,0x50}, // 'c' 206 | {0x70,0x50,0x7C}, // 'd' 207 | {0x30,0x68,0x50}, // 'e' 208 | {0x10,0x7c,0x14}, // 'f' 209 | {0x50,0x68,0x30}, // 'g' 210 | {0x7C,0x08,0x70}, // 'h' 211 | {0x00,0x68,0x00}, // 'i' 212 | {0x40,0x34,0x00}, // 'j' 213 | {0x7C,0x20,0x50}, // 'k' 214 | {0x00,0x7C,0x00}, // 'l' 215 | {0x78,0x18,0x78}, // 'm' 216 | {0x70,0x08,0x70}, // 'n' 217 | {0x30,0x48,0x30}, // 'o' 218 | {0x78,0x28,0x10}, // 'p' 219 | {0x10,0x28,0x78}, // 'q' 220 | {0x78,0x10,0x00}, // 'r' 221 | {0x00,0x50,0x28}, // 's' 222 | {0x08,0x7C,0x08}, // 't' 223 | {0x38,0x40,0x38}, // 'u' 224 | {0x18,0x60,0x18}, // 'v' 225 | {0x38,0x60,0x38}, // 'w' 226 | {0x48,0x30,0x48}, // 'x' 227 | {0x58,0x60,0x38}, // 'y' 228 | {0x68,0x78,0x58}, // 'z' 229 | {0x28,0x54,0x00}, // '{' 230 | {0x00,0x7C,0x00}, // '|' 231 | {0x00,0x54,0x28}, // '}' 232 | {0x20,0x30,0x10}, // '~' 233 | }; 234 | 235 | // The 7-bit ASCII character set... 236 | const PROGMEM unsigned char charset[][5] = { 237 | { 0x00, 0x00, 0x00, 0x00, 0x00 }, // 20 space 238 | { 0x00, 0x00, 0x5f, 0x00, 0x00 }, // 21 ! 239 | { 0x00, 0x07, 0x00, 0x07, 0x00 }, // 22 " 240 | { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // 23 # 241 | { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // 24 $ 242 | { 0x23, 0x13, 0x08, 0x64, 0x62 }, // 25 % 243 | { 0x36, 0x49, 0x55, 0x22, 0x50 }, // 26 & 244 | { 0x00, 0x05, 0x03, 0x00, 0x00 }, // 27 ' 245 | { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // 28 ( 246 | { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // 29 ) 247 | { 0x14, 0x08, 0x3e, 0x08, 0x14 }, // 2a * 248 | { 0x08, 0x08, 0x3e, 0x08, 0x08 }, // 2b + 249 | { 0x00, 0x50, 0x30, 0x00, 0x00 }, // 2c , 250 | { 0x08, 0x08, 0x08, 0x08, 0x08 }, // 2d - 251 | { 0x00, 0x60, 0x60, 0x00, 0x00 }, // 2e . 252 | { 0x20, 0x10, 0x08, 0x04, 0x02 }, // 2f / 253 | { 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 30 0 254 | { 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 31 1 255 | { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 32 2 256 | { 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 33 3 257 | { 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 34 4 258 | { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 35 5 259 | { 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 36 6 260 | { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 37 7 261 | { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 38 8 262 | { 0x06, 0x49, 0x49, 0x29, 0x1e }, // 39 9 263 | { 0x00, 0x36, 0x36, 0x00, 0x00 }, // 3a : 264 | { 0x00, 0x56, 0x36, 0x00, 0x00 }, // 3b ; 265 | { 0x08, 0x14, 0x22, 0x41, 0x00 }, // 3c < 266 | { 0x14, 0x14, 0x14, 0x14, 0x14 }, // 3d = 267 | { 0x00, 0x41, 0x22, 0x14, 0x08 }, // 3e > 268 | { 0x02, 0x01, 0x51, 0x09, 0x06 }, // 3f ? 269 | { 0x32, 0x49, 0x79, 0x41, 0x3e }, // 40 @ 270 | { 0x7e, 0x11, 0x11, 0x11, 0x7e }, // 41 A 271 | { 0x7f, 0x49, 0x49, 0x49, 0x36 }, // 42 B 272 | { 0x3e, 0x41, 0x41, 0x41, 0x22 }, // 43 C 273 | { 0x7f, 0x41, 0x41, 0x22, 0x1c }, // 44 D 274 | { 0x7f, 0x49, 0x49, 0x49, 0x41 }, // 45 E 275 | { 0x7f, 0x09, 0x09, 0x09, 0x01 }, // 46 F 276 | { 0x3e, 0x41, 0x49, 0x49, 0x7a }, // 47 G 277 | { 0x7f, 0x08, 0x08, 0x08, 0x7f }, // 48 H 278 | { 0x00, 0x41, 0x7f, 0x41, 0x00 }, // 49 I 279 | { 0x20, 0x40, 0x41, 0x3f, 0x01 }, // 4a J 280 | { 0x7f, 0x08, 0x14, 0x22, 0x41 }, // 4b K 281 | { 0x7f, 0x40, 0x40, 0x40, 0x40 }, // 4c L 282 | { 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // 4d M 283 | { 0x7f, 0x04, 0x08, 0x10, 0x7f }, // 4e N 284 | { 0x3e, 0x41, 0x41, 0x41, 0x3e }, // 4f O 285 | { 0x7f, 0x09, 0x09, 0x09, 0x06 }, // 50 P 286 | { 0x3e, 0x41, 0x51, 0x21, 0x5e }, // 51 Q 287 | { 0x7f, 0x09, 0x19, 0x29, 0x46 }, // 52 R 288 | { 0x46, 0x49, 0x49, 0x49, 0x31 }, // 53 S 289 | { 0x01, 0x01, 0x7f, 0x01, 0x01 }, // 54 T 290 | { 0x3f, 0x40, 0x40, 0x40, 0x3f }, // 55 U 291 | { 0x1f, 0x20, 0x40, 0x20, 0x1f }, // 56 V 292 | { 0x3f, 0x40, 0x38, 0x40, 0x3f }, // 57 W 293 | { 0x63, 0x14, 0x08, 0x14, 0x63 }, // 58 X 294 | { 0x07, 0x08, 0x70, 0x08, 0x07 }, // 59 Y 295 | { 0x61, 0x51, 0x49, 0x45, 0x43 }, // 5a Z 296 | { 0x00, 0x7f, 0x41, 0x41, 0x00 }, // 5b [ 297 | { 0x02, 0x04, 0x08, 0x10, 0x20 }, // 5c backslash 298 | { 0x00, 0x41, 0x41, 0x7f, 0x00 }, // 5d ] 299 | { 0x04, 0x02, 0x01, 0x02, 0x04 }, // 5e ^ 300 | { 0x40, 0x40, 0x40, 0x40, 0x40 }, // 5f _ 301 | { 0x00, 0x01, 0x02, 0x04, 0x00 }, // 60 ` 302 | { 0x20, 0x54, 0x54, 0x54, 0x78 }, // 61 a 303 | { 0x7f, 0x48, 0x44, 0x44, 0x38 }, // 62 b 304 | { 0x38, 0x44, 0x44, 0x44, 0x20 }, // 63 c 305 | { 0x38, 0x44, 0x44, 0x48, 0x7f }, // 64 d 306 | { 0x38, 0x54, 0x54, 0x54, 0x18 }, // 65 e 307 | { 0x08, 0x7e, 0x09, 0x01, 0x02 }, // 66 f 308 | { 0x0c, 0x52, 0x52, 0x52, 0x3e }, // 67 g 309 | { 0x7f, 0x08, 0x04, 0x04, 0x78 }, // 68 h 310 | { 0x00, 0x44, 0x7d, 0x40, 0x00 }, // 69 i 311 | { 0x20, 0x40, 0x44, 0x3d, 0x00 }, // 6a j 312 | { 0x7f, 0x10, 0x28, 0x44, 0x00 }, // 6b k 313 | { 0x00, 0x41, 0x7f, 0x40, 0x00 }, // 6c l 314 | { 0x7c, 0x04, 0x18, 0x04, 0x78 }, // 6d m 315 | { 0x7c, 0x08, 0x04, 0x04, 0x78 }, // 6e n 316 | { 0x38, 0x44, 0x44, 0x44, 0x38 }, // 6f o 317 | { 0x7c, 0x14, 0x14, 0x14, 0x08 }, // 70 p 318 | { 0x08, 0x14, 0x14, 0x18, 0x7c }, // 71 q 319 | { 0x7c, 0x08, 0x04, 0x04, 0x08 }, // 72 r 320 | { 0x48, 0x54, 0x54, 0x54, 0x20 }, // 73 s 321 | { 0x04, 0x3f, 0x44, 0x40, 0x20 }, // 74 t 322 | { 0x3c, 0x40, 0x40, 0x20, 0x7c }, // 75 u 323 | { 0x1c, 0x20, 0x40, 0x20, 0x1c }, // 76 v 324 | { 0x3c, 0x40, 0x30, 0x40, 0x3c }, // 77 w 325 | { 0x44, 0x28, 0x10, 0x28, 0x44 }, // 78 x 326 | { 0x0c, 0x50, 0x50, 0x50, 0x3c }, // 79 y 327 | { 0x44, 0x64, 0x54, 0x4c, 0x44 }, // 7a z 328 | { 0x00, 0x08, 0x36, 0x41, 0x00 }, // 7b { 329 | { 0x00, 0x00, 0x7f, 0x00, 0x00 }, // 7c | 330 | { 0x00, 0x41, 0x36, 0x08, 0x00 }, // 7d } 331 | { 0x10, 0x08, 0x08, 0x10, 0x08 }, // 7e ~ 332 | { 0x00, 0x00, 0x00, 0x00, 0x00 } // 7f 333 | }; 334 | 335 | */ 336 | /* vim: set expandtab ts=4 sw=4: */ 337 | -------------------------------------------------------------------------------- /VS1053/examples/hello.ino: -------------------------------------------------------------------------------- 1 | /* 2 | vs1003_hello 3 | 4 | A simple MP3 flow player to test if board and library are working together. 5 | The following sketch should say "Hello" every 0.5s :) 6 | Created 2012-04-05 by Andrey Karpov 7 | 8 | 29 May 2015 :: Added by Vassilis Serasidis a function for defective LC Technology VS1053B boards. 9 | 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "printf.h" 21 | #include 22 | #include 23 | 24 | /* 25 | * VS1053 development board connected by it's header pins the following way: 26 | * 27 | * GND - GND 28 | * XDCS - D6 29 | * DREQ - D7 30 | * XRES - D8 31 | * XCS - D9 32 | * SCLK - D13 33 | * SI - D11 34 | * SO - D12 35 | * GND - GND 36 | * 5V - 5V 37 | */ 38 | VS1053 player(9, 6, 7, 8); // cs_pin, dcs_pin, dreq_pin, reset_pin 39 | 40 | unsigned char HelloMP3[] = { 41 | 0xFF,0xF2,0x40,0xC0,0x19,0xB7,0x00,0x14,0x02,0xE6,0x5C, /* ..@.......\ */ 42 | 0x01,0x92,0x68,0x01,0xF1,0x5E,0x03,0x08,0xF0,0x24,0x80, /* ..h..^...$. */ 43 | 0x05,0x9E,0x20,0xC6,0xFC,0x12,0x32,0x5C,0xBF,0xF9,0xB9, /* .. ...2\... */ 44 | 0x20,0x4A,0x7F,0x85,0xEC,0x4C,0xCD,0xC7,0x27,0xFE,0x5C, /* J...L..'.\ */ 45 | 0x34,0x25,0xCB,0xE6,0xFF,0xFF,0x8E,0x42,0xE1,0xA0,0x5E, /* 4%.....B..^ */ 46 | 0xCA,0x6E,0x30,0x9F,0xFF,0xF8,0xC2,0x12,0x84,0xB9,0x7C, /* .n0.......| */ 47 | 0xDC,0x61,0x09,0x4A,0x7F,0xFF,0xFF,0xF9,0x7D,0x32,0x51, /* .a.J....}2Q */ 48 | 0x09,0x7C,0xE1,0xA5,0x6E,0xB4,0xFF,0xFF,0xFF,0xFF,0xD3, /* .|..n...... */ 49 | 0x34,0x41,0x91,0xF0,0x11,0x8F,0x00,0x0F,0x81,0x9C,0x10, /* 4A......... */ 50 | 0xEE,0x59,0xCE,0x56,0x67,0xFF,0xF2,0x42,0xC0,0xEC,0x53, /* .Y.Vg..B..S */ 51 | 0x09,0x15,0xF9,0xAA,0xA8,0x0D,0xD9,0x40,0x00,0xCA,0x34, /* .......@..4 */ 52 | 0x53,0xD9,0x18,0xAB,0x7D,0xF7,0x89,0x3F,0x11,0x38,0x94, /* S...}..?.8. */ 53 | 0x82,0x59,0x93,0x20,0x6A,0x0C,0xEE,0x8E,0x58,0xFA,0x38, /* .Y. j...X.8 */ 54 | 0x82,0xCA,0xF0,0x58,0xBB,0xDA,0x0C,0x50,0x56,0x1F,0xBB, /* ...X...PV.. */ 55 | 0x18,0x5D,0x8B,0x9F,0xDA,0x71,0x4F,0xFF,0xBD,0xFE,0xEF, /* .]...qO.... */ 56 | 0x69,0x36,0x86,0x3C,0x50,0xBB,0x0A,0x07,0x89,0x54,0xF0, /* i6. .(4.... */ 59 | 0xC0,0x01,0x75,0xF8,0x05,0x6B,0x5F,0x41,0x17,0x0B,0xE7, /* ..u..k_A... */ 60 | 0xFF,0xF2,0x40,0xC0,0x61,0xE5,0x0B,0x16,0x09,0xC6,0xC5, /* ..@.a...... */ 61 | 0x74,0x7B,0xCC,0x94,0x7A,0xF7,0x80,0x76,0xB2,0xD2,0xF8, /* t{..z..v... */ 62 | 0x39,0x06,0x38,0xFD,0x71,0xC5,0xDE,0x3A,0x38,0xBF,0xD5, /* 9.8.q..:8.. */ 63 | 0xF7,0x12,0x37,0xCB,0xF5,0x63,0x0C,0x9B,0xCE,0x77,0x25, /* ..7..c...w% */ 64 | 0xED,0xFB,0x3D,0x6B,0x35,0xF9,0x6D,0xD7,0xF9,0x2C,0xD1, /* ..=k5.m..,. */ 65 | 0x97,0x15,0x87,0x93,0xA4,0x49,0x4A,0x18,0x16,0x07,0xA1, /* .....IJ.... */ 66 | 0x60,0xF7,0x52,0x94,0xDB,0x02,0x16,0x70,0xB2,0xD8,0x80, /* `.R....p... */ 67 | 0x30,0xC2,0x94,0x40,0x81,0x74,0x5A,0x19,0x7A,0x80,0x60, /* 0..@.tZ.z.` */ 68 | 0x41,0x21,0x46,0x95,0xD5,0xC4,0x40,0xD2,0x01,0xC0,0x01, /* A!F...@.... */ 69 | 0xDA,0xD9,0xA0,0xB1,0x01,0xFF,0xF2,0x42,0xC0,0x82,0x10, /* .......B... */ 70 | 0x0B,0x12,0xF9,0x9E,0xC9,0x7E,0x7A,0xC6,0x95,0x55,0x09, /* .....~z..U. */ 71 | 0x8B,0x19,0x5E,0x8B,0x26,0xCA,0xEB,0x68,0x8A,0x05,0x8F, /* ..^.&..h... */ 72 | 0x36,0xA5,0xA5,0x03,0xB8,0x9C,0xED,0x24,0x51,0x59,0x90, /* 6......$QY. */ 73 | 0xF6,0xC5,0x7D,0xB5,0xAD,0xAF,0xF6,0x3B,0x18,0xEF,0x3F, /* ..}....;..? */ 74 | 0xFF,0xFF,0x4E,0xDE,0x16,0x66,0x0B,0xAA,0x33,0x23,0xDD, /* ..N..f..3#. */ 75 | 0x9C,0x4E,0x6E,0x55,0x22,0x9D,0xA2,0x40,0xA6,0x36,0x31, /* .NnU"..@.61 */ 76 | 0x69,0xA5,0xE1,0xD9,0x7F,0xF7,0xC6,0xCC,0x48,0x00,0x0E, /* i.......H.. */ 77 | 0x90,0x16,0x00,0x0F,0xDE,0x6E,0x80,0x11,0x0C,0x9A,0x4F, /* .....n....O */ 78 | 0x56,0xDB,0x88,0xD3,0xB2,0x1C,0x00,0xE0,0x2E,0x3E,0xAC, /* V........>. */ 79 | 0xFF,0xF2,0x40,0xC0,0x1C,0xE5,0x19,0x13,0x31,0x4E,0xCD, /* ..@.....1N. */ 80 | 0x9E,0xC3,0x06,0x71,0x03,0x85,0xE5,0xB5,0x6D,0x88,0x50, /* ...q....m.P */ 81 | 0x8E,0x0E,0x17,0x3B,0x19,0xFB,0x4E,0x3B,0x99,0xEF,0x4C, /* ...;..N;..L */ 82 | 0x9E,0xF7,0x7B,0x31,0x7C,0x3C,0x5F,0xFF,0xF4,0xF8,0xE3, /* ..{1|<_.... */ 83 | 0x92,0x42,0x07,0x8E,0x83,0x8E,0x0F,0x05,0x08,0x91,0xA3, /* .B......... */ 84 | 0x16,0xE2,0xDF,0xB7,0x62,0x60,0x48,0x31,0x3C,0xFF,0xD4, /* ....b`H1<.. */ 85 | 0x9E,0x0C,0x68,0x00,0x77,0x54,0xE3,0x1E,0x05,0xC5,0xF8, /* ..h.wT..... */ 86 | 0xEA,0x8D,0x82,0x9D,0x08,0xA9,0x06,0x8D,0x1E,0x5D,0x7C, /* .........]| */ 87 | 0x7F,0x08,0xC0,0x50,0x45,0x42,0xD0,0x36,0xF8,0xB2,0x4D, /* ...PEB.6..M */ 88 | 0x53,0x0C,0x80,0x3B,0x4D,0xFF,0xF2,0x42,0xC0,0x2F,0x3C, /* S..;M..B./< */ 89 | 0x25,0x19,0x29,0xFE,0xBC,0x2E,0xC4,0xD0,0x99,0x4C,0x48, /* %.)......LH */ 90 | 0xB0,0x9C,0x49,0xD2,0x1A,0x2D,0x02,0xC2,0x79,0x69,0x16, /* ..I..-..yi. */ 91 | 0x92,0xA8,0xC5,0xAB,0x45,0x5A,0x68,0xE8,0x75,0x57,0xCD, /* ....EZh.uW. */ 92 | 0xF1,0xB9,0xAA,0x13,0x88,0xE4,0x87,0x42,0x15,0xB3,0x58, /* .......B..X */ 93 | 0xF5,0xA3,0x46,0xB1,0xCF,0xD3,0x59,0x7E,0xBA,0xB5,0xA7, /* ..F...Y~... */ 94 | 0x6B,0x0B,0x17,0x57,0x6B,0x5C,0x4A,0xCD,0x53,0x76,0x2A, /* k..Wk\J.Sv* */ 95 | 0x1D,0x28,0xC5,0x1C,0x76,0x5C,0xDD,0x0A,0x00,0x4B,0xC0, /* .(..v\...K. */ 96 | 0x1B,0xCA,0xA8,0xE9,0x81,0x5B,0xA6,0xDC,0xA4,0x59,0x13, /* .....[...Y. */ 97 | 0xFC,0xBA,0x8F,0x98,0x79,0x44,0x25,0xC9,0x35,0x38,0xCA, /* ....yD%.58. */ 98 | 0xFF,0xF2,0x40,0xC0,0xB9,0x7D,0x1A,0x13,0x79,0x6A,0xC8, /* ..@..}..yj. */ 99 | 0x3E,0xC4,0x46,0x94,0x8D,0x3C,0x67,0x85,0xB1,0xA8,0x89, /* >.F...n.f.. */ 110 | 0xE3,0xC2,0xE0,0x29,0x43,0x87,0x5F,0x4F,0x27,0x9C,0x2C, /* ...)C._O'., */ 111 | 0xD0,0x91,0xF3,0x87,0x9B,0x54,0xED,0xD1,0xB4,0xF3,0x39, /* .....T....9 */ 112 | 0x87,0x22,0x06,0x86,0x0D,0x71,0xE4,0x6F,0x2A,0x08,0x04, /* ."...q.o*.. */ 113 | 0xC0,0x03,0x2A,0xB1,0xE2,0x05,0x4D,0x64,0xA1,0x9C,0xA6, /* ..*...Md... */ 114 | 0x0D,0x41,0xA6,0xF2,0x7A,0xC1,0x30,0xC3,0x38,0x26,0x09, /* .A..z.0.8&. */ 115 | 0x50,0x08,0xC4,0xF6,0x30,0x0C,0xA6,0xA9,0x17,0x00,0x13, /* P...0...... */ 116 | 0x0C,0xDC,0xC4,0x2F,0x28,0xEB,0x3F,0xCD,0x7A,0x3D,0x2F, /* .../(.?.z=/ */ 117 | 0xFF,0xF2,0x40,0xC0,0x18,0x6F,0x2E,0x13,0xA1,0xF2,0xBC, /* ..@..o..... */ 118 | 0x36,0xCB,0x4E,0x99,0x6E,0xFC,0xEE,0xC5,0xF0,0xA0,0xB7, /* 6.N.n...... */ 119 | 0x92,0xD4,0xEE,0x79,0x7C,0x50,0x5D,0xE5,0x04,0x94,0xA9, /* ...y|P].... */ 120 | 0x76,0xCF,0x6C,0x70,0xDD,0x0D,0xD4,0xEE,0xED,0x98,0xE8, /* v.lp....... */ 121 | 0xC8,0x35,0x36,0x7A,0x0C,0x05,0x80,0x03,0xBC,0xBE,0x91, /* .56z....... */ 122 | 0x00,0x7C,0xAE,0x65,0xB8,0x91,0xA3,0x33,0xBA,0x68,0x60, /* .|.e...3.h` */ 123 | 0xD4,0x1A,0x66,0xF8,0x43,0xA0,0x20,0x89,0xE7,0x80,0xD8, /* ..f.C. .... */ 124 | 0x1E,0x4F,0xA0,0x04,0x60,0x06,0x0A,0xA4,0x91,0x24,0xFA, /* .O..`....$. */ 125 | 0x9F,0x57,0x53,0xF4,0x7A,0xDB,0x5F,0x56,0xE3,0x6E,0x0B, /* .WS.z._V.n. */ 126 | 0x8B,0x3A,0x1C,0xF9,0x5E,0xFF,0xF2,0x42,0xC0,0xB1,0x00, /* .:..^..B... */ 127 | 0x38,0x14,0x09,0xEE,0xB4,0x36,0xD3,0x4E,0x99,0xA4,0x78, /* 8....6.N..x */ 128 | 0x94,0x73,0xC4,0x66,0x30,0xF5,0xEA,0xDB,0xBA,0x67,0x67, /* .s.f0....gg */ 129 | 0x95,0x6B,0xAB,0x68,0x5D,0x08,0xA1,0x39,0x56,0xAB,0x1E, /* .k.h]..9V.. */ 130 | 0xD5,0x03,0xE8,0x01,0x70,0x00,0xB3,0x93,0x33,0x19,0x8C, /* ....p...3.. */ 131 | 0x61,0x8F,0xBB,0x5D,0x24,0x12,0x63,0xD3,0x4B,0x5D,0x91, /* a..]$.c.K]. */ 132 | 0x08,0x43,0x22,0x56,0x1A,0xC5,0x10,0x21,0x84,0xA8,0xEA, /* .C"V...!... */ 133 | 0x80,0xBF,0x16,0x8E,0x3D,0x46,0x18,0x9C,0x6E,0x9A,0x91, /* ....=F..n.. */ 134 | 0xE6,0xC9,0x6F,0xD2,0x7D,0x27,0xD7,0xE9,0x6B,0xFF,0x0A, /* ..o.}'..k.. */ 135 | 0x03,0x43,0x89,0xD5,0xBF,0x52,0x97,0x0A,0x25,0x95,0x0D, /* .C...R..%.. */ 136 | 0xFF,0xF2,0x40,0xC0,0xF5,0xC3,0x41,0x13,0x81,0xEE,0xA8, /* ..@...A.... */ 137 | 0x5E,0xD3,0x44,0x98,0xFC,0xCF,0x97,0xF9,0x58,0xB5,0x33, /* ^.D.....X.3 */ 138 | 0xB1,0x85,0x47,0x86,0xD7,0x98,0x01,0x3B,0xA3,0x4F,0x7E, /* ..G....;.O~ */ 139 | 0x04,0xA6,0xC3,0x39,0x21,0x70,0x27,0x62,0xB5,0x18,0x10, /* ...9!p'b... */ 140 | 0x09,0x99,0x00,0x8B,0x7E,0xF2,0xBF,0x52,0x18,0x26,0x30, /* ....~..R.&0 */ 141 | 0x1C,0xB0,0x01,0x49,0x30,0xE0,0xC3,0x11,0x46,0x05,0xCC, /* ...I0...F.. */ 142 | 0x49,0x14,0x28,0xB2,0xED,0x4B,0x57,0x5A,0x2F,0xB7,0x46, /* I.(..KWZ/.F */ 143 | 0x63,0x34,0xD2,0xDA,0x9F,0x56,0x32,0xB7,0xA2,0x25,0xFF, /* c4...V2..%. */ 144 | 0x94,0x28,0x33,0x7F,0x3B,0xC4,0x50,0xEC,0xB1,0xE2,0x26, /* .(3.;.P...& */ 145 | 0xA1,0xB7,0x07,0x7F,0xFB,0xFF,0xF2,0x42,0xC0,0x67,0x6A, /* .......B.gj */ 146 | 0x4C,0x13,0xF9,0x6A,0x90,0x7E,0xDB,0x44,0x94,0x3F,0xFF, /* L..j.~.D.?. */ 147 | 0x14,0xD6,0x2A,0xFF,0xFF,0xC1,0x34,0x8C,0x48,0x22,0x00, /* ..*...4.H". */ 148 | 0x06,0x8F,0x21,0xFD,0x64,0x60,0x04,0x92,0x42,0xEA,0x74, /* ..!.d`..B.t */ 149 | 0x32,0x37,0xAA,0x5A,0x9F,0x67,0x01,0x8B,0x3F,0x37,0x31, /* 27.Z.g..?71 */ 150 | 0xDD,0x06,0x3C,0x01,0x34,0x30,0xE0,0x5C,0x78,0x78,0xCB, /* ..<.40.\xx. */ 151 | 0xD6,0xF1,0x31,0x8A,0x69,0x61,0x93,0x92,0x42,0xCE,0x4B, /* ..1.ia..B.K */ 152 | 0xC5,0x02,0x4E,0x73,0xC6,0x24,0x30,0xCD,0x08,0x66,0xC6, /* ..Ns.$0..f. */ 153 | 0x35,0xAB,0xA2,0x3D,0x2F,0xB3,0xBD,0x34,0x87,0x13,0xEE, /* 5..=/..4... */ 154 | 0x71,0x45,0x68,0xFA,0xEA,0x05,0x84,0x41,0x36,0x4C,0x9A, /* qEh....A6L. */ 155 | 0xFF,0xF2,0x40,0xC0,0xC9,0x92,0x56,0x13,0xD0,0x6E,0x70, /* ..@...V..np */ 156 | 0x54,0xD3,0xCC,0x28,0x06,0xD7,0x0E,0xA4,0x1D,0x9C,0x9D, /* T..(....... */ 157 | 0xD9,0xA9,0x88,0x7B,0xB5,0xA3,0x56,0xB7,0x4B,0x4B,0x5A, /* ...{..V.KKZ */ 158 | 0x9B,0x2C,0xA9,0xAD,0x6F,0x99,0x6C,0xC0,0x4C,0x14,0x14, /* .,..o.l.L.. */ 159 | 0xEF,0xB4,0x20,0x91,0x5F,0xBC,0x81,0x41,0x41,0x5D,0xD4, /* .. ._..AA]. */ 160 | 0x20,0xBD,0x05,0x1A,0x6F,0xE2,0x68,0x56,0x41,0x41,0x57, /* ...o.hVAAW */ 161 | 0xF9,0xBF,0x89,0x82,0x8E,0xC7,0x8F,0x0A,0x0A,0x09,0x37, /* ..........7 */ 162 | 0xF1,0x05,0x0A,0x0A,0x0A,0x0A,0x09,0x05,0x37,0xFF,0x10, /* ........7.. */ 163 | 0x50,0x50,0x53,0x65,0xFF,0xFF,0xFD,0x75,0xDF,0xFF,0xFF, /* PPSe...u... */ 164 | 0x68,0x4F,0xFF,0x84,0x70,0xFF,0xF2,0x42,0xC0,0x27,0x50, /* hO..p..B.'P */ 165 | 0x5F,0x17,0xE8,0x82,0x3C,0x11,0x58,0x18,0x01,0x55,0x48, /* _...<.X..UH */ 166 | 0xBC,0x52,0xFC,0x4A,0x4C,0x3C,0xD5,0xF6,0x11,0x2D,0xBF, /* .R.JL<...-. */ 167 | 0xEA,0x03,0x5C,0x57,0x29,0xBF,0xC3,0x75,0x1C,0xE6,0xDD, /* ..\W)..u... */ 168 | 0xBF,0xED,0xEF,0xD0,0x98,0x77,0x71,0x95,0x73,0xFF,0xED, /* .....wq.s.. */ 169 | 0x54,0xBE,0xD5,0xEE,0xAE,0xC2,0xD5,0x0B,0xFF,0xF1,0x97, /* T.......... */ 170 | 0x8A,0xE4,0x42,0x09,0x99,0xB1,0xEA,0x94,0xDC,0x78,0xB5, /* ..B......x. */ 171 | 0x34,0x0F,0xF1,0x8F,0xFC,0x15,0xF6,0xFA,0xB1,0x47,0xA9, /* 4........G. */ 172 | 0x6C,0x67,0x43,0x8B,0xF2,0x76,0x22,0xED,0xDA,0x85,0xBA, /* lgC..v".... */ 173 | 0x2F,0xC7,0xF9,0xCF,0xFC,0xDB,0x46,0x2E,0x50,0x0A,0x84, /* /.....F.P.. */ 174 | 0xFF,0xF2,0x40,0xC0,0xC6,0x4A,0x59,0x28,0x2B,0x19,0xE0, /* ..@..JY(+.. */ 175 | 0x01,0x89,0x78,0x00,0x52,0x85,0x3C,0x8E,0x54,0x9A,0x48, /* ..x.R.<.T.H */ 176 | 0x5A,0x72,0x32,0x94,0xBF,0x43,0x4F,0x24,0x53,0x4B,0xEC, /* Zr2..CO$SK. */ 177 | 0x4B,0x99,0x0E,0x66,0x1F,0xFF,0xCE,0x7F,0xFF,0x3F,0x10, /* K..f.....?. */ 178 | 0xAE,0x82,0x62,0x71,0x34,0x18,0x59,0x9B,0x51,0xC7,0x59, /* ..bq4.Y.Q.Y */ 179 | 0xCE,0xEE,0xA5,0xFE,0x02,0xBB,0x30,0x91,0x49,0xD5,0x4B, /* ......0.I.K */ 180 | 0xF3,0xDC,0x9A,0xA9,0x57,0x8E,0x72,0x10,0xC0,0x5D,0x60, /* ....W.r..]` */ 181 | 0x67,0xFC,0x7D,0xD6,0xBA,0xDD,0xB3,0x8B,0x5A,0x0A,0x4C, /* g.}.....Z.L */ 182 | 0x41,0x4D,0x45,0x33,0x2E,0x39,0x33,0xAA,0xAA,0xAA,0xAA, /* AME3.93.... */ 183 | 0xAA,0xAA,0xAA,0xAA,0xAA,0x54,0x41,0x47,0x48,0x65,0x6C, /* .....TAGHel */ 184 | 0x6C,0x6F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* lo */ 185 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* */ 186 | 0x20,0x20,0x20,0x20,0x20,0x50,0x61,0x6E,0x75,0x2D,0x4B, /* Panu-K */ 187 | 0x72,0x69,0x73,0x74,0x69,0x61,0x6E,0x20,0x50,0x6F,0x69, /* ristian Poi */ 188 | 0x6B,0x73,0x61,0x6C,0x6F,0x20,0x20,0x20,0x20,0x20,0x20, /* ksalo */ 189 | 0x20,0x20,0x56,0x53,0x44,0x53,0x50,0x20,0x54,0x65,0x73, /* VSDSP Tes */ 190 | 0x74,0x69,0x6E,0x67,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* ting */ 191 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* */ 192 | 0x20,0x20,0x20,0x4D,0x50,0x33,0x20,0x48,0x65,0x6C,0x6C, /* MP3 Hell */ 193 | 0x6F,0x2C,0x20,0x57,0x6F,0x72,0x6C,0x64,0x21,0x20,0x20, /* o, World! */ 194 | 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* */ 195 | 0x00, /* . */ 196 | }; 197 | 198 | void setup () { 199 | // initiate SPI 200 | SPI.begin(); 201 | // initiate a serial port at 57600 202 | Serial.begin(57600); 203 | // internal routines 204 | printf_begin(); 205 | printf_P(PSTR(__FILE__ "\r\n")); 206 | // initiate a player 207 | player.begin(); 208 | player.modeSwitch(); //Change mode from MIDI to MP3 decoding (Vassilis Serasidis). 209 | // set maximum output volume 210 | player.setVolume(0x00); 211 | } 212 | 213 | void loop() { 214 | // play hellomp3 flow each 0.5s ;) 215 | player.playChunk(HelloMP3, sizeof(HelloMP3)); 216 | delay(500); 217 | } 218 | 219 | -------------------------------------------------------------------------------- /Arduino_WebRadio_player.ino: -------------------------------------------------------------------------------- 1 | /* 2 | -----===== Arduino Web radio player ====---- 3 | 4 | (c)05 October 2014 by Vassilis Serasidis 5 | 6 | Home: http://www.serasidis.gr 7 | email: avrsite@yahoo.gr 8 | Version: v1.0 9 | 10 | Hardware: 11 | - Any Arduino (I prefer Arduino pro mini or nano because of its small size and price). 12 | - ENC28J60 ethernet module (EtherCard library is used - Written by Jean-Claude Wippler) 13 | - VS1053B MP3 module/shield (VS1053B library is used - Written by J. Coliz) 14 | - Nokia 5110 LCD module (PCD8544_mod library is used - Written by Carlos Rodrigues - Modified by Vassilis Serasidis ) 15 | 16 | Additional libraries: 17 | - TimerOne (Software watchdog timer - Originaly written by Jesse Tane, last modification Oct 2011 by Andrew Richards). 18 | 19 | Description: 20 | - This web radio player has 14 pre-defined web radio stations (station1, station2,...,station13, station14). 21 | You can add your favorite webradio stations. There is much free available flash memory. 22 | 23 | - For more web radio stations visit http://www.internet-radio.com/ 24 | Visit the http://www.internet-radio.com/ , choose the stations with up to 64-kbps and copy the IP and the Port of the web radio. 25 | For example, right-click on your favorite 64-kbps webradio icon and select http://servers.internet-radio.com/tools/playlistgenerator/?u=http://108.163.215.90:8006/listen.pls&t=.pls 27 | Replace the current station "station1_IP[] = {205,164,36,153}" with the new station "station1_IP[] = {108,163,215,90}". 28 | Do the same to the port. Replace the "station1_Port = 80" with the new one "station1_Port = 8006". 29 | 30 | You can replace the whole 14 stations with the stations of your choice. 31 | 32 | ** This circuit doesn't use a big RAM buffer. That causes a small lag (de-synchronize) due to delay transmission of data packets from the webradio server to your webradio player. 33 | 34 | ** I will try to improve the source code for supporting 128-kbps web radio stations. 35 | 36 | 37 | ***** This source code and hardware are provided as is without any warranty under GNU GPL v3 licence ***** 38 | 39 | Have a good listening! 40 | */ 41 | 42 | #include 43 | #include 44 | #include 45 | #include "PCD8544_mod.h" 46 | #include 47 | 48 | #define BUFFER_LENGTH 600 //Ethernet data bufer length. 49 | #define BUFFER_LENGTH2 32 //VS1053 data buffer length 50 | #define SW_NEXT A1 //Switch for selecting the next webradio station (Arduino pin A1) 51 | #define SW_PREV A2 //Switch for selecting the previous webradio station (Arduino pin A2) 52 | #define LED1 A3 53 | #define LAST_STATION_NUMBER 14 //The last webradio station (14th) 54 | 55 | boolean ViewStationInfo = false; 56 | byte Ethernet::buffer[BUFFER_LENGTH]; 57 | byte MP3_buffer[BUFFER_LENGTH2]; 58 | int indexCounter = 0; 59 | static uint32_t timer; 60 | 61 | char radioStationNumber = 1; //Initial webradio station 62 | boolean radioStationIsChanged = false; 63 | boolean receivedData = true; 64 | 65 | static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; 66 | static byte myip[] = { 192,168,1,200 }; //manualy sets the IP, Gateway IP and DNS in case DHCP fails. 67 | static byte gwip[] = { 192,168,1,1 }; 68 | static byte dnsip[] = { 255,255,255,0 }; 69 | 70 | VS1053 player(9, 6, 7, 8); // cs_pin, dcs_pin, dreq_pin, reset_pin 71 | PCD8544 lcd(3, 4, 5, 2, A0); // clk_pin, data_in_pin, data_select_pin, reset_pin, enable_pin 72 | 73 | //--------------- 14 Web radio stations 64-kbps ---------------------------------------------------------------- 74 | static byte station1_IP[] = {205,164,36,153}; //BOM PSYTRANCE (1.FM TM) 64-kbps 75 | const int station1_Port = 80; 76 | 77 | static byte station2_IP[] = {205,164,62,15}; //1.FM - GAIA, 64-kbps 78 | const int station2_Port = 10032; 79 | 80 | static byte station3_IP[] = {109, 206, 96, 11}; //TOP FM Beograd 106,8 64-kpbs 81 | const int station3_Port = 80; 82 | 83 | static byte station4_IP[] = {85,17,121,216}; //RADIO LEHOVO 971 GREECE, 64-kbps 84 | const int station4_Port = 8468; 85 | 86 | static byte station5_IP[] = {85,17,121,103}; //STAR FM 88.8 Corfu Greece, 64-kbps 87 | const int station5_Port = 8800; 88 | 89 | static byte station6_IP[] = {85,17,122,39}; //www.stylfm.gr laiko, 64-kbps 90 | const int station6_Port = 8530; 91 | 92 | static byte station7_IP[] = {144,76,204,149}; // RADIO KARDOYLA - 64-kbps 22050 Hz 93 | const int station7_Port = 9940; 94 | 95 | static byte station8_IP[] = {198,50,101,130}; //La Hit Radio, Rock - Metal - Hard Rock, 32-kbps 96 | const int station8_Port = 8245; 97 | 98 | static byte station9_IP[] = {94,23,66,155}; // *ILR CHILL & GROOVE* 64-kbps 99 | const int station9_Port = 8106; 100 | 101 | static byte station10_IP[] = {205,164,62,22}; //1.FM - ABSOLUTE TRANCE (EURO) RADIO 64-kbps 102 | const int station10_Port = 7012; 103 | 104 | static byte station11_IP[] = {205,164,62,13}; //1.FM - Sax4Ever 64-kbps 105 | const int station11_Port = 10144; 106 | 107 | static byte station12_IP[] = {83,170,104,91}; //Paradise Radio 106 64-kbps 108 | const int station12_Port = 31265; 109 | 110 | static byte station13_IP[] = {205,164,62,13}; //Costa Del Mar - Chillout (1.FM), 64-kbps 111 | const int station13_Port = 10152; 112 | 113 | static byte station14_IP[] = {46,28,48,140}; //AutoDJ, latin, cumbia, salsa, merengue, regueton, pasillos , 48-kbps 114 | const int station14_Port = 9998; 115 | 116 | 117 | 118 | //===================================================================================================== 119 | // called when the client request is complete 120 | //===================================================================================================== 121 | static void my_callback (byte status, word off, word len) 122 | { 123 | unsigned int i; 124 | 125 | if((indexCounter < 500) && (ViewStationInfo == false)) 126 | { 127 | for(i=0;i 179) && (indexCounter + i < 301)) 131 | lcd.write(Ethernet::buffer[off+i]); 132 | 133 | if(Ethernet::buffer[off+i] == 0x0d && 134 | Ethernet::buffer[off+i+1] == 0x0a && 135 | Ethernet::buffer[off+i+2] == 0x0d && 136 | Ethernet::buffer[off+i+3] == 0x0a) 137 | { 138 | ViewStationInfo = true; 139 | break; //We found the index end (0x0d,0x0a,0x0d,0x0a). Do not search anymore. 140 | } 141 | } 142 | indexCounter += len; 143 | } 144 | else 145 | { 146 | uint8_t* data = (uint8_t *) Ethernet::buffer + off; //Get the data stream from ENC28J60 and... 147 | player.playChunk(data, len); //...send them to VS1053B 148 | timer = millis(); //Update the timeout timer. 149 | receivedData = true; 150 | } 151 | } 152 | 153 | //===================================================================================================== 154 | // 155 | //===================================================================================================== 156 | void setup() 157 | { 158 | pinMode(SW_NEXT, INPUT); //Make SW_NEXT pin as input 159 | pinMode(SW_PREV , INPUT); //Make SW_PREV pin as input 160 | digitalWrite(SW_NEXT, HIGH); //Enable internal pull-up on SW_NEXT pin 161 | digitalWrite(SW_PREV , HIGH); //Enable internal pull-up on SW_PREV pin 162 | 163 | pinMode(LED1, OUTPUT); //LED1 is connected to A3 pin 164 | 165 | Serial.begin(57600); //Start serial port with 57600 bits per seconds 166 | SPI.begin(); //Start Serial Peripheral Interface (SPI) 167 | player.begin(); //Start VS1053B 168 | player.modeSwitch(); //Change mode from MIDI to MP3 decoding (Vassilis Serasidis). 169 | player.setVolume(0); //Set the volume to the maximux. 170 | 171 | lcd.begin(84, 48); //84*48 pixels lcd (Nokia 5110). 172 | lcd.clear(); 173 | lcd.setCursor(0, 0); 174 | lcd.print(F("-= WEBRADIO PLAYER =-")); 175 | lcd.setCursor(0, 1); 176 | lcd.print(F("fw: 1.0")); 177 | lcd.setCursor(0, 2); 178 | lcd.print(F("(C) 2014 BY")); 179 | lcd.setCursor(0, 3); 180 | lcd.print(F("VASSILIS SERASIDIS")); 181 | lcd.setCursor(0, 5); 182 | lcd.print(F("WWW.SERASIDIS.GR")); 183 | delay(5000); 184 | 185 | 186 | Serial.println(F("\n--== Arduino WebRadio player ==--\n")); 187 | Serial.println(F("(c)2014 by Vassilis Serasidis")); 188 | Serial.println(F("http://www.serasidis.gr\n")); 189 | Serial.println(F("\nConnecting...")); 190 | 191 | if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0) //Initiallize ENC28J60. Chip Select pin (CS) is connected on arduino pin D10. 192 | Serial.println(F("Failed to access Ethernet controller")); 193 | if (!ether.dhcpSetup()) 194 | Serial.println(F("DHCP failed")); 195 | 196 | ether.persistTcpConnection(true); //Keep TCP/IP connection alive. 197 | ViewStationInfo = true; 198 | 199 | Timer1.initialize(5000000); // set a timer of length 5000000 microseconds (or 5 sec => the led will blink 5 times, 5 cycles of on-and-off, per second) 200 | Timer1.attachInterrupt( timerIsr ); // attach the service routine here 201 | } 202 | 203 | //===================================================================================================== 204 | // 205 | //===================================================================================================== 206 | void loop() 207 | { 208 | ether.packetLoop(ether.packetReceive()); //Read ENC28J60 for new incoming data packet. 209 | 210 | if(digitalRead(SW_NEXT) == LOW) //Check if the 'next' switch has been pressed. 211 | { 212 | if(radioStationNumber < LAST_STATION_NUMBER) 213 | { 214 | while(digitalRead(SW_NEXT) == LOW) 215 | delay(100); 216 | radioStationNumber += 1; 217 | radioStationIsChanged = true; 218 | } 219 | } 220 | 221 | if(digitalRead(SW_PREV)== LOW) //Check if the 'previous' switch has been pressed. 222 | { 223 | while(digitalRead(SW_PREV) == LOW) 224 | delay(100); 225 | if(radioStationNumber > 1) 226 | { 227 | radioStationNumber -= 1; 228 | radioStationIsChanged = true; 229 | } 230 | } 231 | 232 | if(radioStationIsChanged == true)//If 'next' or 'previous' switch has been pressed, play the selected webradio station. 233 | { 234 | switch (radioStationNumber) 235 | { 236 | case 1: 237 | playWebRadioStation(station1_IP, station1_Port, "01"); 238 | break; 239 | case 2: 240 | playWebRadioStation(station2_IP , station2_Port, "02"); 241 | break; 242 | case 3: 243 | playWebRadioStation(station3_IP , station3_Port, "03"); 244 | break; 245 | case 4: 246 | playWebRadioStation(station4_IP , station4_Port, "04"); 247 | break; 248 | case 5: 249 | playWebRadioStation(station5_IP , station5_Port, "05"); 250 | break; 251 | case 6: 252 | playWebRadioStation(station6_IP , station6_Port, "06"); 253 | break; 254 | case 7: 255 | playWebRadioStation(station7_IP , station7_Port, "07"); 256 | break; 257 | case 8: 258 | playWebRadioStation(station8_IP , station8_Port, "08"); 259 | break; 260 | case 9: 261 | playWebRadioStation(station9_IP , station9_Port, "09"); 262 | break; 263 | case 10: 264 | playWebRadioStation(station10_IP , station10_Port, "10"); 265 | break; 266 | case 11: 267 | playWebRadioStation(station11_IP , station11_Port, "11"); 268 | break; 269 | case 12: 270 | playWebRadioStation(station12_IP , station12_Port, "12"); 271 | break; 272 | case 13: 273 | playWebRadioStation(station13_IP , station13_Port, "13"); 274 | break; 275 | case 14: 276 | playWebRadioStation(station14_IP , station14_Port, "14"); 277 | break; 278 | } 279 | } 280 | 281 | radioStationIsChanged = false; 282 | 283 | if((millis() > timer + 5000)) // Timeout timer. If the song stops playing for 5 seconds re-connect to the server. 284 | { 285 | radioStationIsChanged = true; 286 | ViewStationInfo = false; 287 | Serial.print(F("\nre-connecting to the server...\n")); 288 | lcd.clear(); 289 | lcd.setCursor(8,3); 290 | lcd.print(F("re-connecting to")); 291 | lcd.setCursor(12,4); 292 | lcd.print(F("the server")); 293 | timer = millis(); 294 | } 295 | } 296 | 297 | //===================================================================================================== 298 | // 299 | //===================================================================================================== 300 | void playWebRadioStation ( byte ip[4], const int hisPort, char* preset ) 301 | { 302 | Serial.print("\n\n<"); //Print the station info to the serial port 303 | Serial.print(preset); 304 | Serial.println(F("> ============================================================")); 305 | 306 | player.stopSong(); 307 | ViewStationInfo = false; 308 | indexCounter = 0; 309 | ether.copyIp(ether.hisip, ip); 310 | ether.hisport = hisPort; 311 | ether.printIp("IP: ", ether.myip); 312 | ether.printIp("GW: ", ether.gwip); 313 | ether.printIp("DNS: ", ether.dnsip); 314 | ether.printIp("SRV: ", ether.hisip); 315 | Serial.print("Port: "); 316 | Serial.println(ether.hisport); 317 | Serial.println(); 318 | //ether.browseUrl(PSTR("/"), "",PSTR(""), PSTR("Icy-MetaData:1"), my_callback); 319 | ether.browseUrl(PSTR("/"), "",PSTR(""), PSTR(""), my_callback); 320 | lcd.clear(); 321 | lcd.setCursor(0, 0); //LCD line 0 322 | lcd.write('<'); 323 | lcd.print(preset); //Show on LCD the webradio number (1-14) 324 | lcd.write('>'); 325 | lcd.write(' '); 326 | } 327 | 328 | //===================================================================================================== 329 | // Custom ISR Timer Routine 330 | //===================================================================================================== 331 | void timerIsr() 332 | { 333 | // Toggle LED 334 | digitalWrite( LED1, digitalRead( LED1 ) ^ 1 ); 335 | if(receivedData == true) 336 | receivedData = false; 337 | else 338 | { 339 | radioStationIsChanged = true; 340 | if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0) //Initiallize ENC28J60. Chip Select pin (CS) is connected on arduino pin D10. 341 | Serial.println(F("Failed to access Ethernet controller")); 342 | if (!ether.dhcpSetup()) 343 | Serial.println(F("DHCP failed")); 344 | ether.persistTcpConnection(true); //Keep TCP/IP connection alive. 345 | } 346 | } 347 | --------------------------------------------------------------------------------