This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

memory.c

Committer:
Clemo
Date:
2014-10-28
Revision:
1:8ae4ab73ca6a
Parent:
0:cb80470434eb

File content as of revision 1:8ae4ab73ca6a:

/*
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);
}