Sony Control-S help me do it better

I am working on controlling a Sony receiver via the Control-S bus http://www.armory.com/~spcecdt/remote/control-S.html I have written a proof of concept sketch and am able to turn the receiver on and off. However I think there should be an easier/more logical way to write the program. Below is the code that I have written that works. However it will be complicated to expand as I add more control functions. The control packet has to be 45ms and each packet has to be sent 3 times. long A logical 1 = 1.8ms and a logical 0 =1.2 ms each packet is 12 bits and will take a different amount of time to transmit so I have to do math on each packet to determine how long to wait before I send the next packet (in the case of the power command its 29ms).

I lack the vocabulary I need to properly ask the questions below so please bear with me.

What do I need to do to get a binary number represented in hex to correspond with the string of logical 1's and 0's that i need to send? So I can do something like sendCmd(0xA81).

How do I calculate how long 0xA81 takes to transmit so I can subtract it from 45 to get the amount of time to delay?

Any help is appreciated Thanks, Josh

//////////////////////////////////
//Working Sony Control-S Sketch //
//////////////////////////////////

int cpin = 12; //control s-pin 

void setup() {                
 pinMode(cpin, OUTPUT);   
 digitalWrite(cpin, LOW); // Make sure CPIN is LOW on startup 
 delay(2000); //just seems like a good idea
}

void loop() {
  
/// Example code eventualy will have the code run based on a button press or some other input  

 ////Packet must be sent three times total packet length must be 45ms I know I can simplify sending this 3 times with a loop 

 SB();  //send start string  #1
 powercode(); //send power on
 delay (29) //holds  pin 12 low for 29ms to make entire packet length 45ms
  
 SB();  //send start string #2
 powercode(); //send power on
 delay (29)

 SB();  //send start string #3
 powercode(); //send power on
 delay (29)

//some visual feedback to let me know the packets were sent.
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

/////////Functions////////
/// L1 and L0 functions Define what logic "1" and logic "0" are
/// SB Defines the start bit
//////////

int L1(){   //Logic 1
  //digitalWrite(cpin,LOW);
  delayMicroseconds(600);//space
  digitalWrite(cpin, HIGH);
  delayMicroseconds(1200);
  digitalWrite(cpin,LOW);
}

void L0 () { //Logic 0
  //digitalWrite(cpin,LOW);
  delayMicroseconds(600);//space
  digitalWrite(cpin, HIGH);
  delayMicroseconds(600);
  digitalWrite(cpin, LOW);
}

void SB (){  //start bit transmit
  digitalWrite(cpin,LOW);
  delayMicroseconds(600);
  digitalWrite(cpin, HIGH);
  delayMicroseconds(2400);
  digitalWrite(cpin, LOW);
}





////Control Function

void powercode() // the code that turns the power on and off
{
L1();
L0();
L1();
L0();
L1();
L0();
L0();
L0();
L0();
L0();
L0();
L1();
}

A good place to start would be to look at "bitRead" over at the reference page.

Rather than calculate a delay you can use the time to determine if it's time to send again:

currentTime = millis();
if (timesToSend && currentTime - lastSendTime > 45)
    {
    send the command (again?)
    timesToSend--;
    lastSendTime = currentTime;
    }

if (timesToSend == 0)  //  No output left to do
   {
   if we want to send another command:
         command = whatever value
         timesToSend = 3;
   }

That will send the command 3 times at 45 millisecond intervals.

John, That makes much more sense than what I was trying to do.

AWOL, I think I see where you are going... Not sure if i can get there though.

Thanks, Josh

AWOL, I think I see where you are going... Not sure if i can get there though

This:

void powercode() // the code that turns the power on and off
{
L1();
L0();
L1();
L0();
L1();
L0();
L0();
L0();
L0();
L0();
L0();
L1();
}

looks to me a lot like "transmit (0b101010000001);" or "transmit (0xA81);"

Well, here is my final code for the Sony Control-S I couldn’t wrap my head around a better way to do it so I literally used excel to automate the writing of the functions for the receiver control. I used Excel to turn the Binary string for each control code into the function that calls the series of functions that represent the logical 1’s and 0’s. If I need to add a new function I can now just type the binary string into excel and it spits out a complete function for the command. its not pretty but it works.

Ignore the light switch stuff this project is just the beginning of a bigger home automation project.

#include <X10Firecracker.h>
int cpin = A0; //control s-pin 
int ls1 = A1; //Light Switch Pins 
int ls2 = A2;
int ls3 = A3;
int ls1state = 0;          
int ls1last = 0;
int ls2state = 0;          
int ls2last = 0;
int ls3state = 0;          
int ls3last = 0;
int ls1count = 0;
long lastDebounceTime = 0; 
long debounceDelay = 50;
int lastls1state = LOW;


void setup() {
  pinMode(cpin,OUTPUT); 
  digitalWrite(ls1,HIGH);
  digitalWrite(ls2,HIGH);
  digitalWrite(ls3,HIGH);
  X10.init( 2, 3, 1 );  //Initalize X10 Cm17a
  Serial.begin(9600);    //Initalize serial Port
  pinMode(cpin, OUTPUT);   
  digitalWrite(cpin, LOW); // Make sure CPIN is LOW on startup 
  ls1last =digitalRead(ls1);
  delay(1000);
}

void loop()
{
 
  if (Serial.available() > 0) {
    int inByte = Serial.read();
    //int lastOn = 0;
    switch (inByte) {
    case 'A':  //ON = Uppercase   
      X10.sendCmd( hcA, 1, cmdOn );
      Serial.println("A1 ON"); 
      break;
    case 'B':    
      X10.sendCmd( hcA, 2, cmdOn );
      Serial.println("A2 ON");
      break;
    case 'C':    
      X10.sendCmd( hcA, 3, cmdOn );
      Serial.println("A3 ON");
      break;
    case 'D':    
      X10.sendCmd( hcA, 4, cmdOn );
      Serial.println("A4 ON");
      break;
    case 'E':    
      X10.sendCmd( hcA, 5, cmdOn );
      Serial.println("A5 ON");
      break;
    case 'F':    
      X10.sendCmd( hcA, 5, cmdOn );
      Serial.println("A6 ON");
      break;
    case 'G':    
      X10.sendCmd( hcA, 7, cmdOn );
      Serial.println("A7 ON");
      break;
    case 'H':    
      X10.sendCmd( hcA, 8, cmdOn );
      Serial.println("A8 ON");
      break;
    case 'I':    
      X10.sendCmd( hcA, 9, cmdOn );
      Serial.println("A9 ON");
      break;
    case 'J':    
      X10.sendCmd( hcA, 10, cmdOn );
      Serial.println("A10 ON");
      break;
    case 'K':    
      X10.sendCmd( hcA, 11, cmdOn );
      Serial.println("A11 ON");
      break;
    case 'L':    
      X10.sendCmd( hcA, 12, cmdOn );
      Serial.println("A12 ON");
      break;
    case 'M':    
      X10.sendCmd( hcA, 13, cmdOn );
      Serial.println("A13 ON");
      break;
    case 'N':    
      X10.sendCmd( hcA, 14, cmdOn );
      Serial.println("A14 ON");
      break;
    case 'O':    
      X10.sendCmd( hcA, 15, cmdOn );
      Serial.println("A15 ON");
      break;
    case 'P':    
      X10.sendCmd( hcA, 16, cmdOn );
      Serial.println("A16 ON");
      break;
    case 'a':    //OFF = Lowercase
      X10.sendCmd( hcA, 1, cmdOff );
      Serial.println("A1  OFF");
      break;
    case 'b':    
      X10.sendCmd( hcA, 2, cmdOff );
      Serial.println("A2 OFF");
      break;
    case 'c':    
      X10.sendCmd( hcA, 3, cmdOff );
      Serial.println("A3 OFF");
      break;
    case 'd':    
      X10.sendCmd( hcA, 4, cmdOff );
      Serial.println("A4 OFF");
      break;
    case 'e':    
      X10.sendCmd( hcA, 5, cmdOff );
      Serial.println("A5 OFF");
      break;
    case 'f':    
      X10.sendCmd( hcA, 6, cmdOff );
       Serial.println("A6 OFF");
      break;
    case 'g':    
      X10.sendCmd( hcA, 7, cmdOff );
       Serial.println("A7 OFF");
      break;
    case 'h':    
      X10.sendCmd( hcA, 8, cmdOff );
       Serial.println("A8 OFF");
      break;
    case 'i':    
      X10.sendCmd( hcA, 9, cmdOff );
       Serial.println("A9 OFF");
      break;
    case 'j':    
      X10.sendCmd( hcA, 10, cmdOff );
       Serial.println("A10 OFF");
      break;
    case 'k':    
      X10.sendCmd( hcA, 11, cmdOff );
       Serial.println("A11 OFF");
      break;
    case 'l':    
      X10.sendCmd( hcA, 12, cmdOff );
       Serial.println("A12 OFF");
      break;
    case 'm':    
      X10.sendCmd( hcA, 13, cmdOff );
       Serial.println("A13 OFF");
      break;
    case 'n':    
      X10.sendCmd( hcA, 14, cmdOff );
       Serial.println("A14 OFF");
      break;
    case 'o':    
      X10.sendCmd( hcA, 15, cmdOff );
       Serial.println("A15 OFF");
      break;
    case 'p':    
      X10.sendCmd( hcA, 16, cmdOff );
       Serial.println("A16 OFF");
      break;
    case '+':   //bright
      X10.sendCmd( hcA, 1, cmdBright );
       Serial.println("A BRIGHT OFF");
      break;
    case '-':    //dim
      X10.sendCmd( hcA, 1, cmdDim );
       Serial.println("A DIM OFF");
      break;
    case '0':     
      poweroff();
      Serial.println("Sony Power Off");
      break;
    case '1':     
      poweron();
      Serial.println("Sony Power On");
      break;
    case '2':     
      mute();
      break;
    case '3':     
      vid2();
      break;
    case '4':     
      tuner();
      break;
    case '5':     
      tunescandown();
      break;
    case '6':     
      tunescanup();
      break;
    case '7':     
      {
      int z=0; 
        while (z < 6){
        volup();
        delay (50);
        z++;
        }
      }
     break;
    
    case '8':     
      {
      int y=0; 
        while (y < 6){
        voldn();
        delay (50);
        y++;
        }
      }
     break;
     
    case '9':     
      CD();
      break;

      ///for testing
    case 'Q':    
      X10.sendCmd( hcB, 1, cmdOn);
      digitalWrite(13, HIGH);   
      delay(500);              
      digitalWrite(13, LOW);
      break;
    case 'q':    
      X10.sendCmd( hcB, 1, cmdOff );
      digitalWrite(13, HIGH);   
      delay(200);              
      digitalWrite(13, LOW);
      delay(200); 
      digitalWrite(13, HIGH);   
      delay(200);              
      digitalWrite(13, LOW);
      break;
    }
  }
}
   


/////////Functions For Sony Control S////////
/// Defining what logic "1" and logic "0" are
//////////////////////////
int L1(){   //Logic 1
  //digitalWrite(cpin,LOW);
  delayMicroseconds(600);//space
  digitalWrite(cpin, HIGH);
  delayMicroseconds(1200);
  digitalWrite(cpin,LOW);
}

void L0 () { //Logic 0
  //digitalWrite(cpin,LOW);
  delayMicroseconds(600);//space
  digitalWrite(cpin, HIGH);
  delayMicroseconds(600);
  digitalWrite(cpin, LOW);
}

void SB (){  //start bit transmit
  digitalWrite(cpin,LOW);
  delayMicroseconds(600);
  digitalWrite(cpin, HIGH);
  delayMicroseconds(2400);
  digitalWrite(cpin, LOW);
}


////Control Functions 
////  Send string 

void tuneup  () { int x=0; while (x < 4){SB();L0();L0();L0();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void tunedown () { int x=0; while (x < 4){SB();L1();L0();L0();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void volup () { int x=0; while (x < 4){SB();L0();L1();L0();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void voldn () { int x=0; while (x < 4){SB();L1();L1();L0();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void power () { int x=0; while (x < 4){SB();L1();L0();L1();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void poweron () { int x=0; while (x < 4){SB();L0();L1();L1();L1();L0();L1();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void poweroff () { int x=0; while (x < 4){SB();L1();L1();L1();L1();L0();L1();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void tv () { int x=0; while (x < 4){SB();L1();L0();L1();L1();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void vid2 () { int x=0; while (x < 4){SB();L0();L1();L1();L1();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void tuner () { int x=0; while (x < 4){SB();L1();L0();L0();L0();L0();L1();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void CD () { int x=0; while (x < 4){SB();L1();L0();L1();L0();L0();L1();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void mute () { int x=0; while (x < 4){SB();L0();L0();L1();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void tunerpreset () { int x=0; while (x < 4){SB();L0();L1();L1();L0();L1();L0();L0();L0();L0();L0();L0();L1();delay (25);x++;}}
void tunescanup  () { int x=0; while (x < 4){SB();L0();L1();L0();L0();L1();L0();L0();L1();L0();L1();L1();L0();delay (25);x++;}}
void tunescandown  () { int x=0; while (x < 4){SB();L1();L1();L0();L0();L1();L0();L0();L1();L0();L1();L1();L0();delay (25);x++;}}



///FEEDBACk Function
void flash (){
int x;
while (x < 6){
digitalWrite(13,HIGH);
delay (100);
digitalWrite (13,LOW);
x++;
}
}