This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

Revision:
0:cb80470434eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memory.c	Tue Oct 28 12:19:42 2014 +0000
@@ -0,0 +1,318 @@
+/*
+Copyright 2013 Paul Soulsby www.soulsbysynths.com
+    This file is part of Atmegatron.
+
+    Atmegatron is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Atmegatron is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Atmegatron.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+//******Read and write patches to flash memory**************
+
+#include "atmegatron.h"
+
+
+//save patch
+void Memory_Save(byte patchnum)
+{
+  byte i; //, v,
+  byte lsb, msb;
+  byte anal, out;
+  uint32_t addr;
+  byte bit_position;
+  //boolean b;
+  
+  cli();                                    //halt interrupts (i.e. audio engine).  don't want it interfering with eeprom writing
+  
+  addr = (uint32_t)patchnum * MEM_PATCHSIZE;          //find start address  (normal patch size = 19 bytes)
+  /*v = 0;
+  
+  for (i=0;i<8;i++){                        //writes all 16 function values to memory
+    lsb = Hardware_Get_Value(v);            //each function is value 0-15 = 4 bit value.
+    msb = Hardware_Get_Value(v+1);          //so can store 2 function values in each byte (8 bits)
+    msb = msb << 4;                         //this is done by bit-shifting every other value left 4 bits
+    out = msb | lsb;                        //and ORing with other value
+    EEPROM.write(addr+i, out);              //then write to eeprom
+    v += 2;
+  }*/
+
+  // Write all 16 function values to memory
+  for (i=0; i<8; i++)
+  {
+    lsb = Hardware_Get_Value(2*i);            //each function is value 0-15 = 4 bit value.
+    msb = Hardware_Get_Value(2*i+1);          //so can store 2 function values in each byte (8 bits)
+    EEPROM.write(addr,((msb<<4)&0xf0)|(lsb&0x0f));  //then write to eeprom
+    addr += 1;
+  }
+
+  //write all ctrl values to memory
+  anal = Hardware_Get_Ctrl(0, CTRL_FILT);   //first the 6 red bank ctrls
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(0, CTRL_Q);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(0, CTRL_ENV);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(0, CTRL_LFO);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(0, CTRL_AMP);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(0, CTRL_FX);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(1, CTRL_ENV);    //then the 4 green bank ctrls
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(1, CTRL_LFO);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(1, CTRL_AMP);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  anal = Hardware_Get_Ctrl(1, CTRL_FX);
+  EEPROM.write(addr, anal);
+  addr += 1;
+  
+                                            //write function shift modes to memory.   
+  out = 0;                                  //these are boolean, so 1 bit each.  so 8 can be store in each byte (i.e. 8 bits).  out is used to build up output byte
+  bit_position = 0x01;
+  if (Hard_Get_Shift(FUNC_WAVE)==true){     //get each shift mode and set/clear each bit of out.   First wavetable bank
+    //bitSet(out, 0);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 0);
+  //}
+  bit_position <<= 1;
+  if (Hard_Get_Shift(FUNC_FILT)==true){    //filter normalise mode
+    //bitSet(out, 1);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 1);
+  //}
+  bit_position <<= 1;
+  if (Hard_Get_Shift(FUNC_FENVA)==true){   //filt/pitch env invert mode
+    //bitSet(out, 2);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 2);
+  //}
+  bit_position <<= 1;
+  if (Hard_Get_Shift(FUNC_LFOTYPE)==true){  //lfo invert mode
+    //bitSet(out, 3);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 3);
+  //}
+#ifdef __HAS_ARPEGGIATOR__
+  bit_position <<= 1;
+  if (Hard_Get_Shift(FUNC_ARPTYPE)==true){  //arp ping-pong mode
+    //bitSet(out, 4);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 4);
+  //}
+#endif // __HAS_ARPEGGIATOR__
+  bit_position <<= 1;
+  if (Hard_Get_Shift(FUNC_PORTA)==true){    //proportional portamento
+    //bitSet(out, 5);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 5);
+  //}
+  bit_position <<= 1;
+  if (Hard_Get_Shift(FUNC_BITCRUSH)==true){  //bitcrush before filter mode
+    //bitSet(out, 6);
+    out |= bit_position;
+  }
+  //else{
+  //  bitClear(out, 6);
+  //}
+  EEPROM.write(addr, out);                //write compiled bits to eeprom
+  addr += 1;
+  sei();                                     //restart interrupts (audio engine)
+  
+}
+
+
+bool Memory_Load_Patch(uint8_t *p_dst, uint32_t src)
+{
+	int i;
+	bool patch_not_empty = false;
+	for (i=0; i<MEM_PATCHSIZE; i++)
+	{
+		// We use special EEPROM library that doesn't care about interrupts.
+		p_dst[i] = EEPROM.read(src+i);
+		if (p_dst[i]!=0 && p_dst[i]!=0xff)
+		{
+			patch_not_empty = true;
+		}
+	}
+	return patch_not_empty;
+}
+
+
+//load patch
+bool Memory_Load(byte patchnum)
+{
+  int i;
+  byte in;
+  uint8_t eeprom_buffer[MEM_PATCHSIZE];
+  
+  if (Memory_Load_Patch(eeprom_buffer,patchnum*MEM_PATCHSIZE)==false) return false;
+
+   //set function values
+  for (i=0; i<8; i++)
+  {
+    in = eeprom_buffer[i];
+    // Two function values in each byte. First one can be obtained by blanking top 4 bits.
+    Hardware_Let_Value(2*i,in&0x0f);
+    Hardware_Let_Value(2*i+1,(in>>4)&0x0f);
+  }
+
+  Hardware_Let_Ctrl(0, CTRL_FILT, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(0, CTRL_Q, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(0, CTRL_ENV, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(0, CTRL_LFO, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(0, CTRL_AMP, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(0, CTRL_FX, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(1, CTRL_ENV, eeprom_buffer[i++]);      //the the 4 green bank ctrls
+  Hardware_Let_Ctrl(1, CTRL_LFO, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(1, CTRL_AMP, eeprom_buffer[i++]);
+  Hardware_Let_Ctrl(1, CTRL_FX, eeprom_buffer[i++]);
+
+  in = eeprom_buffer[i++];                 //read entire byte
+  Hard_Let_Shift(FUNC_WAVE,(in&0x01)!=0);          //and set wavetable bank accordingly
+  Hard_Let_Shift(FUNC_FILT,(in&0x02)!=0);
+  Hard_Let_Shift(FUNC_FENVA,(in&0x04)!=0);         //filter/pitch env invert mode
+  Hard_Let_Shift(FUNC_LFOTYPE,(in&0x08)!=0);       //lfo invert mode
+#ifdef __HAS_ARPEGGIATOR__
+  Hard_Let_Shift(FUNC_ARPTYPE,(in&0x10)!=0);        //arpeggiator pingpong
+#endif // __HAS_ARPEGGIATOR__
+  Hard_Let_Shift(FUNC_PORTA,(in&0x20)!=0);          //proportional portamento
+  Hard_Let_Shift(FUNC_BITCRUSH,(in&0x40)!=0);       //filter before bit crusher
+
+  return true;
+}
+
+
+//***** User wave ******
+//save user wave
+void Memory_UserWave_Write(byte patchnum)
+{
+  int i, addr;
+  cli();                                                   //stop interrupts (audio engine)
+  addr = ((int)patchnum * WAVE_LEN) + (MEM_PATCHSIZE*16);  //calc start address. 288 bytes is the offset from 16 mem patches
+  for (i=0;i<WAVE_LEN;i++){
+    EEPROM.write(addr + i, Wave_Get_UserWave(i));          //write each sample to memory
+  }  
+  sei();                                                   //restart interrupts (audio engine)
+}
+
+
+//load user wave
+void Memory_UserWave_Read(byte patchnum)
+{
+  int i, addr;
+  cli();                                                   //stop interrupts (audio engine)
+  addr = ((int)patchnum * WAVE_LEN) + (MEM_PATCHSIZE*16);  //calc start address. 288 bytes is the offset from 16 mem patches
+  for (i=0;i<WAVE_LEN;i++){
+    Wave_Let_UserWave(i,EEPROM.read(addr + i));            //read each sample value from memory
+  }
+  sei();                                                   //restart interrupts (audio engine)
+}
+
+
+//initialise atmegatron with vanilla patch
+void Memory_Vanilla(void)
+{
+  Hardware_Let_Value(FUNC_WAVE, 0);        //square wave
+  Hardware_Let_Value(FUNC_FILT, 1);        //lpf
+  Hardware_Let_Value(FUNC_FENVA, 0);       //'donk' shape filter env
+  Hardware_Let_Value(FUNC_FENVDR, 6);    
+  Hardware_Let_Value(FUNC_FENVS, 0);
+  Hardware_Let_Value(FUNC_AENVA, 0);       //full sustain amp env with short decay if sustain lowered
+  Hardware_Let_Value(FUNC_AENVD, 6);
+  Hardware_Let_Value(FUNC_AENVS, 15);
+  Hardware_Let_Value(FUNC_AENVR, 0);
+  Hardware_Let_Value(FUNC_LFOTYPE, 0);     //sine LFO
+  Hardware_Let_Value(FUNC_LFOSPEED, 8);    //semi-quavers
+#ifdef __HAS_ARPEGGIATOR__
+  Hardware_Let_Value(FUNC_ARPTYPE, 0);     //arp off
+  Hardware_Let_Value(FUNC_ARPSPEED, 5);    //quavers
+#endif // __HAS_ARPEGGIATOR__
+  Hardware_Let_Value(FUNC_PORTA, 0);       //porta off   
+  Hardware_Let_Value(FUNC_BITCRUSH, 0);    //bitcrush off  
+  Hardware_Let_Ctrl(0,CTRL_FILT,255);      //filter full open
+  Hardware_Let_Ctrl(0,CTRL_Q,0);           //resonance at min (0.5)
+  Hardware_Let_Ctrl(0,CTRL_ENV,0);         //All Envs and LFO amts = 0
+  Hardware_Let_Ctrl(1,CTRL_ENV,0);  
+  Hardware_Let_Ctrl(0,CTRL_LFO,0);
+  Hardware_Let_Ctrl(1,CTRL_LFO,0);
+  Hardware_Let_Ctrl(0,CTRL_AMP,0);
+  Hardware_Let_Ctrl(1,CTRL_AMP,0);
+  Hardware_Let_Ctrl(0,CTRL_FX,0);          //no distortion 
+  Hardware_Let_Ctrl(1,CTRL_FX,0);          //no phaser
+  Hard_Let_Shift(FUNC_WAVE, false);        //all shift modes off   
+  Hard_Let_Shift(FUNC_FILT, false); 
+  Hard_Let_Shift(FUNC_FENVA, false);
+  Hard_Let_Shift(FUNC_LFOTYPE, false);
+#ifdef __HAS_ARPEGGIATOR__
+  Hard_Let_Shift(FUNC_ARPTYPE, false);
+#endif // __HAS_ARPEGGIATOR__
+  Hard_Let_Shift(FUNC_PORTA, false);
+  Hard_Let_Shift(FUNC_BITCRUSH, false);
+}
+
+
+//read patch from memory and output as sysex
+void Memory_SYSEX_write_mem(void)
+{
+  byte data;
+  int i;
+  
+  Serial.write(SYSEXBEGIN);
+  Serial.write(125);    //  1  manufacturer ID
+  Serial.write(0);      //  2  product ID
+  Serial.write(SYSEX_MEM);      //  3  message type
+  for (i=0;i<496;i++){  //496 bytes of the mem used
+    cli();
+    data = EEPROM.read(i);
+    sei();
+    Serial.write(data >> 1);  //MSB
+    Serial.write(data & 0x01);  //LSB
+    Serial.flush();
+  }
+  Serial.write(SYSEXEND);              
+  
+}
+
+
+void Memory_Channel_Write(byte channel)
+{
+  EEPROM.write(511, channel);
+}
+
+
+byte Memory_Channel_Read(void)
+{
+  return EEPROM.read(511);
+}