#include <Wire.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
// Define register values, etc to facilitate programming
// Note: Reg address is address plus R/W bit
// This is why the address here is different from the
// address in the data sheet
#define REG0 0 // Register 0 address (Volume Adjustment)
#define REG1 1 // Register 1 address (Volume Adjustment)
#define REG2 2 // Register 2 address (Volume Adjustment)
#define REG3 3 // Register 3 address (Volume Adjustment)
#define REG4 4 // Register 4 address (Volume Adjustment)
#define REG5 5 // Register 5 address (Volume Adjustment)
#define REG6 6 // Register 6 address (Volume Adjustment)
#define REG7 7 // Register 7 address (Volume Adjustment)
// The following to be used in Reg4
#define DEFAULTVOL 0x64 //-50 dB this is 50x2=100
#define MINVOL 0xC6 //-99dB this is 99X2=198. -Dac adjustment is .5 db
#define MAXVOL 0x00 //-0 dB
#define VOLUPPIN 4 // Button to increase volume
#define VOLDOWNPIN 2 // Button to decrease volume
#define IRPIN 3 // The pin for the remote sensor
#define VOLBUTTONPIN 38
#define KEY1 128 // The value when pressing the 1 key in remote
#define KEY2 129 // The value when pressing the 2 key in remote
#define KEY3 130 // The value when pressing the 3 key in remote
#define KEY4 131 // The value when pressing the 4 key in remote
#define KEY5 132 // The value when pressing the 5 key in remote
#define KEY7 134 // The value when pressing the 7 key in remote
#define KEY8 135 // The value when pressing the 8 key in remote
#define KEY9 136 // The value when pressing the 9 key in remote
#define KEYVOLUP 18 // The value when pressing volume up key in remote
#define KEYVOLDOWN 19 // The value when pressing volume down key in remote
#define KEYDISPLAY 186 // The value when pressing display key in remote
#define KEYPICTUREUP 152 // The value when pressing picture + key in remote
#define KEYPICTUREDOWN 153 // The value when pressing picture - key in remote
#define KEY1 1024 // The value when pressing 1 key in remote
#define KEY2 1025 // The value when pressing 2 key in remote
#define KEYYELLOW 462 // The value when pressing yellow text key in remote
#define IRFILSELDELAY 300 // Delay when selecting filter with remote to preven multiple selection
#define ONEPULSE 1000 // Microsecond threshold for value 1 in remote putlse
#define B 0xFF // The character for a completely filled box
#define A 0x20 // The character for blank
// The routine to create the custom characters in the LCD
void DefineLargeChar()
{
// A 1 in the binary representation of the character means it is filled in
// characters are 5 pixels wide by 8 pixels tall
// We need 7 custom characters for the OPUS DAC display.
// (Custom character 0 doesn't work in the Web4Robot LCD)
// Define Custom Characters
byte custchar1[8]= {B11100,B11110,B11111,B11111,B11111,B11111,B11111,B11111};
byte custchar2[8]= {B11111,B11111,B11111,B11111,B11111,B00000,B00000,B00000};
byte custchar3[8]={B00000,B00000,B00000,B11111,B11111,B11111,B11111,B11111};
byte custchar4[8]= {B11111,B11111,B11111,B11111,B11111,B11111,B01111,B00111};
byte custchar5[8]={B11111,B11111,B11111,B11111,B11111,B11111,B00000,B00000};
byte custchar6[8]={B00000,B11111,B11111,B11111,B11111,B11111,B00000,B00000};
byte custchar7[8]= {B00000,B11100,B11110,B11111,B11111,B11111,B11111,B11111};
lcd.createChar(1, custchar1);
lcd.createChar(2, custchar2);
lcd.createChar(3, custchar3);
lcd.createChar(4, custchar4);
lcd.createChar(5, custchar5);
lcd.createChar(6, custchar6);
lcd.createChar(7, custchar7);
}
// Array index into parts of big numbers. Numbers consist of 9 custom characters in 3 lines
// 0 1 2 3 4 5 6 7 8 9
char bn1[]={B,2,1, 2,1,A, 2,2,1, 2,2,1, 3,A,B, B,2,2, B,2,2, 2,2,B, B,2,1, B,2,1};
char bn2[]={B,A,B, A,B,A ,3,2,2, A,6,1, 5,6,B, 5,6,7, B,6,7, A,3,2, B,6,B, 5,6,B};
char bn3[]={4,3,B, 3,B,3, B,3,3, 3,3,B, A,A,B, 3,3,B, 4,3,B, A,B,A, 4,3,B, A,A,B};
void printOneNumber(uint8_t digit)
{
// Print position is hardcoded
// Line 1 of the one digit number
lcd.setCursor(0,1);
lcd.write(bn1[digit*3]);
lcd.write(bn1[digit*3+1]);
lcd.write(bn1[digit*3+2]);
// Line 2 of the one-digit number
lcd.setCursor(0,2);
lcd.write(bn2[digit*3]);
lcd.write(bn2[digit*3+1]);
lcd.write(bn2[digit*3+2]);
// Line 3 of the one-digit number
lcd.setCursor(0,3);
lcd.write(bn3[digit*3]);
lcd.write(bn3[digit*3+1]);
lcd.write(bn3[digit*3+2]);
}
void printTwoNumber(uint8_t number)
{
// Print position is hardcoded
int digit0; // To represent the ones
int digit1; // To represent the tens
digit0=number%10;
digit1=number/10;
// Line 1 of the two-digit number
lcd.setCursor(13,1);
lcd.write(bn1[digit1*3]);
lcd.write(bn1[digit1*3+1]);
lcd.write(bn1[digit1*3+2]);
lcd.write(A); // Blank
lcd.write(bn1[digit0*3]);
lcd.write(bn1[digit0*3+1]);
lcd.write(bn1[digit0*3+2]);
// Line 2 of the two-digit number
lcd.setCursor(13,2);
lcd.write(bn2[digit1*3]);
lcd.write(bn2[digit1*3+1]);
lcd.write(bn2[digit1*3+2]);
lcd.write(A); // Blank
lcd.write(bn2[digit0*3]);
lcd.write(bn2[digit0*3+1]);
lcd.write(bn2[digit0*3+2]);
// Line 3 of the two-digit number
lcd.setCursor(13,3);
lcd.write(bn3[digit1*3]);
lcd.write(bn3[digit1*3+1]);
lcd.write(bn3[digit1*3+2]);
lcd.write(A); // Blank
lcd.write(bn3[digit0*3]);
lcd.write(bn3[digit0*3+1]);
lcd.write(bn3[digit0*3+2]);
}
// The write to ESS9008 DAC routine
void bufwritereg(uint8_t regaddr,uint8_t regval)
{
Wire.beginTransmission(0x48);
Wire.send(regaddr);
Wire.send(regval);
Wire.endTransmission();
}
// Interrupt service routine for rotary encoder. Determines direction.
volatile byte volUp=0; // flags for the interrupt routine
volatile byte volDown=0;
void decoder()
{
if (digitalRead(2) == digitalRead(4))
{
volUp = 1; //if on interrupt the encoder channels are the same, direction is clockwise
}
else
{
volDown = 1; //if they are not the same, direction is ccw
}
}
// interrupt service routine for remote
volatile byte remoteOn = 0; // 1 means remote has been pressed
void remoting()
{
remoteOn=1;
}
// Declaring some more variables
int currVol=DEFAULTVOL; // this needs to be at least 10 bits
byte regval=0; // variable for volume lower bits
int irCode=0; // The code returned by the remote IR pulses
// This is the main decoding code for the remote.
int getIRKey() {
int duration=1;
int result=0;
while((duration=pulseIn(IRPIN, LOW, 50000)) < 2200 && duration!=0)
{
//do nothing waiting for start pulse
}
int mask = 1; // set mask to bit 0
for (int idx = 0; idx < 12; idx++) // get all 12 bits
{
duration = pulseIn(IRPIN, LOW, 2000); // measure the bit pulse
if (duration > ONEPULSE) // 1 bit?
result |= mask; // yes, update ir code
mask <<= 1; // shift mask to next bit
}
return result;
}
void setup() {
lcd.begin(20, 4);
lcd.clear();
DefineLargeChar(); // Define large characters
Wire.begin(); // Joining the I2C bus as master
pinMode(VOLUPPIN, INPUT); // Button or Encoder pin for volume up
digitalWrite(VOLUPPIN, HIGH); // Enable pull-up resistor
pinMode(VOLDOWNPIN, INPUT); // Button or Encoder pin for volume down
digitalWrite(VOLDOWNPIN, HIGH); // Enable pull-down resistor
pinMode(IRPIN, INPUT); // Pin for IR Receiver
digitalWrite(IRPIN, HIGH); // Enable high as specified by datasheet
delay(3000);
// The following lines is to set up the default volume
// To set up the volume you need to write to at least 8 registers
regval=DEFAULTVOL;
bufwritereg(REG0,regval);
bufwritereg(REG1,regval);
bufwritereg(REG2,regval);
bufwritereg(REG3,regval);
bufwritereg(REG4,regval);
bufwritereg(REG5,regval);
bufwritereg(REG6,regval);
bufwritereg(REG7,regval);
attachInterrupt(0, decoder, CHANGE); // ISR for rotary encoder
attachInterrupt(1, remoting, RISING); // ISR for remote IR sensor
lcd.setCursor(0,0);
// print header for current input
printOneNumber(1);
// print header for volume
lcd.setCursor(13,0);
lcd.print("-dB VOL");
printTwoNumber(currVol/2);
// Print the rest of the display
lcd.setCursor(4,2);
lcd.print("INPT");
lcd.write(0xA5);
lcd.print("PCM");
lcd.setCursor(4,1);
lcd.print("RATE");
lcd.write(0xA5);
lcd.print("192");
}
void loop()
{
// The following is to adjust the volume down (larger number)
while(volUp==1) // While there is CW motion in the rotary encoder
{
volUp=0; // Reset the flag
if (currVol<MINVOL)// Check if already at min numerical Volume
{
currVol=currVol+1; // Increase 0.5 dB
regval=currVol;
bufwritereg(REG0,regval); // Writing to reg 0
bufwritereg(REG1,regval);
bufwritereg(REG2,regval);
bufwritereg(REG3,regval);
bufwritereg(REG4,regval);
bufwritereg(REG5,regval);
bufwritereg(REG6,regval);
bufwritereg(REG7,regval);
printTwoNumber(currVol/2);
}
}
// The following is to adjust the volume up (smaller numbers)
while(volDown==1) // While there is ccw motion in rotary encoder
{
volDown=0; // clear the flag
if (currVol>MAXVOL) // Check if already at max Volume
{
currVol=currVol-1; // Decrease 0.5 dB
regval=currVol; // Calculate value for reg0
bufwritereg(REG0,regval); // Writing to reg 0
bufwritereg(REG1,regval);
bufwritereg(REG2,regval);
bufwritereg(REG3,regval);
bufwritereg(REG4,regval);
bufwritereg(REG5,regval);
bufwritereg(REG6,regval);
bufwritereg(REG7,regval);
printTwoNumber(currVol/2);
}
}
// The following code is for the remote.
while (remoteOn==1)
{
irCode = getIRKey(); //Fetch the key
//lcd.setCursor(4,3); // Used to find out remote keys value
//lcd.print(" ");
//lcd.setCursor(4,3); // Used to find out remote keys value
//lcd.print(irCode);
switch(irCode){
case KEY1:
printOneNumber(1);
break;
case KEY2:
printOneNumber(2);
break;
// The following for volume
case KEYVOLUP:
if (currVol<MINVOL)// Check if already at min numerical Volume
{
currVol=currVol+1; // Increase 0.5 dB
regval=currVol; // Calculate value for reg0
bufwritereg(REG0,regval); // Writing to reg 0
bufwritereg(REG1,regval);
bufwritereg(REG2,regval);
bufwritereg(REG3,regval);
bufwritereg(REG4,regval);
bufwritereg(REG5,regval);
bufwritereg(REG6,regval);
bufwritereg(REG7,regval);
printTwoNumber(currVol/2);
}
break;
case KEYVOLDOWN:
if (currVol>MAXVOL) // Check if already at max Volume
{
currVol=currVol-1; // Decrease 0.5 dB
regval=currVol;
bufwritereg(REG0,regval); // Writing to reg 0
bufwritereg(REG1,regval);
bufwritereg(REG2,regval);
bufwritereg(REG3,regval);
bufwritereg(REG4,regval);
bufwritereg(REG5,regval);
bufwritereg(REG6,regval);
bufwritereg(REG7,regval);
printTwoNumber(currVol/2);
}
break;
}
remoteOn=0; //reset flag
}
}
Κυριακή 6 Δεκεμβρίου 2009
The Buffalo Code so far....
Here is the latest code. Most sections were derived from HIFIDUINO- glt's work - appropriate thanks are due!
Δευτέρα 12 Οκτωβρίου 2009
My Buffalo
Here is my Buffalo24 with IVY and MUX and defeatable Metronome. The 20x4 lcd, the OTTO and the I2C bus is driven by a SEEEDUINO Mega Arduino compatible MCU.
The I2C 3.3v conversion is performed by Analog Devices iCoupler Isolator ADUM1250 and the 3.3v control lines selection by Analog Devices ADG3304.
A rotary encoder is used for volume selection. Sony remote Control and the rotary encoder is implemented ala HIFIDUINO style
Εγγραφή σε:
Αναρτήσεις (Atom)