Examples - Generic OneWire Example

Top  Previous  Next

//------------------------------------------------------------------------------
// DS2408.vpl, created 2012-05-09 10:19
//
// Demonstrate communication with Maxim DS2408 1-Wire device, using the generic
// 1-Wire interface.
//
// DESCRIPTION of the DS2408
//    The DS2408 is an 8-channel, programmable I/O 1-Wire chip. PIO outputs are
//    configured as open-drain and provide an on resistance of 100Ω max.
//    A robust PIO channel-access communication protocol ensures that PIO
//    output-setting changes occur error-free. A data-valid strobe output can
//    be used to latch PIO logic states into external circuitry such as a D/A
//    converter (DAC) or microcontroller data bus.
//
//
// HARDWARE configuration
//    The hardware used to communicate with is based on the reference design
//    found in the datasheet of the DS2408 (version 19-5702; 12/10), and an
//    RTCU AX9 pro, which supply the DS2408 with 3.3VDC from DCOUT33.
//
//    AX9 pro              DS2408            External
//
//    1-Wire      -->   IO         P0  -->   SW1    
//    SGND        -->   GND        P1  -->   SW2
//    DCOUT33     -->   VCC        P2  -->   SW3
//                                 P3  -->   SW4
//                                 P4  -->   LED1
//                                 P5  -->   LED2
//                                 P6  -->   LED3
//                                 P7  -->   LED4
//    
//------------------------------------------------------------------------------
INCLUDE rtcu.inc
 
//  Output variables that can be configured via the configuration dialog
VAR_OUTPUT
  Connected     : BOOL; | Connected to the DS2408
  NotConnected   : BOOL; | NOT connected to the DS2408
END_VAR;
 
//------------------------------------------------------------------------------
// Special 1-Wire function to read the registers of a
// Maxim DS2408 - 1-Wire 8-Channel Addressable Switch
//
// INPUT
//    device   : INT (default 1 (1st.))
//       device number withing the family is handling multiple DS2408 on same net
//
// OUTPUT
//    P     : ARRAY[0..7] OF BOOL
//             PIO Logic State
//    PL    : ARRAY[0..7] OF BOOL
//             PIO Output Latch State Register
//    AL    : ARRAY[0..7] OF BOOL
//             PIO Activity Latch State Register
//    SM    : ARRAY[0..7] OF BOOL
//             Conditional Search Channel Selection Mask
//    SP    : ARRAY[0..7] OF BOOL
//             Conditional Search Channel Polarity Selection
//    PLS   : BOOL  
//             Pin or Activity Latch Select
//    CT    : BOOL
//             Conditional Search Logical Term
//    ROS   : BOOL    
//             RSTZ Pin Mode Control
//    PORL  : BOOL    
//             Power-On Reset Latch
//    VCCP  : BOOL
//             VCC Power Status
//    ready : BOOL  
//             Last update successful
//
//------------------------------------------------------------------------------
FUNCTION_BLOCK owDS2408;
VAR_INPUT
  device   : INT    := 1;       // use device found with owSearchX()
END_VAR;
VAR_OUTPUT
  P       : ARRAY[0..7] OF BOOL; // PIO Logic State
  PL       : ARRAY[0..7] OF BOOL; // PIO Output Latch State Register
  AL       : ARRAY[0..7] OF BOOL; // PIO Activity Latch State Register
  SM       : ARRAY[0..7] OF BOOL; // Conditional Search Channel Selection Mask
  SP       : ARRAY[0..7] OF BOOL; // Conditional Search Channel Polarity Selection
  PLS     : BOOL   := FALSE;     // Pin or Activity Latch Select
  CT       : BOOL   := FALSE;     // Conditional Search Logical Term
  ROS     : BOOL   := FALSE;     // RSTZ Pin Mode Control
  PORL     : BOOL   := FALSE;     // Power-On Reset Latch
  VCCP     : BOOL   := FALSE;     // VCC Power Status
  ready   : BOOL   := FALSE;     // Last update successful
END_VAR;
VAR
  regs     : ARRAY[16#88..16#8F] OF SINT; // Register map
  crc     : INT;               // inverted crc16 all data sent and received.
  rc       : INT;
  i       : SINT;
END_VAR;
ready := FALSE;
 
// RST -> PD -> Select
rc := owAccess(family := 16#29, device := device);
IF rc <> 0 THEN
  DebugFmt(message := "owDS2408 : Failed to access device (\1)", v1 := rc);
  RETURN;
END_IF;
 
// RPR - Command "Read PIO Registers"
owWrite(data := 16#F0);
// TA - Target address
owWrite(data := 16#88); // TA1 (T7:T0)
owWrite(data := 16#00); // TA2 (T15:T8)
owReadData(data := ADDR(regs), size := SIZEOF(regs));
owReadData(data := ADDR(crc),  size := SIZEOF(crc));
owRelease();
 
// Validate received data against received CRC16                            
IF NOT (crcCalculate(
     buffer     := ADDR(regs),
     length     := SIZEOF(regs),
     order       := 16,
     polynom     := 16#0000_8005, // X^16+X^15+X^2+1
     preset     := 16#0000_66CC, // the CRC16 of RPR + TA using same polynom
     direct     := TRUE,  
     finalxor   := NOT (crc),     // check against received inverted crc
     reverseData := TRUE,  
     reverseCRC := TRUE  
  ) = 0) THEN
  DebugMsg(message := "owDS2408 : Failed to read register (CRC error)");
  RETURN;
END_IF;
 
// Map register values to output values
FOR i := 0 TO 7 DO
  P[i] := (regs[16#88] AND shl8(in := 1, n := i))  <> 0;
END_FOR;
FOR i := 0 TO 7 DO
  PL[i] := (regs[16#89] AND shl8(in := 1, n := i)) <> 0;
END_FOR;
FOR i := 0 TO 7 DO
  AL[i] := (regs[16#8A] AND shl8(in := 1, n := i)) <> 0;
END_FOR;
FOR i := 0 TO 7 DO
  SM[i] := (regs[16#8B] AND shl8(in := 1, n := i)) <> 0;
END_FOR;
FOR i := 0 TO 7 DO
  SP[i] := (regs[16#8C] AND shl8(in := 1, n := i)) <> 0;
END_FOR;
 
PLS   := (regs[16#8D] AND 16#01) <> 0;
CT   := (regs[16#8D] AND 16#02) <> 0;
ROS   := (regs[16#8D] AND 16#04) <> 0;
PORL := (regs[16#8D] AND 16#08) <> 0;
VCCP := (regs[16#8D] AND 16#80) <> 0;
 
ready := TRUE; // all data received successful
END_FUNCTION_BLOCK;
 
//------------------------------------------------------------------------------
// Special 1-Wire function to set the Control/Status Register.
// This will also clear the power-on reset latch (PORL) status.
//
// INPUTS
//    device   : INT (default 1 (1st.))
//       device number withing the family is handling multiple DS2408 on same net
//    PLS   : BOOL  
//             Pin or Activity Latch Select configuration
//    CT    : BOOL
//             Conditional Search Logical Term configuration
//    ROS   : BOOL    
//             RSTZ Pin Mode Control configuration
//------------------------------------------------------------------------------
FUNCTION owDS2408Cfg;
VAR_INPUT
  device   : INT   := 1;
  PLS     : BOOL   := FALSE;   // Pin or Activity Latch Select
  CT       : BOOL   := FALSE;   // Conditional Search Logical Term
  ROS     : BOOL   := FALSE;   // RSTZ Pin Mode Control
END_VAR;
 
VAR
  reg      : SINT   := 16#00;
  val      : SINT   := 16#00;
  rc       : INT;
END_VAR;
 
IF PLS THEN reg := reg OR 16#01; END_IF;
IF CT THEN reg := reg OR 16#02; END_IF;
IF ROS THEN reg := reg OR 16#04; END_IF;
 
// RST -> PD -> Select
rc := owAccess(family := 16#29, device := device);
IF rc <> 0 THEN
  DebugFmt(message := "owDS2408Cfg : Failed to access device (\1)", v1 := rc);
  RETURN;
END_IF;
 
owWrite(data := 16#CC);
owWrite(data := 16#8D);
owWrite(data := 16#00);
owWrite(data := reg);
owRelease();
 
rc := owAccess(family := 16#29, device := device);
IF rc <> 0 THEN
  DebugFmt(message := "owDS2408Cfg (verify) : Failed to access device (\1)",
          v1 := rc);
  RETURN;
END_IF;
 
owWrite(data := 16#F0); // read reg
owWrite(data := 16#8D);
owWrite(data := 16#00);
owRead(data := val);
owRelease();
 
IF (val AND 16#0007) <> reg THEN
  DebugFmt(message := "owDS2408Cfg (validate) : Failed (\1 <> \2)",
          v1 := (val AND 16#0007), v2 := (reg AND 16#00FF));
END_IF;
END_FUNCTION;
 
//------------------------------------------------------------------------------
// Special 1-Wire function to reset the PIO Activity Latch State Register
//
// INPUTS
//    device   : INT (default 1 (1st.))
//       device number withing the family is handling multiple DS2408 on same net
//------------------------------------------------------------------------------
FUNCTION owDS2408ResetAL : BOOL;
VAR_INPUT
  device   : INT := 1;
END_VAR;
 
VAR
  ack      : SINT;
  rc       : INT;
END_VAR;
 
rc := owAccess(family := 16#29, device := device);
IF rc <> 0 THEN
  DebugFmt(message := "owDS2408ResetAL : Failed to access device (\1)",
          v1 := rc);
  RETURN;
END_IF;
 
owWrite(data := 16#C3);
owRead(data := ack);
owRelease();
 
IF (ack AND 16#00FF) <> 16#00AA THEN
  DebugFmt(message := "owDS2408ResetAL : Failed to reset latch (ack = \1)",
          v1 := (ack AND 16#00FF));
  RETURN;
END_IF;
owDS2408ResetAL := TRUE;
END_FUNCTION;
 
//------------------------------------------------------------------------------
// Special 1-Wire function to set the PIO pins state.
//
// output pin status will be ignored when using pins as inputs.
//
// INPUTS
//    device   : INT (default 1 (1st.))
//       device number withing the family is handling multiple DS2408 on same net
//
//    p0       : BOOL (default OFF)
//       pin 0 ON/OFF
//    p1       : BOOL (default OFF)
//       pin 1 ON/OFF
//    p2       : BOOL (default OFF)
//       pin 2 ON/OFF
//    p3       : BOOL (default OFF)
//       pin 3 ON/OFF
//    p4       : BOOL (default OFF)
//       pin 4 ON/OFF
//    p5       : BOOL (default OFF)
//       pin 5 ON/OFF
//    p6       : BOOL (default OFF)
//       pin 6 ON/OFF
//    p7       : BOOL (default OFF)  
//       pin 7 ON/OFF
//------------------------------------------------------------------------------
FUNCTION owDS2408SetOutput;
VAR_INPUT
  device   : INT    := 1;
  p0       : BOOL   := OFF;
  p1       : BOOL   := OFF;
  p2       : BOOL   := OFF;
  p3       : BOOL   := OFF;
  p4       : BOOL   := OFF;
  p5       : BOOL   := OFF;
  p6       : BOOL   := OFF;
  p7       : BOOL   := OFF;  
END_VAR;
 
VAR
  mask     : SINT := 0; // the pin stat after the update
  ack      : SINT;
  rc       : INT;
  i        : SINT;
  status   : SINT;
END_VAR;
 
IF p0 THEN mask := mask OR 16#01; END_IF;
IF p1 THEN mask := mask OR 16#02; END_IF;
IF p2 THEN mask := mask OR 16#04; END_IF;
IF p3 THEN mask := mask OR 16#08; END_IF;
IF p4 THEN mask := mask OR 16#10; END_IF;
IF p5 THEN mask := mask OR 16#20; END_IF;
IF p6 THEN mask := mask OR 16#40; END_IF;
IF p7 THEN mask := mask OR 16#80; END_IF;
 
rc := owAccess(family := 16#29, device := device);
IF rc <> 0 THEN
  DebugFmt(message := "owDS2408SetOutput : Failed to access device (\1)", v1 := rc);
  RETURN;
END_IF;
 
owWrite(data := 16#5A);
owWrite(data := mask);
owWrite(data := NOT(mask));
owRead(data := ack);
owRead(data := status);
owRelease();
 
IF (ack AND 16#00FF) <> 16#00AA THEN
  DebugFmt(message := "owDS2408SetOutput : Failed to set new pin state (reply \1)",
          v1 := (ack AND 16#00FF));
END_IF;
END_FUNCTION;

 

 

//-----------------------------------------------------------------------------
// Application to run
//    Monitor the state of the DS2408 inputs (pin 0-3), and maps it to
//    the outputs (pin 4-7).
//-----------------------------------------------------------------------------
PROGRAM DS2408;
VAR
  DS2408   : owDS2408;
  id       : STRING;  
  cnt      : INT;
  i        : INT;
  upd      : BOOL;
END_VAR;
 
// Enable/Disable 3.3VDC output to supply external LEDs
boardDCOut(enable:=ON);
 
BEGIN
  IF connected THEN
    Sleep(delay := 500); // allow DS2408 to detect changes on inputs
    DS2408(device := 1);
  END_IF;
  IF DS2408.ready THEN
    owDS2408ResetAL(device := 1); // reset the latches as we got them
    upd := FALSE;
    IF DS2408.porl THEN
        DebugMsg(Message := "Power-On Reset detected.");
        owDS2408Cfg(device := 1, ros := ON);
        upd := TRUE;
    ELSE
        FOR i := 0 TO 3 DO
          IF DS2408.al[i] THEN
              DebugFmt(message := "DS2408 : PIN \1 = \2",
                      v1 := i, v2 := SINT(DS2408.p[i]));
              upd := TRUE;
          END_IF;
        END_FOR;
    END_IF;
    IF upd THEN
        owDS2408SetOutput(
          device := 1,
          p4 := DS2408.p[0],
          p5 := DS2408.p[1],
          p6 := DS2408.p[2],
          p7 := DS2408.p[3]);
    END_IF;
  ELSE
    IF NOT (id = "") THEN
        DebugMsg(message := "Lost connection to DS2408 device 1 '" + id +"'");
        id := "";
    END_IF;
    cnt := owSearchX(first := 16#29, last := 16#29); // only search for DS2408 devices
    IF cnt > 0 THEN
        DebugFmt(message := "Found \1 DS2408 1-Wire devices.", v1 := cnt);
        id := owGetID(device := 1, family := 16#29);
        DebugFmt(message := "Using DS2408 1-Wire device = " + id);        
    ELSIF cnt < 0 THEN
        DebugMsg(message := "Failed to search for DS2408 1-Wire devices.");
    END_IF;
  END_IF;
  Connected    := (id <> "");
  NotConnected := NOT Connected;
END;
END_PROGRAM;