#include #define PIN_DATA_VOL_A 8 #define PIN_DATA_VOL_B 7 #define PIN_DATA_VOL_C 6 #define PIN_DATA_VOL_D 5 #define PIN_DATA_CLOCK 9 #define PIN_SR_DATA 2 #define PIN_SR_LTCH 3 #define PIN_SR_CLOCK 4 #define PIN_LED 13 // Serial Protocol: // 9600 Baud // 1 char: room number 1-5 // 2 char: command v (volume) / r (relais) // relais command: // 3 char: a or b // volume command: // 3-5 char: 0-100 volume long tick; uint16_t relaisData = 0xffff; void setup() { Serial.begin(9600); Serial.setTimeout(100); pinMode(PIN_DATA_VOL_A, OUTPUT); pinMode(PIN_DATA_VOL_B, OUTPUT); pinMode(PIN_DATA_VOL_C, OUTPUT); pinMode(PIN_DATA_VOL_D, OUTPUT); pinMode(PIN_DATA_CLOCK, OUTPUT); pinMode(PIN_SR_DATA, OUTPUT); pinMode(PIN_SR_LTCH, OUTPUT); pinMode(PIN_SR_CLOCK, OUTPUT); pinMode(PIN_LED, OUTPUT); // shift out one time 0xffff to set all pins high. our relais boards // are active-low shiftRelais(relaisData); setVolume(1, 50); setVolume(2, 50); setVolume(3, 50); setVolume(4, 50); setVolume(5, 50); } void shiftRelais(uint16_t data) { digitalWrite(PIN_SR_LTCH, LOW); shiftOut(PIN_SR_DATA, PIN_SR_CLOCK, MSBFIRST, (data >> 8)); shiftOut(PIN_SR_DATA, PIN_SR_CLOCK, MSBFIRST, data & 0xff); digitalWrite(PIN_SR_LTCH, HIGH); } // channel is our "room" 1-5 / state for switching between A or B input void switchInputs(uint8_t channel, bool state) { // 16 . . . . . . . . . . . . . . . . . . . 0 // we use a simple switch case with some if instead of // tricky bitmagic to allow a more visual programming // of our relais configuration switch(channel) { case 1: if(state) { relaisData |= _BV(7) | _BV(6); } else { relaisData &= ~(_BV(7) | _BV(6)); } break; case 2: if(state) { relaisData |= _BV(5) | _BV(4); } else { relaisData &= ~(_BV(5) | _BV(4)); } break; case 3: if(state) { relaisData |= _BV(3) | _BV(2); } else { relaisData &= ~(_BV(3) | _BV(2)); } break; case 4: if(state) { relaisData |= _BV(1) | _BV(0); } else { relaisData &= ~(_BV(1) | _BV(0)); } break; case 5: if(state) { relaisData |= (_BV(15) | _BV(14)); } else { relaisData &= ~(_BV(15) | _BV(14)); } break; } shiftRelais(relaisData); } uint8_t logify(uint8_t volumelinear){ double volumelog=log10( ((double)volumelinear)/10.0 +1)*97; return (int)volumelog; } // control a M62429 Chip for Volume Control // function take from here: http://forum.arduino.cc/index.php?topic=244152.0 void setVolume(uint8_t volume, uint8_t dataPin) { uint8_t bits; uint16_t data = 0; // control word is built by OR-ing in the bits // convert attenuation to volume / remember 0 is full volume! volume = (volume > 100) ? 0 : (((volume * 83) / -100) + 83); data |= (0 << 0); data |= (0 << 1); data |= ((21 - (volume / 4)) << 2); data |= ((3 - (volume % 4)) << 7); data |= (0b11 << 9); for (bits = 0; bits < 11; bits++) { _delay_us(2); digitalWrite(dataPin, 0); _delay_us (2); digitalWrite(PIN_DATA_CLOCK, 0); _delay_us (2); digitalWrite(dataPin, (data >> bits) & 0x01); _delay_us (2); digitalWrite(PIN_DATA_CLOCK, 1); } _delay_us(2); digitalWrite(dataPin, 1); // final clock latches data in _delay_us (2); digitalWrite(PIN_DATA_CLOCK, 0); } void loop() { long currentMillis = millis(); if (Serial.available() > 0) { String ser = Serial.readString(); int room = ser.charAt(0) - 48; if(room >= 1 && room <= 5) { char command = ser.charAt(1); if(command == 'v') { //volume int datapin=0; switch(room){ case 1: datapin=PIN_DATA_VOL_A; break; case 2: datapin=PIN_DATA_VOL_B; break; case 3: datapin=PIN_DATA_VOL_C; break; case 4: datapin=PIN_DATA_VOL_D; break; } int vol=ser.substring(2).toInt(); setVolume(logify(vol),datapin); } else if(command == 'r') { // relais char state = ser.charAt(2); if (state=='a') { switchInputs(room,true); } else if (state=='b') { switchInputs(room,false); } } // end if command check } // end if room check } // end serial available check }