Source slection on multizone amp

Discussion in 'C-Touch/HomeGate/SchedulePlus/PICED Software' started by Matt, Dec 16, 2012.

  1. Matt

    Matt

    Joined:
    Aug 3, 2004
    Messages:
    27
    Likes Received:
    2
    Location:
    Cairns North Queensland
    Just a quick question to all the logic code buffs out there.

    I am trying to integrate a axium multi zone amp in to my c-bus system, and have most of it up and running but the code for the source selection (which i borrowed and adapted from the forum) is a bit clunky and sometimes misses button presses (the button press is logged in the piced log file) or skips sources (jumps 2 source selections).

    So the question is. Am i going about this the right way or is there a easier or more elegant way to go about it

    so the code is
    Code:
    {Zone1 source Select}
    RequiredSourceZone1Amp := GetLightingLevel("Zone1Source");   {get the level}
    Zone1SourceOutString := Z1Source;  {set the first part of the command string}
    Append(Zone1SourceOutString,Zone1Source); {add the strings together}
    Append(Zone1SourceOutString,LF); {add a line feed } 
    if GetLightingState("Zone1Source")=ON then
    begin
    Zone1SourceCounter := Zone1SourceCounter +1;
    end;
    
    case Zone1SourceCounter of
    1 : begin
    Zone1Source := CD;
    Zone1SourceName := 'CD';
      end;
    2 : begin 
    Zone1Source := Tape;
    Zone1SourceName := 'Tape';
      end;
    3 : begin
    Zone1Source := Tuner;
    Zone1SourceName := 'Tuner';
      end;
    4 : begin
    Zone1Source := Aux;
    Zone1SourceName := 'Aux';
      end;
    5 : begin 
    Zone1Source := Utility;
    Zone1SourceName := 'Utility';
      end;
    6 : begin
    Zone1Source := Sat;
    Zone1SourceName := 'Sat';
      end;
    7 : begin
    Zone1Source := Dvd;
    Zone1SourceName := 'Dvd';
      end;
    8 : begin
    Zone1Source := Video;
    Zone1SourceName := 'Video';
      end;
        end;
    if Zone1SourceCounter >= 9 then
    begin Zone1SourceCounter := 0;
    end;
    if ( RequiredSourceZone1Amp <> CurrentSourceZone1Amp) then
    begin
    WriteSerial(1, Zone1SourceOutString);
    SetStringIBSystemIO("Label Group Text", "Local Network", "Lighting", "Zone1Source", Variant1, Zone1SourceName);
    CurrentSourceZone1Amp := RequiredSourceZone1Amp;
    end;
    
     
    Matt, Dec 16, 2012
    #1
  2. Matt

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,548
    Likes Received:
    178
    Location:
    Adelaide, Australia
    A couple of quick questions
    1/ How is the DLT set up (i.e what happens when you press the source switch)
    2/ Can multiple DLT's change the source in the same zone?
    3/ Is this code repeated for multiple zones?
    4/ What are the values for CD, Tape etc (I assume they are set in the initialisation section?)

    Also, you might want to try changing the wrap around test to >= 8. As it is, every ninth press will be ignored.

    Ashley
     
    Ashley, Dec 16, 2012
    #2
  3. Matt

    Matt

    Joined:
    Aug 3, 2004
    Messages:
    27
    Likes Received:
    2
    Location:
    Cairns North Queensland
    Hello Ashley

    some answers to your questions are as follows

    1. The DLT set-up i am using at the moment as just a test unit on my bench with button one as a bell press all other buttons are unassigned

    2. Not yet but that may be a requirement in the future i was mainly hoping to control from the wiser

    3. The code is not repeated yet as i was trying to get 1 zone working first then just to duplicate the code for the other 7 zones

    4. The Values for The sources are just hex values defined in 'constants'
    e.g. CD = #$30#$30;
    that are added to the final hex string and then sent to the amp.

    Also i have not downloaded the project into the touchscreen yet. I am just running the project in piced connected to the network via a 5500cn and watching the log for the serial out strings.
     
    Last edited by a moderator: Dec 17, 2012
    Matt, Dec 17, 2012
    #3
  4. Matt

    NickD Moderator

    Joined:
    Nov 1, 2004
    Messages:
    1,427
    Likes Received:
    64
    Location:
    Adelaide
    This will increment your source count while the group is on. If you are using a bell press, then it will increment the source once every 200ms (ie 5 times a second) while you have your finger on the button.

    I'd suggest you use an "On" key function, and when the On state is detected in the logic, the logic then turns the group off. This will ensure you get a single step for each button press.

    Alternatively you could change the "if" to a "once" but this will still allow multiple steps in the event that there is any key bounce on the bellpress (resulting in multiple on/off commands).

    Nick
     
    Last edited by a moderator: Dec 18, 2012
    NickD, Dec 18, 2012
    #4
  5. Matt

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,548
    Likes Received:
    178
    Location:
    Adelaide, Australia
    Hi Matt

    As Nick has suggested, I think the main issue you are having is with the Bell Press command. The logic is only executed every 200mS at which point it will look at the current GA value. If the button is pressed and released withing this time frame (quite easy to do), the button press will be missed. Also, if the button is held down for more than 200mS (also quite easy to do), the logic will see the GA set in both scans and skip over 2 sources. There is also that problem with the wrap around test using 9 instead of 8 which means every 9th press will do nothing.

    The best way to detect button presses in logic is to set the GA to a specific value (either using the ON or PRESET macro functions), then get the logic to turn it off again once it has processed the command. This way a press can never be missed no matter how slow the logic is running.

    You can simplify your logic by using an array to hold each source selection then just indexing into the array. This gets rid of that long CASE command. In a similar way, the same bit of logic can handle all the zones, getting rid of duplicate logic.

    In the code below, the DLT (or whatever) is set to macro function ON to step through the sources, or PRESET 1-8 to directly select a source (note that this won't work for DLT labels unless you modify the code to use variants). The GA selects the zone. An array called zoneGAs contains a list of all the GAs used in the switches in order of Zone number. I have used a character array here rather than the usual integer array because it can be initialised with all the GA's in one command (as a string) rather than a seperate assignment for each zone. The ORD (ordinal) function converts the character into an integer.

    Each scan, the module loops through the zones (using the FOR statement) and reads the value of the GA for that zone. If the GA is not 0 (OFF) we know the switch has been pressed. If the value is 255 we step onto the next source. Because we need to store a seperate source for each zone we use an array to hold all the values. If the value is 1-8 we select the source directly (there is no real need to range test this a is permanantly set up in the switches).

    The command to send to the Axium is stored as a skeleton holding the fixed parts. We then just overwrite the zone and source characters. This is a lot more efficient than multiple Append statements which have to copy the string contents. The Zone number is converted to hex using 2 lookup tables, one for each digit. Again this takes a lot less code than IntToHex and the associated copying. The source is converted to ascii by adding the source number to an ascii '0' to give ascii '1' to '8'.

    The DLT labels are stored in a array of strings which is directly indexed by the source number.

    The last step is to set the GA back to OFF.

    The initialisation section sets all the zone GA's to 1 which forces all the sources to be reset to source 1

    I tested this on a DLT an it all works fine. I don't have an Axium to test but the output looks correct.



    Code:
    {Constants}
    
    ZoneCount = 8; // Change for number of zones suported
    
    {Global Variables}
    
    zone: integer; // Current zone being tested
    ZoneSource: array[1..zoneCount] of integer;      // Saves current source for each zone
    SourceNames: array[1..8] of array[0..7] of char; // Holds source names. Set up once in initialisation section
    ZoneGAs: array[0..zoneCount] of char;            // Must be initialised to list of GA's controlling each zone
    ZoneCodes1: array[0..32] of char;                // 1st char of hex digit 
    ZoneCodes2: array[0..32] of char;                // 2nd char of hex digit
    zoneGA: integer;                                 // Temp store for GA of zone pressed
    zoneCommand: array[0..7] of char;                // Command to send to Axium
    newSource: integer;                              // Temp hold for new source selected
    
    {Initialisation section}
    
    // Init source names
    SourceNames[1] := 'CD';
    SourceNames[2] := 'Tape';
    SourceNames[3] := 'Tuner';
    SourceNames[4] := 'Aux';
    SourceNames[5] := 'Utility';
    SourceNames[6] := 'Sat';
    SourceNames[7] := 'Dvd';
    SourceNames[8] := 'Video';
    //
    ZoneCodes1     := '00000000000000001111111111111111'; // 1st hex digit of zone
    ZoneCodes2     := '0123456789ABCDEF0123456789ABCDEF'; // 2nd hex digit of zone
    ZoneCommand    := '03zz0s'#10;                        // Skeleton Set Source command
    // Set GA's controlling each zone here. In switch set function to 'ON' for NEXT and preset 0-7 for direct selection
    ZoneGAs        := #120#121#122#123#124#125#126#127;   // They don't have to be sequential!
    //
    for zone := 1 to zoneCount do SetLightingLevel(ord(zoneGAs[zone]), 1, "0s"); // Init all GA's
    openSerial(1, 1, 9600, 8, 1, 0, 0); // Open serial port
    
    
    {Module}
    //
    // Select Axium source. GA gives zone, level gives new source (1-8). 255 = step to next
    //
    for zone := 1 to ZoneCount do                 // Loop for all zones
    begin
      zoneGA := ord(zoneGAs[zone]);               // Get next zone GA to test
      newSource := GetLightingLevel(zoneGA);      // Get current GA level;
      if newSource <> 0 then                      // Switch has been pressed
      begin
        if newSource = 255 then                   // 255 = ON = Step to next
        begin
          newSource := zoneSource[zone];          // Get last source
          newSource := newSource + 1;             // Next source
          if newSource > 8 then newSource := 1;   // Wrap around
        end;
        zoneSource[zone] := newSource;            // Save new source
        // Set up command
        zoneCommand[3] := zoneCodes1[zone];       // Put 1st hex char of Zone into command string
        zoneCommand[4] := zoneCodes2[zone];       // Put 2nd hex char of Zone into command string
        zoneCommand[6] := chr(ord('0') + newSource - 1); // Put new source into command string
        writeSerial(1, zoneCommand);              // Write it
        SetStringIBSystemIO("Label Group Text", "Local", "Lighting", zoneGA, Variant1, SourceNames[newSource]); // Set label
        SetLightingState(zoneGA, OFF);            // Reset GA
      end
    end

    Ashley
     
    Last edited by a moderator: Dec 18, 2012
    Ashley, Dec 18, 2012
    #5
  6. Matt

    Matt

    Joined:
    Aug 3, 2004
    Messages:
    27
    Likes Received:
    2
    Location:
    Cairns North Queensland
    Ashley Thank you very much for the code it works like a charm.

    I have finally had a chance to sit down and work on it again after a short break, It was starting to do my head in. I haven't done much with the logic programming and it is all very over whelming at this point, but i am slowly learning with the generous help on this forum.

    Now i just have to figure out how to do the same thing with the power and the mute commands.
     
    Matt, Dec 31, 2012
    #6
  7. Matt

    Ashley

    Joined:
    Dec 1, 2005
    Messages:
    1,548
    Likes Received:
    178
    Location:
    Adelaide, Australia
    Just out of curiosity, how are you doing the volume?

    The Axium looks like a nice unit. Where did you source it from and how much do they cost?

    Ashley
     
    Ashley, Jan 1, 2013
    #7
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.