@ -1,35 +1,19 @@
/* Ian Fleet 2018
All files , software , schematics and designs are provided as - is with no warranty .
All files , software , schematics and designs are for experimental / hobby use .
Under no circumstances should any part be used for critical systems where safety ,
life or property depends upon it . You are responsible for all use .
You are free to use , modify , derive or otherwise extend for your own purposes
*/
// This example emulates a DS2413 device on an Arduino UNO
// note : physical DS2413 devices found in 2018 are often clones with
// a device code different to the Maxim datasheet
# include "Arduino.h"
# include "Arduino.h"
# include "OneWireSlave.h"
# include "OneWireSlave.h"
# include "comptime.h"
# include "comptime.h"
// This is the pin that will be used for one-wire data
// This is the pin that will be used for one-wire data
// On Arduino Uno, you can use pin 2 or pin 3
// On Arduino Uno, you can use pin 2 or pin 3
Pin oneWireData ( 2 ) ;
Pin oneWireData ( 2 ) ; // PB2 only attiny85 pin with rising/falling interrupts
//Pin led(0);
Pin led ( 13 ) ; // builtin led
// This sample emulates a DS2413 device , so we start by defining the available commands
// This sample emulates a DS2413 device , so we start by defining the available commands
const byte DS2413_FAMILY_ID = 0x3A ; // Maxim DS2413 device code
const byte DS2413_FAMILY_ID = 0x3A ; // Maxim DS2413 device code
const byte CLONE_FAMILY_ID = 0x85 ; // Clone device code
const byte CLONE_FAMILY_ID = 0x85 ; // Chinese clone device code
const byte DS2413_ACCESS_READ = 0xF5 ;
const byte DS2413_ACCESS_READ = 0xF5 ;
const byte DS2413_ACCESS_WRITE = 0x5A ;
const byte DS2413_ACCESS_WRITE = 0x5A ;
const byte DS2413_ACK_SUCCESS = 0xAA ;
const byte DS2413_ACK_SUCCESS = 0xAA ;
@ -39,11 +23,11 @@ const byte owROM[7] = { DS2413_FAMILY_ID, SERIAL_NUMBER};
// will be calculated in begin:---------------^^^^
// will be calculated in begin:---------------^^^^
// or use fixed id - make sure it doesn't conflict with another device
// or use fixed id - make sure it doesn't conflict with another device
//const byte owROM[7] = { 0x3A, 0x00, 0x00, 0x00 , 0x00, 0x11, 0x22 };
//const byte owROM[7] = { 0x3A, 0x00, 0x55, 0xAA , 0x00, 0x11, 0x22 };
# define PIOA 4 // DS2413 PIO PINS on the UNO
# define PIOA 3 // (pin 3)
# define PIOB 5 //
# define PIOB 4 // (pin 4)
uint8_t latch = 0 ;
uint8_t latch = 0 ;
uint8_t statusbyte1 = 0 ;
uint8_t statusbyte1 = 0 ;
@ -55,13 +39,11 @@ enum DeviceState
DS_WaitingCommand ,
DS_WaitingCommand ,
DS_WaitingStatus1 ,
DS_WaitingStatus1 ,
DS_WaitingStatus2 ,
DS_WaitingStatus2 ,
} ;
} ;
volatile DeviceState state = DS_WaitingReset ;
volatile DeviceState state = DS_WaitingReset ;
// scratchpad
// scratchpad
volatile byte scratchpad [ 2 ] ;
volatile byte scratchpad [ 2 ] ;
volatile byte response [ 2 ] ;
volatile byte response [ 2 ] ;
@ -72,21 +54,19 @@ void owReceive(OneWireSlave::ReceiveEvent evt, byte data);
void setup ( )
void setup ( )
{
{
led . outputMode ( ) ;
// led.outputMode();
// led.writeLow();
Serial . begin ( 115200 ) ;
// OSCCAL = 85;
// Setup the OneWire library
// Setup the OneWire library
OWSlave . setReceiveCallback ( & owReceive ) ;
OWSlave . setReceiveCallback ( & owReceive ) ;
OWSlave . begin ( owROM , oneWireData . getPinNumber ( ) ) ;
OWSlave . begin ( owROM , oneWireData . getPinNumber ( ) ) ;
}
}
//////////////////////////////////////////
//////////////////////////////////////////
void loop ( )
void loop ( )
{
{
delay ( 1000 ) ;
delay ( 10 ) ;
cli ( ) ; //disable interrupts
cli ( ) ; //disable interrupts
// Be sure to not block interrupts for too long, OneWire timing is very tight for some operations. 1 or 2 microseconds (yes, microseconds, not milliseconds) can be too much depending on your master controller, but then it's equally unlikely that you block exactly at the moment where it matters.
// Be sure to not block interrupts for too long, OneWire timing is very tight for some operations. 1 or 2 microseconds (yes, microseconds, not milliseconds) can be too much depending on your master controller, but then it's equally unlikely that you block exactly at the moment where it matters.
@ -94,9 +74,6 @@ void loop()
sei ( ) ; //enable interrupts
sei ( ) ; //enable interrupts
led . writeLow ( ) ; // flash the led
delay ( 1000 ) ;
led . writeHigh ( ) ;
}
}
//////////////////////////////////////////
//////////////////////////////////////////
@ -110,24 +87,27 @@ static uint8_t getstatus() {
uint8_t x = ( ~ c ) < < 4 ;
uint8_t x = ( ~ c ) < < 4 ;
return x + c ;
return x + c ;
}
}
//////////////////////////////////////////
//////////////////////////////////////////
static void port ( int PIO , bool stat ) {
static void port ( int led , bool stat ) {
if ( stat ) {
if ( stat ) {
digitalWrite ( PIO , HIGH ) ;
digitalWrite ( led , HIGH ) ;
pinMode ( PIO , INPUT ) ;
pinMode ( led , INPUT ) ;
} else {
} else {
pinMode ( PIO , OUTPUT ) ;
pinMode ( led , OUTPUT ) ;
digitalWrite ( PIO , LOW ) ;
digitalWrite ( led , LOW ) ;
}
}
}
}
//////////////////////////////////////////
//////////////////////////////////////////
static void set ( uint8_t val ) {
static void set ( uint8_t val ) {
latch = val ;
latch = val ;
port ( PIOA , latch & 1 ) ;
port ( PIOA , latch & 1 ) ;
port ( PIOB , latch & 2 ) ;
port ( PIOB , latch & 2 ) ;
// TODO store latch value for recovery at startup
//eeprom_write_byte((uint8_t*)10, (unsigned char)latch);
}
}
//////////////////////////////////////////
//////////////////////////////////////////
@ -140,48 +120,49 @@ void owReceive(OneWireSlave::ReceiveEvent evt, byte data)
switch ( state )
switch ( state )
{
{
case DS_WaitingCommand :
case DS_WaitingCommand :
switch ( data ) // on command byte
switch ( data )
{
{
case DS2413_ACCESS_WRITE :
case DS2413_ACCESS_WRITE :
state = DS_WaitingStatus1 ; // wait for status byte 1
state = DS_WaitingStatus1 ;
//OWSlave.beginWriteBit(0, true); // send zeros as long as the conversion is not finished
break ;
break ;
case DS2413_ACCESS_READ :
case DS2413_ACCESS_READ :
state = DS_WaitingReset ;
state = DS_WaitingReset ;
scratchpad [ 0 ] = getstatus ( ) ; //return status in DS2413 format
scratchpad [ 0 ] = getstatus ( ) ;
OWSlave . beginWrite ( ( const byte * ) scratchpad , 1 , 0 ) ;
OWSlave . beginWrite ( ( const byte * ) scratchpad , 1 , 0 ) ;
break ;
default :
//TODO : report invalid commands
break ;
break ;
} // end switch (data) command
//case :
// break;
}
break ;
break ;
case DS_WaitingStatus1 :
case DS_WaitingStatus1 :
statusbyte1 = data ;
statusbyte1 = data ;
state = DS_WaitingStatus2 ; // wait for status byte 2
state = DS_WaitingStatus2 ;
break ;
break ;
case DS_WaitingStatus2 :
case DS_WaitingStatus2 :
statusbyte2 = data ;
statusbyte2 = data ;
if ( statusbyte1 ! = ~ statusbyte2 ) { // is DS2413 status data valid?
if ( statusbyte1 ! = ~ statusbyte2 ) {
set ( statusbyte1 ) ;
set ( statusbyte1 ) ;
response [ 0 ] = DS2413_ACK_SUCCESS ;
response [ 0 ] = DS2413_ACK_SUCCESS ;
} else {
} else {
response [ 0 ] = 0x11 ; // mark error - real DS2413 don't do this
response [ 0 ] = 0x11 ; // mark error
}
}
response [ 1 ] = getstatus ( ) ; // DS2413 expects an update of new status
response [ 1 ] = getstatus ( ) ;
OWSlave . beginWrite ( ( const byte * ) response , 2 , 0 ) ;
OWSlave . beginWrite ( ( const byte * ) response , 2 , 0 ) ;
state = DS_WaitingCommand ;
state = DS_WaitingCommand ;
break ;
break ;
} // end switch state
}
break ;
break ;
case OneWireSlave : : RE_Reset :
case OneWireSlave : : RE_Reset :
state = DS_WaitingCommand ;
state = DS_WaitingCommand ;
break ;
break ;
@ -189,5 +170,5 @@ void owReceive(OneWireSlave::ReceiveEvent evt, byte data)
case OneWireSlave : : RE_Error :
case OneWireSlave : : RE_Error :
state = DS_WaitingReset ;
state = DS_WaitingReset ;
break ;
break ;
} // end switch evt
}
}
}