Upload files to ''
Added support for attiny85 at 16mhz. Attiny85 fuses settings and OSCCAL calibration are required to meet the OneWire timing specifications
This commit is contained in:
parent
1a0eda0d59
commit
d698f10a08
51
LowLevel.h
51
LowLevel.h
@ -29,20 +29,38 @@
|
||||
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask))
|
||||
|
||||
#if defined (__AVR_ATtiny85__)
|
||||
#define CLEARINTERRUPT GIFR |= (1 << INTF0)
|
||||
#include "UserTimer.h" //ATtiny-support based on TinyCore1 Arduino-core for ATtiny at http://github.com/Coding-Badly/TinyCore1.git
|
||||
|
||||
/* Note : The attiny85 clock speed = 16mhz (fuses L 0xF1, H 0xDF. E oxFF
|
||||
OSCCAL VALUE must also be calibrated to 16mhz
|
||||
|
||||
*/
|
||||
#define CLEARINTERRUPT GIFR |= (1 << INTF0) | (1<<PCIF);
|
||||
#define USERTIMER_COMPA_vect TIMER1_COMPA_vect
|
||||
|
||||
__attribute__((always_inline)) static inline void UserTimer_Init( void )
|
||||
{
|
||||
UserTimer_SetToPowerup();
|
||||
UserTimer_SetWaveformGenerationMode(UserTimer_(CTC_OCR));
|
||||
TCCR1 = 0; //stop the timer
|
||||
TCNT1 = 0;
|
||||
//GTCCR |= (1<<PSR1); //reset the prescaler
|
||||
TIMSK = 0; // clear timer interrupts enable
|
||||
}
|
||||
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
|
||||
__attribute__((always_inline)) static inline void UserTimer_Run(int skipTicks)
|
||||
{
|
||||
UserTimer_SetCount(0);
|
||||
UserTimer_SetOutputCompareMatchAndClear(skipTicks);
|
||||
UserTimer_ClockSelect(UserTimer_(Prescale_Value_64));
|
||||
|
||||
TCNT1 = 0; //zero the timer
|
||||
GTCCR |= (1 << PSR1); //reset the prescaler
|
||||
OCR1A = skipTicks; //set the compare value
|
||||
TCCR1 |= (1 << CTC1) | (0 << CS13) | (1 << CS12) | (1 << CS11) | (0 << CS10);//32 prescaler
|
||||
//TCCR1 |= (1 << CTC1) | (0 << CS13) | (1 << CS12) | (0 << CS11) | (0 << CS10);//8 prescaler
|
||||
TIMSK |= (1 << OCIE1A); //interrupt on Compare Match A
|
||||
}
|
||||
#define UserTimer_Stop() UserTimer_ClockSelect(UserTimer_(Stopped))
|
||||
|
||||
__attribute__((always_inline)) static inline void UserTimer_Stop()
|
||||
{
|
||||
TIMSK = 0; //&= ~(1 << OCIE1A);// clear timer interrupt enable
|
||||
TCCR1 = 0;
|
||||
}
|
||||
|
||||
|
||||
#elif defined (__AVR_ATmega328P__)
|
||||
#define CLEARINTERRUPT EIFR |= (1 << INTF0)
|
||||
@ -52,8 +70,7 @@ __attribute__((always_inline)) static inline void UserTimer_Init( void )
|
||||
{
|
||||
TCCR1A = 0;
|
||||
TCCR1B = 0;
|
||||
// enable timer compare interrupt
|
||||
TIMSK1 |= (1 << OCIE1A);
|
||||
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
|
||||
}
|
||||
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
|
||||
{
|
||||
@ -112,6 +129,7 @@ __attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
|
||||
#error "Please define I/O register types here"
|
||||
#endif
|
||||
|
||||
|
||||
class Pin
|
||||
{
|
||||
private:
|
||||
@ -133,13 +151,6 @@ class Pin
|
||||
pinNumber_ = pin;
|
||||
mask_ = PIN_TO_BITMASK(pin);
|
||||
reg_ = PIN_TO_BASEREG(pin);
|
||||
int x = reg_;
|
||||
Serial.print(" Pin:");
|
||||
Serial.print(pin);
|
||||
Serial.print(" mask:");
|
||||
Serial.print(mask_);
|
||||
Serial.print(" reg:");
|
||||
Serial.println(x);
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
@ -176,12 +187,10 @@ class Pin
|
||||
|
||||
inline void attachInterrupt(void (*handler)(), int mode)
|
||||
{
|
||||
//Serial.print(" handler:");
|
||||
//int x = handler;
|
||||
//Serial.println(x);
|
||||
CLEARINTERRUPT; // clear any pending interrupt (we want to call the handler only for interrupts happening after it is attached)
|
||||
::attachInterrupt(interruptNumber_, handler, mode);
|
||||
}
|
||||
|
||||
inline void detachInterrupt() {
|
||||
::detachInterrupt(interruptNumber_);
|
||||
}
|
||||
|
@ -11,19 +11,40 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned long ResetMinDuration = 480;
|
||||
const unsigned long ResetMaxDuration = 900;
|
||||
#if defined (__AVR_ATtiny85__)
|
||||
|
||||
const unsigned long PresenceWaitDuration = 15;
|
||||
const unsigned long PresenceDuration = 200;
|
||||
const unsigned long ResetMinDuration = 480; // min 480us / 484us measured
|
||||
const unsigned long ResetMaxDuration = 640; //
|
||||
|
||||
const unsigned long ReadBitSamplingTime = 25;
|
||||
const unsigned long PresenceWaitDuration = 35; // spec 15us to 60us / 40us measured
|
||||
|
||||
const unsigned long SendBitDuration = 35;
|
||||
const unsigned long PresenceDuration = 150; // spec 60us to 240us / 148us measured
|
||||
|
||||
const byte ReceiveCommand = (byte)-1;
|
||||
const unsigned long ReadBitSamplingTime = 15; // spec > 15us to 60us / 31us measured
|
||||
|
||||
void(*timerEvent)() = 0;
|
||||
// SendBitDuration varies the bus release time to indicate a "1"
|
||||
// measured total send bit duration is 63us versus 60us in the spec
|
||||
const unsigned long SendBitDuration = 20; // bus release time spec 15us / measured 19us
|
||||
|
||||
|
||||
#elif defined (__AVR_ATmega328P__)
|
||||
|
||||
const unsigned long ResetMinDuration = 480;
|
||||
const unsigned long ResetMaxDuration = 900;
|
||||
|
||||
const unsigned long PresenceWaitDuration = 15;
|
||||
|
||||
const unsigned long PresenceDuration = 200;
|
||||
|
||||
const unsigned long ReadBitSamplingTime = 25;
|
||||
|
||||
const unsigned long SendBitDuration = 35;
|
||||
|
||||
#endif
|
||||
|
||||
const byte ReceiveCommand = (byte) - 1;
|
||||
|
||||
void(*timerEvent)() = 0;
|
||||
}
|
||||
|
||||
OneWireSlave OWSlave;
|
||||
@ -79,7 +100,7 @@ ISR(USERTIMER_COMPA_vect) // timer1 interrupt
|
||||
void OneWireSlave::begin(const byte* rom, byte pinNumber)
|
||||
{
|
||||
pin_ = Pin(pinNumber);
|
||||
resetStart_ = (unsigned long)-1;
|
||||
resetStart_ = (unsigned long) - 1;
|
||||
lastReset_ = 0;
|
||||
|
||||
memcpy(rom_, rom, 7);
|
||||
@ -143,7 +164,7 @@ void OneWireSlave::beginWrite(const byte* bytes, short numBytes, void(*complete)
|
||||
|
||||
void OneWireSlave::endWrite_(bool error, bool resetInterrupts)
|
||||
{
|
||||
if(resetInterrupts)
|
||||
if (resetInterrupts)
|
||||
beginWaitReset_();
|
||||
|
||||
if (sendingClientBytes_)
|
||||
@ -231,16 +252,33 @@ byte OneWireSlave::crc8(const byte* data, short numBytes)
|
||||
return crc;
|
||||
}
|
||||
|
||||
#if defined (__AVR_ATtiny85__)
|
||||
|
||||
void OneWireSlave::setTimerEvent_(short delayMicroSeconds, void(*handler)())
|
||||
{
|
||||
delayMicroSeconds -= 8; // remove overhead (tuned on attiny85, values 0 - 10 work ok)
|
||||
|
||||
short skipTicks = delayMicroSeconds / 2; // 16mhz clock, prescaler = 32
|
||||
if (skipTicks < 1) skipTicks = 1;
|
||||
timerEvent = handler;
|
||||
UserTimer_Run(skipTicks);
|
||||
}
|
||||
|
||||
#elif defined (__AVR_ATmega328P__)
|
||||
|
||||
void OneWireSlave::setTimerEvent_(short delayMicroSeconds, void(*handler)())
|
||||
{
|
||||
delayMicroSeconds -= 10; // remove overhead (tuned on Arduino Uno)
|
||||
|
||||
// prescaler 64
|
||||
short skipTicks = (delayMicroSeconds - 3) / 4; // round the micro seconds delay to a number of ticks to skip (4us per tick, so 4us must skip 0 tick, 8us must skip 1 tick, etc.)
|
||||
if (skipTicks < 1) skipTicks = 1;
|
||||
timerEvent = handler;
|
||||
UserTimer_Run(skipTicks);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void OneWireSlave::disableTimer_()
|
||||
{
|
||||
UserTimer_Stop();
|
||||
@ -289,7 +327,7 @@ void OneWireSlave::beginResetDetectionSendZero_()
|
||||
void OneWireSlave::cancelResetDetection_()
|
||||
{
|
||||
disableTimer_();
|
||||
resetStart_ = (unsigned long)-1;
|
||||
resetStart_ = (unsigned long) - 1;
|
||||
}
|
||||
|
||||
void OneWireSlave::resetCheck_()
|
||||
@ -386,9 +424,11 @@ void OneWireSlave::beginWaitReset_()
|
||||
disableTimer_();
|
||||
pin_.inputMode();
|
||||
pin_.attachInterrupt(&OneWireSlave::waitReset_, CHANGE);
|
||||
resetStart_ = (unsigned int)-1;
|
||||
//resetStart_ = (unsigned int) - 1;
|
||||
resetStart_ = (unsigned long) - 1;
|
||||
}
|
||||
|
||||
|
||||
void OneWireSlave::waitReset_()
|
||||
{
|
||||
onEnterInterrupt_();
|
||||
@ -396,22 +436,28 @@ void OneWireSlave::waitReset_()
|
||||
unsigned long now = micros();
|
||||
if (state)
|
||||
{
|
||||
if (resetStart_ == (unsigned int)-1)
|
||||
if (resetStart_ == (unsigned long) - 1)
|
||||
{
|
||||
onLeaveInterrupt_();
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long resetDuration = now - resetStart_;
|
||||
resetStart_ = (unsigned int)-1;
|
||||
static unsigned long resetDuration = now - resetStart_;
|
||||
//resetStart_ = (unsigned int) - 1;
|
||||
resetStart_ = (unsigned long) - 1;
|
||||
if (resetDuration >= ResetMinDuration)
|
||||
{
|
||||
if (resetDuration > ResetMaxDuration)
|
||||
{
|
||||
ERROR("Reset too long");
|
||||
onLeaveInterrupt_();
|
||||
return;
|
||||
}
|
||||
|
||||
// The following test has been removed because of a bug which causes the value of
|
||||
// resetduration to exceed ResetMaxDuration intermittently. This happens
|
||||
// only on the attiny platform - possibly due to the implementation of
|
||||
// micros() in the attiny core
|
||||
|
||||
// if (resetDuration > ResetMaxDuration)
|
||||
// {
|
||||
// ERROR("Reset too long");
|
||||
// onLeaveInterrupt_();
|
||||
// return;
|
||||
// }
|
||||
|
||||
lastReset_ = now;
|
||||
pin_.detachInterrupt();
|
||||
@ -420,6 +466,9 @@ void OneWireSlave::waitReset_()
|
||||
endWrite_(true, false);
|
||||
if (clientReceiveCallback_ != 0)
|
||||
clientReceiveCallback_(RE_Reset, 0);
|
||||
} else
|
||||
{
|
||||
//ERROR("Reset too short");
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -614,7 +663,7 @@ void OneWireSlave::searchRomOnBitReceived_(bool bit, bool error)
|
||||
}
|
||||
}
|
||||
|
||||
void OneWireSlave::beginWriteBytes_(const byte* data, short numBytes, void(*complete)(bool error))
|
||||
void OneWireSlave::beginWriteBytes_(const byte * data, short numBytes, void(*complete)(bool error))
|
||||
{
|
||||
sendBuffer_ = data;
|
||||
bufferLength_ = numBytes;
|
||||
@ -661,7 +710,7 @@ void OneWireSlave::bitSent_(bool error)
|
||||
beginSendBit_(bit, &OneWireSlave::bitSent_);
|
||||
}
|
||||
|
||||
void OneWireSlave::beginReceiveBytes_(byte* buffer, short numBytes, void(*complete)(bool error))
|
||||
void OneWireSlave::beginReceiveBytes_(byte * buffer, short numBytes, void(*complete)(bool error))
|
||||
{
|
||||
recvBuffer_ = buffer;
|
||||
bufferLength_ = numBytes;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
class OneWireSlave
|
||||
{
|
||||
public:
|
||||
public:
|
||||
enum ReceiveEvent
|
||||
{
|
||||
RE_Reset, //!< The master has sent a general reset
|
||||
@ -21,13 +21,19 @@ public:
|
||||
void end();
|
||||
|
||||
//! Sets (or replaces) a function to be called when something is received. The callback is executed from interrupts and should be as short as possible. Failure to return quickly can prevent the library from correctly reading the next byte.
|
||||
void setReceiveCallback(void(*callback)(ReceiveEvent evt, byte data)) { clientReceiveCallback_ = callback; }
|
||||
void setReceiveCallback(void(*callback)(ReceiveEvent evt, byte data)) {
|
||||
clientReceiveCallback_ = callback;
|
||||
}
|
||||
|
||||
//! Sets (or replaces) a function to be called when a bit is received. The byte reception callback is called after that if the received bit was the last of a byte. The callback is executed from interrupts and should be as short as possible. Failure to return quickly can prevent the library from correctly reading the next bit.
|
||||
void setReceiveBitCallback(void(*callback)(bool bit)) { clientReceiveBitCallback_ = callback; }
|
||||
void setReceiveBitCallback(void(*callback)(bool bit)) {
|
||||
clientReceiveBitCallback_ = callback;
|
||||
}
|
||||
|
||||
//! Sets (or replaces) a function to be called when the library has a message to log, if the functionality is enabled in OneWireSlave.cpp. This is for debugging purposes.
|
||||
void setLogCallback(void(*callback)(const char* message)) { logCallback_ = callback; }
|
||||
void setLogCallback(void(*callback)(const char* message)) {
|
||||
logCallback_ = callback;
|
||||
}
|
||||
|
||||
//! Writes the specified bytes synchronously. This function blocks until the write operation has finished. Do not call from an interrupt handler! Returns true in case of success, false if an error occurs.
|
||||
bool write(const byte* bytes, short numBytes);
|
||||
@ -49,7 +55,7 @@ public:
|
||||
|
||||
static byte crc8(const byte* data, short numBytes);
|
||||
|
||||
private:
|
||||
private:
|
||||
static void setTimerEvent_(short delayMicroSeconds, void(*handler)());
|
||||
static void disableTimer_();
|
||||
|
||||
@ -100,7 +106,7 @@ private:
|
||||
static void endSendBitZero_();
|
||||
static void resetCheck_();
|
||||
|
||||
private:
|
||||
private:
|
||||
static byte rom_[8];
|
||||
static byte scratchpad_[8];
|
||||
static Pin pin_;
|
||||
|
Loading…
Reference in New Issue
Block a user