#include "Arduino.h" #include "OneWireSlave.h" #include "comptime.h" // This is the pin that will be used for one-wire data // On Arduino Uno, you can use pin 2 or pin 3 Pin oneWireData(2); // PB2 only attiny85 pin with rising/falling interrupts //Pin led(0); // 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 CLONE_FAMILY_ID = 0x85; // Chinese clone device code const byte DS2413_ACCESS_READ = 0xF5; const byte DS2413_ACCESS_WRITE = 0x5A; const byte DS2413_ACK_SUCCESS = 0xAA; // generate unique id const byte owROM[7] = { DS2413_FAMILY_ID, SERIAL_NUMBER}; // will be calculated in begin:---------------^^^^ // or use fixed id - make sure it doesn't conflict with another device //const byte owROM[7] = { 0x3A, 0x00, 0x55, 0xAA, 0x00, 0x11, 0x22 }; #define PIOA 3 // (pin 3) #define PIOB 4 // (pin 4) uint8_t latch = 0; uint8_t statusbyte1 = 0; uint8_t statusbyte2 = 0; enum DeviceState { DS_WaitingReset, DS_WaitingCommand, DS_WaitingStatus1, DS_WaitingStatus2, }; volatile DeviceState state = DS_WaitingReset; // scratchpad volatile byte scratchpad[2]; volatile byte response[2]; // This function will be called each time the OneWire library has an event to notify (reset, error, byte received) void owReceive(OneWireSlave::ReceiveEvent evt, byte data); ////////////////////////////////////////// void setup() { // led.outputMode(); // led.writeLow(); // OSCCAL = 85; // Setup the OneWire library OWSlave.setReceiveCallback(&owReceive); OWSlave.begin(owROM, oneWireData.getPinNumber()); } ////////////////////////////////////////// void loop() { delay(10); 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. // This can be mitigated by using error checking and retry in your high-level communication protocol. A good thing to do anyway. sei();//enable interrupts } ////////////////////////////////////////// static uint8_t getstatus() { uint8_t c = 0; if (latch & 0x01) c |= 0x02; if (digitalRead(PIOA)) c |= 0x01; if (latch & 0x02) c |= 0x08; if (digitalRead(PIOB)) c |= 0x04; uint8_t x = (~c) << 4; return x + c; } ////////////////////////////////////////// static void port(int led, bool stat) { if (stat) { digitalWrite(led, HIGH); pinMode(led, INPUT); } else { pinMode(led, OUTPUT); digitalWrite(led, LOW); } } ////////////////////////////////////////// static void set(uint8_t val) { latch = val; port(PIOA, latch & 1); port(PIOB, latch & 2); //eeprom_write_byte((uint8_t*)10, (unsigned char)latch); } ////////////////////////////////////////// void owReceive(OneWireSlave::ReceiveEvent evt, byte data) { switch (evt) { case OneWireSlave::RE_Byte: switch (state) { case DS_WaitingCommand: switch (data) { case DS2413_ACCESS_WRITE: state = DS_WaitingStatus1; //OWSlave.beginWriteBit(0, true); // send zeros as long as the conversion is not finished break; case DS2413_ACCESS_READ: state = DS_WaitingReset; scratchpad[0] = getstatus(); OWSlave.beginWrite((const byte*)scratchpad, 1, 0); break; //case : // break; } break; case DS_WaitingStatus1: statusbyte1 = data; state = DS_WaitingStatus2; break; case DS_WaitingStatus2: statusbyte2 = data; if (statusbyte1 != ~statusbyte2) { set(statusbyte1); response[0] = DS2413_ACK_SUCCESS; } else { response[0] = 0x11; // mark error } response[1] = getstatus(); OWSlave.beginWrite((const byte*)response, 2, 0); state = DS_WaitingCommand; break; } break; case OneWireSlave::RE_Reset: state = DS_WaitingCommand; break; case OneWireSlave::RE_Error: state = DS_WaitingReset; break; } }