/*********************************************************
HTL Eisenstadt     VFS5.c  V 1.0        2012-06-02 
**********************************************************   
History of versions: 
V 1.0  2012-06-02  S. Flamisch   First test file o.k.!
V 1.1   
V 1.2  
--------------------------------------------------------- 
Chip type: ATmega8      Extern crystal clock: 16 MHz !!!
Hardware: myMicro - board
Fuse bits CKSEL1,2,3 must be unprogrammed(1) f.ext.clock
Warning! Do not alter the other fuse bits !!!
High fuse: 0xD9  Low Fuse: 0xFF !
Made and compiled with CVAVR 2.04
--------------------------------------------------------- 
Simulates Vox Footswitch VFS5 for Valvetronix Amps.
Analog Voltages for channel and bank switching are 
made here by an 10bit-DAC, conttrolled by an ATMega8
I2C-Bus.
2 Banks: green and red, each 4 Channels 1...4
*********************************************************/
// Precompiler statements and include files:
#include <mega8.h> 	// include file w. SFR names
#include <delay.h>      // incl. delay-library of CVAVR

// Input-Pins at hardware myMicro (all ACTIVE LOW!) :
#define kRes     PINB.0 // 
#define kChan    PINB.1 // switches chann. 1-2-3-4-1-2...
#define kBank    PINB.2 // switch Bank red=low

#define BaGrn    PORTD.2 // 1=Bank green LEDs Andode on
#define BaRed    PORTD.3 // 1=Bank red LEDs Andode on
#define Ch4      PORTD.4 // 0=channel LED 4 on
#define Ch3      PORTD.5 // 0=channel LED 3 on
#define Ch2      PORTD.6 // 0=channel LED 2 on
#define Ch1      PORTD.7 // 0=channel LED 1 on
#define RED      0       // Flag for Bank
#define GREEN    1       // Flag for Bank
#define SC PORTC.5 // I2C Serial Clock
#define SD PORTC.4 // I2C Serial Data
#define CS PORTC.3 // I2C  /Chip Select act. low

// Declare your global variables here: ------------------ 
bit kChanOld = 1; // for edge detecting

// 10 bit DAC-values [0]=Idle Value, Ch1 ...Ch4 
unsigned int ZGrnCh[]= {699,570,476,325,201}; 
unsigned int ZRedCh[]= {794,632,518,344,208};
unsigned char Chan = 1;   // start with channel 1
unsigned char Counter=20; // Count main while cycles
// Predeclare your function prototypes here:
// -----------------------------------------
void InitSFRs(); // initialization of Hardware (SFRs)
void CheckKeys();   // look for changed buttons
void Write();       // Write Out to LEDs and DAC
void WriteDAC(unsigned int); // Write by I2C to DAC
void WriteI2C(unsigned char); // Write one bit to I2C
// ********************************************************
void main(void)
// ********************************************************
{
// Declare your local variables here

InitSFRs();       // initialize the hardware
//switch I2C-Port inactive:
CS=1;
SC=0;
SD=0;

// --- Test all LEDS: ----------------------
   BaGrn=1; //Voltage Anode LEDs Green on
   Ch1=0;   // Ch1 on (active low!)
   delay_ms(200);
   Ch1=1;
   Ch2=0;
   delay_ms(200);
   Ch2=1;
   Ch3=0;
   delay_ms(200);
   Ch3=1;
   Ch4=0;
   delay_ms(200);
   BaGrn=0;
   BaRed=1;  //Voltage Anode LEDs Red on
   Ch4=1;
   Ch1=0;
   delay_ms(200);
   Ch1=1;
   Ch2=0;
   delay_ms(200);
   Ch2=1;
   Ch3=0;
   delay_ms(200);
   Ch3=1;
   Ch4=0;
   delay_ms(200); 
   BaRed=0; //V Anode off
   Ch4=1;
   // Initalize for starting with Ch1 
   Chan=1;
   if (kBank)  // footswitch is sw. to GREEN  
    {WriteDAC(ZGrnCh[Chan]);
     BaGrn=1;
     BaRed=0;
     Ch1=0;
     delay_ms(50);}
   else        // footswitch is sw. to RED
    {WriteDAC(ZRedCh[Chan]); 
     BaGrn=0;
     BaRed=1;
     Ch1=0;          
     delay_ms(50);}
// ---------------------------------------------------------   
while (1)    // do forever
 { 
  delay_ms(5);  // for stable debouncing
  Counter++;
  if (Counter >250)
      {Counter = 20;
      }
  CheckKeys();  // look for changed keys and evaluate
 } // end of while 
}  // end of main ++++++++++++++++++++++++++++++++++++++++++++

// ***********************************************************
void Write()
// ***********************************************************
// write out to LEDs and to DAC:
{ 
  Ch1=1; // switch Channel-LEDS first (active low!)
  Ch2=1;
  Ch3=1;
  Ch4=1;
  if (Chan==1)
      Ch1=0;
  if (Chan==2)
      Ch2=0;
  if (Chan==3)
      Ch3=0;
  if (Chan==4)
      Ch4=0;  
  if (kBank)  // footswitch is sw. to GREEN  
    {WriteDAC(ZGrnCh[Chan]);
     BaGrn=1;
     BaRed=0;
     delay_ms(50);} // give Amp time to check
  else        // footswitch is sw. to RED
    {WriteDAC(ZRedCh[Chan]); 
     BaGrn=0;
     BaRed=1;     
     delay_ms(50);} // give Amp time to check                
} 

// ***********************************************************
void WriteDAC(unsigned int value)
// ***********************************************************
// write out 10 bit value by I2C-Bus to DAC:
{  
unsigned char buf_hi;
unsigned char buf_lo;
unsigned char buf;
SC=0; // inactive
CS=1; // inactive
// prepare high and low byte:
buf_hi= (value>>8);
buf_lo= (value & 0xFF);
// -----------------------------------------
CS=0;  //start transfer with chip select low
#asm ("NOP\NOP\NOP") // wait short
// -----------------------------------------
//  ------- write first 8 bits: ---------------
WriteI2C(0); //send bit 15 (0-> write to DAC A)
WriteI2C(0); //send bit 14 (0) dont care
WriteI2C(0); //send bit 13 (Gain 0->2x2,048V)
WriteI2C(1); //send bit 12 (1-> enable output)

buf=(buf_hi >> 1);
WriteI2C(buf); //send bit 11 (=d9) 
buf=buf_hi;
WriteI2C(buf); //send bit 10 (=d8)

buf=(buf_lo >> 7);
WriteI2C(buf); //send bit 9 (=d7) 
buf=(buf_lo >> 6);
WriteI2C(buf); //send bit 8 (=d6)

//  ------- write second 8 bits: ---------------
buf=(buf_lo >> 5);
WriteI2C(buf); //send bit 7 (=d5)
buf=(buf_lo >> 4);
WriteI2C(buf); //send bit 6 (=d4)
buf=(buf_lo >> 3);
WriteI2C(buf); //send bit 5 (=d3)
buf=(buf_lo >> 2);
WriteI2C(buf); //send bit 4 (=d2)
buf=(buf_lo >> 1);
WriteI2C(buf); //send bit 3 (=d1)
buf=(buf_lo);
WriteI2C(buf); //send bit 2 (=d0)
// last two bits not used by 10bit DAC:
WriteI2C(0); //send bit 1 (0)
WriteI2C(0); //send bit 0 (0)
// -----------------------------------------
#asm ("NOP") // wait short
CS=1;  //stop transfer
}

// ***********************************************************
void WriteI2C(unsigned char datachar)
// ***********************************************************
// write out one bit to I2C
// bit to write must be LSB of datachar!!!
{  
if (datachar & 0x01)  // evaluate LSB and write data bit
    {SD=1;}
else
    {SD=0;}
#asm ("NOP\NOP\NOP") // wait short
SC=1; // clock rising edge, stores data bit
#asm ("NOP\NOP\NOP") // wait short
SC=0; // clock off
#asm ("NOP") // wait short 
}
// ***********************************************************
void CheckKeys()
// ***********************************************************
// check keys for changes:
{ 
 if (!kChan && kChanOld && (Counter>=20)) // check key ...
    { 
      if (Chan < 4)
           Chan++;
      else if (Chan>=4)
           Chan=1;
      // switch LEDS and DAC
      Write();  // 
      //delay_ms(100);      // debouncing 
    }
 
 else  // key Channel is not pressed, send Idle Value to DAC
 { 
  
  if (kBank)  // footswitch is sw. to GREEN  
   { WriteDAC(ZGrnCh[0]);
     BaGrn=1;
     BaRed=0;
     //delay_ms(1);
   }    
  else        // footswitch is sw. to RED
    { WriteDAC(ZRedCh[0]);
      BaGrn=0;
      BaRed=1;
      //delay_ms(1);
    }  
 } 
 kChanOld = kChan;   // save state now 
} 

// **********************************************************
// function "InitSFRs" 
// **********************************************************
// Initialize all the hardware by
// writing to the Special Function Registers
void InitSFRs()
{
// Port B initialization:
// PIN:        PB7  PB6  PB5  PB4  PB3  PB2  PB1  PB0
// STATE:       0    0    0    0    P    P    P    P
// DIRECTION:  Out  Out  Out  Out   In  In   In    In
PORTB=0x0F; //  0    0    0    0    1    1    1    1
DDRB=0xF0;  //  1    1    1    1    0    0    0    0 

// Port C initialization:
// PIN:        PC7  PC6  PC5  PC4  PC3  PC2  PC1  PC0
// STATE:       -    P    1    1    1    0    0    0
// DIRECTION:   -   In   Out  Out  Out  Out  Out  Out 
PORTC=0xE0; //  1    1    1    0    0    0    0    0
DDRC=0x3F;  //  0    0    1    1    1    1    1    1 

// Port D initialization: (LED matrix outputs)
// PIN:        PD7  PD6  PD5  PD4  PD3  PD2  PD1  PD0
// STATE:       1    1    1    1    0    0    0    0 
// DIRECTION:  Out  Out  Out  Out  Out  Out  Out  In
PORTD=0xF0; //  1    1    1    1    0    0    0    0
DDRD=0xFE;  //  1    1    1    1    1    1    1    0 

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 31250 for MIDI, (9600 for RS232)
UBRRH=0x00;
UBRRL=0x1F;   // UART: 31 Dez. for 31,25 Bd. (MIDI)
//UBRRL=0x67; // UART:103 Dez=0x0067 f. 9600Bd.(RS232)
UCSRA=0x00;
UCSRB=0x08;   // 0000 1000 enable Tx 
UCSRC=0x86;   // 1000 0110 

} // ------------------------------------------------------

// End of code