An experimental timer interrupt driven software based 1-Wire master interface that was created by Robert David Brinzer for a University of Glasgow Level 4 Electronic and Software Engineering Final Year project. This implementation requires mbed RTOS and does not use NOP waits. Perfect for programs that require multi-tasking. Includes the Read and Search network commands and can be easily extended to support new network and transport commands.
Interface/OneWire.cpp
- Committer:
- sroy
- Date:
- 2013-04-15
- Revision:
- 0:7c6dd6bc20e4
File content as of revision 0:7c6dd6bc20e4:
#include "OneWire.h" const OneWire_MicroInstruction OneWire::_OneWire_MicroProgram[10] = {&OneWire::_io_low,&OneWire::_io_high, &OneWire::_io_low,&OneWire::_io_high, &OneWire::_io_low,&OneWire::_io_high,&OneWire::_io_read, &OneWire::_io_low,&OneWire::_io_high,&OneWire::_io_read}; const unsigned short DEFAULT_TIMES[10] = {ONEWIRE_WRITE1LOW, ONEWIRE_TIMESLOT+ONEWIRE_RECOVER-ONEWIRE_WRITE1LOW+ONEWIRE_RECOVER, ONEWIRE_WRITE0LOW, ONEWIRE_TIMESLOT+ONEWIRE_RECOVER-ONEWIRE_WRITE0LOW+ONEWIRE_RECOVER, ONEWIRE_READLOW, ONEWIRE_READDURATION-ONEWIRE_READLOW-1, ONEWIRE_TIMESLOT-ONEWIRE_READDURATION-ONEWIRE_READLOW-1+ONEWIRE_RECOVER, ONEWIRE_TIMESLOT*8, ONEWIRE_PULSEHIGH+ONEWIRE_PULSELOW/2, ONEWIRE_TIMESLOT*8-(ONEWIRE_PULSEHIGH+ONEWIRE_PULSELOW/2)+ONEWIRE_RECOVER}; void OneWire::_nextmicroinst(){ if(_microinstn == 0){ _resumeinst(); }else{ _timer.attach_us(this, &OneWire::_nextmicroinst, timeing[_microinstc]); (this->*_OneWire_MicroProgram[_microinstc++])(); _microinstn-= 1; } } void OneWire::_resumeinst(){ unsigned char offset = _inststate & 0x0F; if(offset < 8){ if((execute.code>>offset) & 0x01) op_send1(); else op_send0(); _inststate+= 1; }else{ if(execute.inst == NULL) endInstruction(); else (*(execute.inst))(this); } } void OneWire::_nextinst(){ if(_instn > 0){ execute = (*_instruction).network; if(execute.inst == NULL) _inststate = 0x08; // skip network and transport command but allow reset else _inststate = 0x10; // send reset pulse readhandle = &OneWire::_presencedetect; op_reset(); }else{ error = SUCCESS; osSignalSet(_caller, 1); } } void OneWire::_presencedetect(OneWire * which, char bit){ if(bit) which->abort(NO_PRESENCE); // it is pointless to continue when there is no device attached } void OneWire::_ei_detect(){ if(detecthandle != NULL) (*detecthandle)(this); } // Private pin I/O methods void OneWire::_io_high(){ _pin = 1; } void OneWire::_io_low(){ _pin = 0; } void OneWire::_io_read(){ _pin.input(); (*readhandle)(this, _pin); _pin.output(); } // Public utility methods OneWire::OneWire(PinName pin) : _pin(pin), _detect(pin){ _pin.output(); _pin = 1; // turn on devices to allow them to start working _pin.mode(PullUp); _detect.mode(PullUp); _detect.fall(this, &OneWire::_ei_detect); timeing = DEFAULT_TIMES; detecthandle = NULL; } int OneWire::send(OneWire_Instruction * inst, unsigned char instnum){ _detect.fall(NULL); _instruction = inst; _instn = instnum; _nextinst(); _caller = Thread::gettid(); Thread::signal_wait(0); osSignalSet(_caller, 0); _detect.fall(this, &OneWire::_ei_detect); return error != SUCCESS; } void OneWire::endInstruction(){ if(_inststate>>4 && _instruction->transport.inst != NULL){ execute = _instruction->transport; _inststate = 0x00; _timer.attach_us(this, &OneWire::_resumeinst, 1); // MAKE TIMING CONFIGURABLE }else{ _instruction+= 1; _instn-= 1; _timer.attach_us(this, &OneWire::_nextinst, 1); // MAKE TIMING CONFIGURABLE } } // depricated, use at own risk void OneWire::repeatInstruction(){ execute = (*_instruction).network; _inststate = 0x10; // send reset pulse readhandle = &OneWire::_presencedetect; op_reset(); } void OneWire::abort(OneWire_Error err){ _timer.detach(); error = err; osSignalSet(_caller, 1); } // Public IO methods void OneWire::op_send1(){ _microinstn = 2; _microinstc = 0; _nextmicroinst(); } void OneWire::op_send0(){ _microinstn = 2; _microinstc = 2; _nextmicroinst(); } void OneWire::op_read(){ _microinstn = 3; _microinstc = 4; _nextmicroinst(); } void OneWire::op_reset(){ _microinstn = 3; _microinstc = 7; _nextmicroinst(); }