/* Four Sample Player David Johnson-Davies - www.technoblogy.com - 21st January 2020 ATtiny85 @ 8 MHz (internal oscillator; BOD disabled) CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ #include // Winbond DataFlash commands #define PAGEPROG 0x02 #define READSTATUS 0x05 #define READDATA 0x03 #define WRITEENABLE 0x06 #define CHIPERASE 0x60 #define READID 0x90 #define POWERDOWN 0xB9 #define RELEASEPD 0xAB // ATtiny85 pins used for dataflash const int sck = 2, miso = 1, mosi = 0, cs = 3; class DF { public: boolean Setup(); void BeginRead(uint32_t addr); void BeginWrite(void); uint8_t ReadByte(void); void WriteByte(uint8_t data); void EndRead(void); void EndWrite(void); void PowerDown(boolean); private: unsigned long addr; uint8_t Read(void); void Write(uint8_t); void Busy(void); void WriteEnable(void); }; boolean DF::Setup () { uint8_t manID, devID; pinMode(cs, OUTPUT); digitalWrite(cs, HIGH); pinMode(sck, OUTPUT); pinMode(mosi, OUTPUT); pinMode(miso, INPUT); digitalWrite(sck, LOW); digitalWrite(mosi, HIGH); delay(1); digitalWrite(cs, LOW); delay(100); Write(READID); Write(0);Write(0);Write(0); manID = Read(); devID = Read(); digitalWrite(cs, HIGH); return (devID == 0x15); // Found correct device } void DF::Write (uint8_t data) { uint8_t bit = 0x80; while (bit) { if (data & bit) PORTB = PORTB | (1<>1; PINB = 1<>16); Write(addr>>8); Write(addr); } uint8_t DF::Read () { uint8_t data = 0; uint8_t bit = 0x80; while (bit) { PINB = 1<>1; } return data; } void DF::EndRead(void) { digitalWrite(cs, 1); } void DF::BeginWrite () { addr = 0; // Erase DataFlash WriteEnable(); digitalWrite(cs, 0); Write(CHIPERASE); digitalWrite(cs, 1); Busy(); } uint8_t DF::ReadByte () { return Read(); } void DF::WriteByte (uint8_t data) { // New page if ((addr & 0xFF) == 0) { digitalWrite(cs, 1); Busy(); WriteEnable(); digitalWrite(cs, 0); Write(PAGEPROG); Write(addr>>16); Write(addr>>8); Write(0); } Write(data); addr++; } void DF::EndWrite (void) { digitalWrite(cs, 1); Busy(); } DF DataFlash; // Audio player ********************************************** volatile boolean StayAwake; const int speaker = 4; volatile int Play = 0; volatile uint32_t Count; uint32_t Sizes[5] = { 0, 2486, 5380, 10291, 1415837 }; // Sample interrupt ISR (TIMER0_COMPA_vect) { char sample = DataFlash.ReadByte(); OCR1B = sample; // End of data? Go to sleep Count--; if (Count == 0) { DataFlash.EndRead(); TIMSK = 0; // Turn off interrupt StayAwake = false; } } // Pin change interrupt ISR (PCINT0_vect) { int Buttons = PINB; if ((Buttons & 1<