|
//------------------------------------------------------------------------------
// 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 a
// RTCU device.
//
// DS2408 External
//
// 1-Wire --> IO P0 --> SW1
// SGND --> GND P1 --> SW2
// 3.3V --> 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 send 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;
|