update OneWire lib

This commit is contained in:
MichaelDvP
2022-06-07 08:18:56 +02:00
parent 9524ec1317
commit a22783a3e4
4 changed files with 807 additions and 710 deletions

View File

@@ -1,8 +1,4 @@
/* /*
taken from:
https://github.com/arendst/Tasmota/blob/development/lib/lib_basic/OneWire-Stickbreaker/OneWire.cpp
modified for ems-esp old lib compatibility
Copyright (c) 2007, Jim Studt (original old version - many contributors since) Copyright (c) 2007, Jim Studt (original old version - many contributors since)
The latest version of this library may be found at: The latest version of this library may be found at:
@@ -36,17 +32,6 @@ private email about OneWire).
OneWire is now very mature code. No changes other than adding OneWire is now very mature code. No changes other than adding
definitions for newer hardware support are anticipated. definitions for newer hardware support are anticipated.
=======
Version 2.3.3 ESP32 Stickbreaker 06MAY2019
Add a #ifdef to isolate ESP32 mods
Version 2.3.1 ESP32 everslick 30APR2018
add IRAM_ATTR attribute to write_bit/read_bit to fix icache miss delay
https://github.com/espressif/arduino-esp32/issues/1335
Version 2.3 ESP32 stickbreaker 28DEC2017
adjust to use portENTER_CRITICAL(&mux) instead of noInterrupts();
adjust to use portEXIT_CRITICAL(&mux) instead of Interrupts();
Version 2.3: Version 2.3:
Unknown chip fallback mode, Roger Clark Unknown chip fallback mode, Roger Clark
Teensy-LC compatibility, Paul Stoffregen Teensy-LC compatibility, Paul Stoffregen
@@ -154,27 +139,18 @@ sample code bearing this copyright.
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
*/ */
#include <Arduino.h>
#include "OneWire.h" #include "OneWire.h"
#include "util/OneWire_direct_gpio.h"
#ifdef ESP32
#define t_noInterrupts() \
{ \
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; \
portENTER_CRITICAL(&mux)
#define t_interrupts() \
portEXIT_CRITICAL(&mux); \
}
#else
#define t_noInterrupts noInterrupts
#define t_interrupts interrupts
#endif
void OneWire::begin(uint8_t pin) { void OneWire::begin(uint8_t pin)
pinMode(pin, INPUT); {
bitmask = PIN_TO_BITMASK(pin); pinMode(pin, INPUT);
baseReg = PIN_TO_BASEREG(pin); bitmask = PIN_TO_BITMASK(pin);
baseReg = PIN_TO_BASEREG(pin);
#if ONEWIRE_SEARCH #if ONEWIRE_SEARCH
reset_search(); reset_search();
#endif #endif
} }
@@ -185,94 +161,84 @@ void OneWire::begin(uint8_t pin) {
// //
// Returns 1 if a device asserted a presence pulse, 0 otherwise. // Returns 1 if a device asserted a presence pulse, 0 otherwise.
// //
#ifdef ARDUINO_ARCH_ESP32
uint8_t IRAM_ATTR OneWire::reset(void)
#else
uint8_t OneWire::reset(void) uint8_t OneWire::reset(void)
#endif
{ {
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
volatile IO_REG_TYPE * reg IO_REG_BASE_ATTR = baseReg; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
uint8_t r; uint8_t r;
uint8_t retries = 125; uint8_t retries = 125;
t_noInterrupts();
DIRECT_MODE_INPUT(reg, mask);
t_interrupts();
// wait until the wire is high... just in case
do {
if (--retries == 0)
return 0;
delayMicroseconds(2);
} while (!DIRECT_READ(reg, mask));
t_noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(reg, mask); DIRECT_MODE_INPUT(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low interrupts();
delayMicroseconds(480); // wait until the wire is high... just in case
DIRECT_MODE_INPUT(reg, mask); // allow it to float do {
delayMicroseconds(70); if (--retries == 0) return 0;
r = !DIRECT_READ(reg, mask); delayMicroseconds(2);
t_interrupts(); } while ( !DIRECT_READ(reg, mask));
delayMicroseconds(410);
return r; noInterrupts();
DIRECT_WRITE_LOW(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
interrupts();
delayMicroseconds(480);
noInterrupts();
DIRECT_MODE_INPUT(reg, mask); // allow it to float
delayMicroseconds(70);
r = !DIRECT_READ(reg, mask);
interrupts();
delayMicroseconds(410);
return r;
} }
// //
// Write a bit. Port and bit is used to cut lookup time and provide // Write a bit. Port and bit is used to cut lookup time and provide
// more certain timing. // more certain timing.
// //
#ifdef ARDUINO_ARCH_ESP32 void OneWire::write_bit(uint8_t v)
void IRAM_ATTR OneWire::write_bit(uint8_t v)
#else
void OneWire::write_bit(uint8_t v)
#endif
{ {
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
volatile IO_REG_TYPE * reg IO_REG_BASE_ATTR = baseReg; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
if (v & 1) { if (v & 1) {
t_noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(reg, mask); DIRECT_WRITE_LOW(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low DIRECT_MODE_OUTPUT(reg, mask); // drive output low
delayMicroseconds(10); delayMicroseconds(10);
DIRECT_WRITE_HIGH(reg, mask); // drive output high DIRECT_WRITE_HIGH(reg, mask); // drive output high
t_interrupts(); interrupts();
delayMicroseconds(55); delayMicroseconds(55);
} else { } else {
t_noInterrupts(); noInterrupts();
DIRECT_WRITE_LOW(reg, mask); DIRECT_WRITE_LOW(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low DIRECT_MODE_OUTPUT(reg, mask); // drive output low
delayMicroseconds(65); delayMicroseconds(65);
DIRECT_WRITE_HIGH(reg, mask); // drive output high DIRECT_WRITE_HIGH(reg, mask); // drive output high
t_interrupts(); interrupts();
delayMicroseconds(5); delayMicroseconds(5);
} }
} }
// //
// Read a bit. Port and bit is used to cut lookup time and provide // Read a bit. Port and bit is used to cut lookup time and provide
// more certain timing. // more certain timing.
// //
#ifdef ARDUINO_ARCH_ESP32
uint8_t IRAM_ATTR OneWire::read_bit(void)
#else
uint8_t OneWire::read_bit(void) uint8_t OneWire::read_bit(void)
#endif
{ {
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
volatile IO_REG_TYPE * reg IO_REG_BASE_ATTR = baseReg; volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
uint8_t r; uint8_t r;
t_noInterrupts(); noInterrupts();
DIRECT_MODE_OUTPUT(reg, mask); DIRECT_MODE_OUTPUT(reg, mask);
DIRECT_WRITE_LOW(reg, mask); DIRECT_WRITE_LOW(reg, mask);
delayMicroseconds(3); delayMicroseconds(3);
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
delayMicroseconds(10); delayMicroseconds(10);
r = DIRECT_READ(reg, mask); r = DIRECT_READ(reg, mask);
t_interrupts(); interrupts();
delayMicroseconds(53); delayMicroseconds(53);
return r; return r;
} }
// //
@@ -286,25 +252,25 @@ void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
uint8_t bitMask; uint8_t bitMask;
for (bitMask = 0x01; bitMask; bitMask <<= 1) { for (bitMask = 0x01; bitMask; bitMask <<= 1) {
OneWire::write_bit((bitMask & v) ? 1 : 0); OneWire::write_bit( (bitMask & v)?1:0);
} }
if (!power) { if ( !power) {
t_noInterrupts(); noInterrupts();
DIRECT_MODE_INPUT(baseReg, bitmask); DIRECT_MODE_INPUT(baseReg, bitmask);
DIRECT_WRITE_LOW(baseReg, bitmask); DIRECT_WRITE_LOW(baseReg, bitmask);
t_interrupts(); interrupts();
} }
} }
void OneWire::write_bytes(const uint8_t * buf, uint16_t count, bool power /* = 0 */) { void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
for (uint16_t i = 0; i < count; i++) for (uint16_t i = 0 ; i < count ; i++)
write(buf[i]); write(buf[i]);
if (!power) { if (!power) {
t_noInterrupts(); noInterrupts();
DIRECT_MODE_INPUT(baseReg, bitmask); DIRECT_MODE_INPUT(baseReg, bitmask);
DIRECT_WRITE_LOW(baseReg, bitmask); DIRECT_WRITE_LOW(baseReg, bitmask);
t_interrupts(); interrupts();
} }
} }
// //
@@ -315,40 +281,41 @@ uint8_t OneWire::read() {
uint8_t r = 0; uint8_t r = 0;
for (bitMask = 0x01; bitMask; bitMask <<= 1) { for (bitMask = 0x01; bitMask; bitMask <<= 1) {
if (OneWire::read_bit()) if ( OneWire::read_bit()) r |= bitMask;
r |= bitMask;
} }
return r; return r;
} }
void OneWire::read_bytes(uint8_t * buf, uint16_t count) { void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
for (uint16_t i = 0; i < count; i++) for (uint16_t i = 0 ; i < count ; i++)
buf[i] = read(); buf[i] = read();
} }
// //
// Do a ROM select // Do a ROM select
// //
void OneWire::select(const uint8_t rom[8]) { void OneWire::select(const uint8_t rom[8])
{
uint8_t i; uint8_t i;
write(0x55); // Choose ROM write(0x55); // Choose ROM
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) write(rom[i]);
write(rom[i]);
} }
// //
// Do a ROM skip // Do a ROM skip
// //
void OneWire::skip() { void OneWire::skip()
write(0xCC); // Skip ROM {
write(0xCC); // Skip ROM
} }
void OneWire::depower() { void OneWire::depower()
t_noInterrupts(); {
DIRECT_MODE_INPUT(baseReg, bitmask); noInterrupts();
t_interrupts(); DIRECT_MODE_INPUT(baseReg, bitmask);
interrupts();
} }
#if ONEWIRE_SEARCH #if ONEWIRE_SEARCH
@@ -357,29 +324,30 @@ void OneWire::depower() {
// You need to use this function to start a search again from the beginning. // You need to use this function to start a search again from the beginning.
// You do not need to do it for the first search, though you could. // You do not need to do it for the first search, though you could.
// //
void OneWire::reset_search() { void OneWire::reset_search()
// reset the search state {
LastDiscrepancy = 0; // reset the search state
LastDeviceFlag = FALSE; LastDiscrepancy = 0;
LastFamilyDiscrepancy = 0; LastDeviceFlag = false;
for (int i = 7;; i--) { LastFamilyDiscrepancy = 0;
ROM_NO[i] = 0; for(int i = 7; ; i--) {
if (i == 0) ROM_NO[i] = 0;
break; if ( i == 0) break;
} }
} }
// Setup the search to find the device type 'family_code' on the next call // Setup the search to find the device type 'family_code' on the next call
// to search(*newAddr) if it is present. // to search(*newAddr) if it is present.
// //
void OneWire::target_search(uint8_t family_code) { void OneWire::target_search(uint8_t family_code)
// set the search state to find SearchFamily type devices {
ROM_NO[0] = family_code; // set the search state to find SearchFamily type devices
for (uint8_t i = 1; i < 8; i++) ROM_NO[0] = family_code;
ROM_NO[i] = 0; for (uint8_t i = 1; i < 8; i++)
LastDiscrepancy = 64; ROM_NO[i] = 0;
LastFamilyDiscrepancy = 0; LastDiscrepancy = 64;
LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0;
LastDeviceFlag = false;
} }
// //
@@ -398,116 +366,121 @@ void OneWire::target_search(uint8_t family_code) {
// Return TRUE : device found, ROM number in ROM_NO buffer // Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search // FALSE : device not found, end of search
// //
uint8_t OneWire::search(uint8_t * newAddr, bool search_mode /* = true */) { bool OneWire::search(uint8_t *newAddr, bool search_mode /* = true */)
uint8_t id_bit_number; {
uint8_t last_zero, rom_byte_number, search_result; uint8_t id_bit_number;
uint8_t id_bit, cmp_id_bit; uint8_t last_zero, rom_byte_number;
bool search_result;
uint8_t id_bit, cmp_id_bit;
unsigned char rom_byte_mask, search_direction; unsigned char rom_byte_mask, search_direction;
// initialize for search // initialize for search
id_bit_number = 1; id_bit_number = 1;
last_zero = 0; last_zero = 0;
rom_byte_number = 0; rom_byte_number = 0;
rom_byte_mask = 1; rom_byte_mask = 1;
search_result = 0; search_result = false;
// if the last call was not the last one // if the last call was not the last one
if (!LastDeviceFlag) { if (!LastDeviceFlag) {
// 1-Wire reset // 1-Wire reset
if (!reset()) { if (!reset()) {
// reset the search // reset the search
LastDiscrepancy = 0; LastDiscrepancy = 0;
LastDeviceFlag = FALSE; LastDeviceFlag = false;
LastFamilyDiscrepancy = 0; LastFamilyDiscrepancy = 0;
return FALSE; return false;
} }
// issue the search command
if (search_mode == true) {
write(0xF0); // NORMAL SEARCH
} else {
write(0xEC); // CONDITIONAL SEARCH
}
// loop to do the search // issue the search command
do { if (search_mode == true) {
// read a bit and its complement write(0xF0); // NORMAL SEARCH
id_bit = read_bit(); } else {
cmp_id_bit = read_bit(); write(0xEC); // CONDITIONAL SEARCH
}
// check for no devices on 1-wire // loop to do the search
if ((id_bit == 1) && (cmp_id_bit == 1)) do
break; {
else { // read a bit and its complement
// all devices coupled have 0 or 1 id_bit = read_bit();
if (id_bit != cmp_id_bit) cmp_id_bit = read_bit();
search_direction = id_bit; // bit write value for search
else {
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < LastDiscrepancy)
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
else
// if equal to last pick 1, if not then pick 0
search_direction = (id_bit_number == LastDiscrepancy);
// if 0 was picked then record its position in LastZero // check for no devices on 1-wire
if (search_direction == 0) { if ((id_bit == 1) && (cmp_id_bit == 1)) {
last_zero = id_bit_number; break;
} else {
// all devices coupled have 0 or 1
if (id_bit != cmp_id_bit) {
search_direction = id_bit; // bit write value for search
} else {
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < LastDiscrepancy) {
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
} else {
// if equal to last pick 1, if not then pick 0
search_direction = (id_bit_number == LastDiscrepancy);
}
// if 0 was picked then record its position in LastZero
if (search_direction == 0) {
last_zero = id_bit_number;
// check for Last discrepancy in family // check for Last discrepancy in family
if (last_zero < 9) if (last_zero < 9)
LastFamilyDiscrepancy = last_zero; LastFamilyDiscrepancy = last_zero;
} }
}
// set or clear the bit in the ROM byte rom_byte_number
// with mask rom_byte_mask
if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask;
else
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
// serial number search direction write bit
write_bit(search_direction);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
if (rom_byte_mask == 0) {
rom_byte_number++;
rom_byte_mask = 1;
}
} }
} while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!(id_bit_number < 65)) {
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
LastDiscrepancy = last_zero;
// check for last device // set or clear the bit in the ROM byte rom_byte_number
if (LastDiscrepancy == 0) // with mask rom_byte_mask
LastDeviceFlag = TRUE; if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask;
else
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
search_result = TRUE; // serial number search direction write bit
} write_bit(search_direction);
}
// if no device found then reset counters so next 'search' will be like a first // increment the byte counter id_bit_number
if (!search_result || !ROM_NO[0]) { // and shift the mask rom_byte_mask
LastDiscrepancy = 0; id_bit_number++;
LastDeviceFlag = FALSE; rom_byte_mask <<= 1;
LastFamilyDiscrepancy = 0;
search_result = FALSE; // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
} else { if (rom_byte_mask == 0) {
for (int i = 0; i < 8; i++) rom_byte_number++;
newAddr[i] = ROM_NO[i]; rom_byte_mask = 1;
} }
return search_result; }
} }
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!(id_bit_number < 65)) {
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
LastDiscrepancy = last_zero;
// check for last device
if (LastDiscrepancy == 0) {
LastDeviceFlag = true;
}
search_result = true;
}
}
// if no device found then reset counters so next 'search' will be like a first
if (!search_result || !ROM_NO[0]) {
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
search_result = false;
} else {
for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
}
return search_result;
}
#endif #endif
@@ -517,93 +490,91 @@ uint8_t OneWire::search(uint8_t * newAddr, bool search_mode /* = true */) {
// //
#if ONEWIRE_CRC8_TABLE #if ONEWIRE_CRC8_TABLE
// This table comes from Dallas sample code where it is freely reusable, // Dow-CRC using polynomial X^8 + X^5 + X^4 + X^0
// though Copyright (C) 2000 Dallas Semiconductor Corporation // Tiny 2x16 entry CRC table created by Arjen Lentz
static const uint8_t PROGMEM dscrc_table[] = {0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, // See http://lentz.com.au/blog/calculating-crc-with-a-tiny-32-entry-lookup-table
64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, static const uint8_t PROGMEM dscrc2x16_table[] = {
128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74
237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, };
111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245,
23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119,
244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42,
200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
//
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM // Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
// and the registers. (note: this might better be done without to // and the registers. (Use tiny 2x16 entry CRC table)
// table, it would probably be smaller and certainly fast enough uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
// compared to all those delayMicrosecond() calls. But I got {
// confused, so I use this table from the examples.) uint8_t crc = 0;
//
uint8_t OneWire::crc8(const uint8_t * addr, uint8_t len) {
uint8_t crc = 0;
while (len--) { while (len--) {
crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); crc = *addr++ ^ crc; // just re-using crc as intermediate
} crc = pgm_read_byte(dscrc2x16_table + (crc & 0x0f)) ^
return crc; pgm_read_byte(dscrc2x16_table + 16 + ((crc >> 4) & 0x0f));
}
return crc;
} }
#else #else
// //
// Compute a Dallas Semiconductor 8 bit CRC directly. // Compute a Dallas Semiconductor 8 bit CRC directly.
// this is much slower, but much smaller, than the lookup table. // this is much slower, but a little smaller, than the lookup table.
// //
uint8_t OneWire::crc8(const uint8_t * addr, uint8_t len) { uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
uint8_t crc = 0; {
uint8_t crc = 0;
while (len--) { while (len--) {
#if defined(__AVR__) #if defined(__AVR__)
crc = _crc_ibutton_update(crc, *addr++); crc = _crc_ibutton_update(crc, *addr++);
#else #else
uint8_t inbyte = *addr++; uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) { for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01; uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1; crc >>= 1;
if (mix) if (mix) crc ^= 0x8C;
crc ^= 0x8C; inbyte >>= 1;
inbyte >>= 1; }
}
#endif #endif
} }
return crc; return crc;
} }
#endif #endif
#if ONEWIRE_CRC16 #if ONEWIRE_CRC16
bool OneWire::check_crc16(const uint8_t * input, uint16_t len, const uint8_t * inverted_crc, uint16_t crc) { bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc)
{
crc = ~crc16(input, len, crc); crc = ~crc16(input, len, crc);
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
} }
uint16_t OneWire::crc16(const uint8_t * input, uint16_t len, uint16_t crc) { uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc)
{
#if defined(__AVR__) #if defined(__AVR__)
for (uint16_t i = 0; i < len; i++) { for (uint16_t i = 0 ; i < len ; i++) {
crc = _crc16_update(crc, input[i]); crc = _crc16_update(crc, input[i]);
} }
#else #else
static const uint8_t oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; static const uint8_t oddparity[16] =
{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
for (uint16_t i = 0; i < len; i++) { for (uint16_t i = 0 ; i < len ; i++) {
// Even though we're just copying a byte from the input, // Even though we're just copying a byte from the input,
// we'll be doing 16-bit computation with it. // we'll be doing 16-bit computation with it.
uint16_t cdata = input[i]; uint16_t cdata = input[i];
cdata = (cdata ^ crc) & 0xff; cdata = (cdata ^ crc) & 0xff;
crc >>= 8; crc >>= 8;
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
crc ^= 0xC001; crc ^= 0xC001;
cdata <<= 6; cdata <<= 6;
crc ^= cdata; crc ^= cdata;
cdata <<= 1; cdata <<= 1;
crc ^= cdata; crc ^= cdata;
} }
#endif #endif
return crc; return crc;
} }
#endif #endif
#endif #endif

View File

@@ -1,17 +1,19 @@
#ifndef OneWire_h #ifndef OneWire_h
#define OneWire_h #define OneWire_h
#include <inttypes.h> #ifdef __cplusplus
#include <stdint.h>
#if defined(__AVR__) #if defined(__AVR__)
#include <util/crc16.h> #include <util/crc16.h>
#endif #endif
#if ARDUINO >= 100 #if ARDUINO >= 100
#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc #include <Arduino.h> // for delayMicroseconds, digitalPinToBitMask, etc
#else #else
#include "WProgram.h" // for delayMicroseconds #include "WProgram.h" // for delayMicroseconds
#include "pins_arduino.h" // for digitalPinToBitMask, etc #include "pins_arduino.h" // for digitalPinToBitMask, etc
#endif #endif
// You can exclude certain features from OneWire. In theory, this // You can exclude certain features from OneWire. In theory, this
@@ -40,7 +42,7 @@
// old versions of OneWire). If you disable this, a slower // old versions of OneWire). If you disable this, a slower
// but very compact algorithm is used. // but very compact algorithm is used.
#ifndef ONEWIRE_CRC8_TABLE #ifndef ONEWIRE_CRC8_TABLE
#define ONEWIRE_CRC8_TABLE 0 #define ONEWIRE_CRC8_TABLE 1
#endif #endif
// You can allow 16-bit CRC checks by defining this to 1 // You can allow 16-bit CRC checks by defining this to 1
@@ -49,408 +51,26 @@
#define ONEWIRE_CRC16 1 #define ONEWIRE_CRC16 1
#endif #endif
#ifndef FALSE // Board-specific macros for direct GPIO
#define FALSE 0 #include "util/OneWire_direct_regtype.h"
#endif
#ifndef TRUE
#define TRUE 1
#endif
// Platform specific I/O definitions class OneWire
{
#if defined(__AVR__)
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_BASE_ATTR asm("r30")
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base) + 1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base) + 1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base) + 2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base) + 2)) |= (mask))
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__)
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (1)
#define IO_REG_TYPE uint8_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR __attribute__((unused))
#define DIRECT_READ(base, mask) (*((base) + 512))
#define DIRECT_MODE_INPUT(base, mask) (*((base) + 640) = 0)
#define DIRECT_MODE_OUTPUT(base, mask) (*((base) + 640) = 1)
#define DIRECT_WRITE_LOW(base, mask) (*((base) + 256) = 1)
#define DIRECT_WRITE_HIGH(base, mask) (*((base) + 128) = 1)
#elif defined(__MKL26Z64__)
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) ((*((base) + 16) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) (*((base) + 20) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) (*((base) + 20) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) (*((base) + 8) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) (*((base) + 4) = (mask))
#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__)
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
// If you have trouble with OneWire on Arduino Due, please check the
// status of delayMicroseconds() before reporting a bug in OneWire!
#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*((base) + 15)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base) + 5)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base) + 4)) = (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base) + 13)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base) + 12)) = (mask))
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
#endif
#elif defined(__PIC32MX__)
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*(base + 4)) & (mask)) ? 1 : 0) //PORTX + 0x10
#define DIRECT_MODE_INPUT(base, mask) ((*(base + 2)) = (mask)) //TRISXSET + 0x08
#define DIRECT_MODE_OUTPUT(base, mask) ((*(base + 1)) = (mask)) //TRISXCLR + 0x04
#define DIRECT_WRITE_LOW(base, mask) ((*(base + 8 + 1)) = (mask)) //LATXCLR + 0x24
#define DIRECT_WRITE_HIGH(base, mask) ((*(base + 8 + 2)) = (mask)) //LATXSET + 0x28
#elif defined(ARDUINO_ARCH_ESP8266)
// Special note: I depend on the ESP community to maintain these definitions and
// submit good pull requests. I can not answer any ESP questions or help you
// resolve any problems related to ESP chips. Please do not contact me and please
// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked
// on ESP community forums.
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)GPO)
#define PIN_TO_BITMASK(pin) (1 << pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS
#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS
#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS
#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS
#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS
#elif defined(ARDUINO_ARCH_ESP32)
#include <driver/rtc_io.h>
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline)) IO_REG_TYPE directRead(IO_REG_TYPE pin) {
#if CONFIG_IDF_TARGET_ESP32C3
return (GPIO.in.val >> pin) & 0x1;
#else // plain ESP32
if (pin < 32)
return (GPIO.in >> pin) & 0x1;
else if (pin < 46)
return (GPIO.in1.val >> (pin - 32)) & 0x1;
#endif
return 0;
}
static inline __attribute__((always_inline)) void directWriteLow(IO_REG_TYPE pin) {
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.out_w1tc.val = ((uint32_t)1 << pin);
#else // plain ESP32
if (pin < 32)
GPIO.out_w1tc = ((uint32_t)1 << pin);
else if (pin < 46)
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
#endif
}
static inline __attribute__((always_inline)) void directWriteHigh(IO_REG_TYPE pin) {
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.out_w1ts.val = ((uint32_t)1 << pin);
#else // plain ESP32
if (pin < 32)
GPIO.out_w1ts = ((uint32_t)1 << pin);
else if (pin < 46)
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
#endif
}
static inline __attribute__((always_inline)) void directModeInput(IO_REG_TYPE pin) {
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.enable_w1tc.val = ((uint32_t)1 << (pin));
#else
if (digitalPinIsValid(pin)) {
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if (rtc_reg) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
//#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later
// int8_t rtc_io = esp32_gpioMux[pin].rtc;
// uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
// if ( rtc_reg ) // RTC pins PULL settings
// {
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
// }
#endif
// Input
if (pin < 32)
GPIO.enable_w1tc = ((uint32_t)1 << pin);
else
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
// uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
// pinFunction |= FUN_IE; // input enable but required for output as well?
// pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
// ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
// GPIO.pin[pin].val = 0;
}
#endif
}
static inline __attribute__((always_inline)) void directModeOutput(IO_REG_TYPE pin) {
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.enable_w1ts.val = ((uint32_t)1 << (pin));
#else
if (digitalPinIsValid(pin) && pin <= 33) // pins above 33 can be only inputs
{
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if (rtc_reg) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
//#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later
// int8_t rtc_io = esp32_gpioMux[pin].rtc;
// uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
// if ( rtc_reg ) // RTC pins PULL settings
// {
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
// }
#endif
// Output
if (pin < 32)
GPIO.enable_w1ts = ((uint32_t)1 << pin);
else // already validated to pins <= 33
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
// uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
// pinFunction |= FUN_IE; // input enable but required for output as well?
// pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
// ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
// GPIO.pin[pin].val = 0;
}
#endif
}
#define DIRECT_READ(base, pin) directRead(pin)
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin)
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin)
#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin)
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin)
//#warning "ESP32 OneWire testing"
#elif defined(__SAMD21G18A__)
#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*((base) + 8)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base) + 1)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base) + 2)) = (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base) + 5)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base) + 6)) = (mask))
#elif defined(RBL_NRF51822)
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin)
#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin)
#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin)
#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL)
#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin)
#elif defined(__arc__) /* Arduino101/Genuino101 specifics */
#include "scss_registers.h"
#include "portable.h"
#include "avr/pgmspace.h"
#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId)
#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType)
#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase)
#define DIR_OFFSET_SS 0x01
#define DIR_OFFSET_SOC 0x04
#define EXT_PORT_OFFSET_SS 0x0A
#define EXT_PORT_OFFSET_SOC 0x50
/* GPIO registers base address */
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase)
#define PIN_TO_BITMASK(pin) pin
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline)) IO_REG_TYPE directRead(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
IO_REG_TYPE ret;
if (SS_GPIO == GPIO_TYPE(pin)) {
ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS));
} else {
ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC);
}
return ((ret >> GPIO_ID(pin)) & 0x01);
}
static inline __attribute__((always_inline)) void directModeInput(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), ((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
} else {
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin));
}
}
static inline __attribute__((always_inline)) void directModeOutput(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), ((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
} else {
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin));
}
}
static inline __attribute__((always_inline)) void directWriteLow(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base);
} else {
MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin));
}
}
static inline __attribute__((always_inline)) void directWriteHigh(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base);
} else {
MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin));
}
}
#define DIRECT_READ(base, pin) directRead(base, pin)
#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin)
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin)
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin)
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin)
#elif defined(__riscv)
/*
* Tested on highfive1
*
* Stable results are achieved operating in the
* two high speed modes of the highfive1. It
* seems to be less reliable in slow mode.
*/
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline)) IO_REG_TYPE directRead(IO_REG_TYPE mask) {
return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0;
}
static inline __attribute__((always_inline)) void directModeInput(IO_REG_TYPE mask) {
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
GPIO_REG(GPIO_IOF_EN) &= ~mask;
GPIO_REG(GPIO_INPUT_EN) |= mask;
GPIO_REG(GPIO_OUTPUT_EN) &= ~mask;
}
static inline __attribute__((always_inline)) void directModeOutput(IO_REG_TYPE mask) {
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
GPIO_REG(GPIO_IOF_EN) &= ~mask;
GPIO_REG(GPIO_INPUT_EN) &= ~mask;
GPIO_REG(GPIO_OUTPUT_EN) |= mask;
}
static inline __attribute__((always_inline)) void directWriteLow(IO_REG_TYPE mask) {
GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask;
}
static inline __attribute__((always_inline)) void directWriteHigh(IO_REG_TYPE mask) {
GPIO_REG(GPIO_OUTPUT_VAL) |= mask;
}
#define DIRECT_READ(base, mask) directRead(mask)
#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask)
#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask)
#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask)
#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask)
#else
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE unsigned int
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) digitalRead(pin)
#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW)
#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH)
#define DIRECT_MODE_INPUT(base, pin) pinMode(pin, INPUT)
#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin, OUTPUT)
#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture."
#endif
class OneWire {
private: private:
IO_REG_TYPE bitmask; IO_REG_TYPE bitmask;
volatile IO_REG_TYPE * baseReg; volatile IO_REG_TYPE *baseReg;
#if ONEWIRE_SEARCH #if ONEWIRE_SEARCH
// global search state // global search state
unsigned char ROM_NO[8]; unsigned char ROM_NO[8];
uint8_t LastDiscrepancy; uint8_t LastDiscrepancy;
uint8_t LastFamilyDiscrepancy; uint8_t LastFamilyDiscrepancy;
uint8_t LastDeviceFlag; bool LastDeviceFlag;
#endif #endif
public: public:
OneWire() { OneWire() { }
} OneWire(uint8_t pin) { begin(pin); }
OneWire(uint8_t pin) {
begin(pin);
}
void begin(uint8_t pin); void begin(uint8_t pin);
// Perform a 1-Wire reset cycle. Returns 1 if a device responds // Perform a 1-Wire reset cycle. Returns 1 if a device responds
@@ -470,12 +90,12 @@ class OneWire {
// another read or write. // another read or write.
void write(uint8_t v, uint8_t power = 0); void write(uint8_t v, uint8_t power = 0);
void write_bytes(const uint8_t * buf, uint16_t count, bool power = 0); void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);
// Read a byte. // Read a byte.
uint8_t read(void); uint8_t read(void);
void read_bytes(uint8_t * buf, uint16_t count); void read_bytes(uint8_t *buf, uint16_t count);
// Write a bit. The bus is always left powered at the end, see // Write a bit. The bus is always left powered at the end, see
// note in write() about that. // note in write() about that.
@@ -505,13 +125,13 @@ class OneWire {
// might be a good idea to check the CRC to make sure you didn't // might be a good idea to check the CRC to make sure you didn't
// get garbage. The order is deterministic. You will always get // get garbage. The order is deterministic. You will always get
// the same devices in the same order. // the same devices in the same order.
uint8_t search(uint8_t * newAddr, bool search_mode = true); bool search(uint8_t *newAddr, bool search_mode = true);
#endif #endif
#if ONEWIRE_CRC #if ONEWIRE_CRC
// Compute a Dallas Semiconductor 8 bit CRC, these are used in the // Compute a Dallas Semiconductor 8 bit CRC, these are used in the
// ROM and scratchpad registers. // ROM and scratchpad registers.
static uint8_t crc8(const uint8_t * addr, uint8_t len); static uint8_t crc8(const uint8_t *addr, uint8_t len);
#if ONEWIRE_CRC16 #if ONEWIRE_CRC16
// Compute the 1-Wire CRC16 and compare it against the received CRC. // Compute the 1-Wire CRC16 and compare it against the received CRC.
@@ -534,7 +154,7 @@ class OneWire {
// *not* at a 16-bit integer. // *not* at a 16-bit integer.
// @param crc - The crc starting value (optional) // @param crc - The crc starting value (optional)
// @return True, iff the CRC matches. // @return True, iff the CRC matches.
static bool check_crc16(const uint8_t * input, uint16_t len, const uint8_t * inverted_crc, uint16_t crc = 0); static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0);
// Compute a Dallas Semiconductor 16 bit CRC. This is required to check // Compute a Dallas Semiconductor 16 bit CRC. This is required to check
// the integrity of data received from many 1-Wire devices. Note that the // the integrity of data received from many 1-Wire devices. Note that the
@@ -548,9 +168,15 @@ class OneWire {
// @param len - How many bytes to use. // @param len - How many bytes to use.
// @param crc - The crc starting value (optional) // @param crc - The crc starting value (optional)
// @return The CRC16, as defined by Dallas Semiconductor. // @return The CRC16, as defined by Dallas Semiconductor.
static uint16_t crc16(const uint8_t * input, uint16_t len, uint16_t crc = 0); static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0);
#endif #endif
#endif #endif
}; };
// Prevent this name from leaking into Arduino sketches
#ifdef IO_REG_TYPE
#undef IO_REG_TYPE
#endif #endif
#endif // __cplusplus
#endif // OneWire_h

View File

@@ -0,0 +1,445 @@
#ifndef OneWire_Direct_GPIO_h
#define OneWire_Direct_GPIO_h
// This header should ONLY be included by OneWire.cpp. These defines are
// meant to be private, used within OneWire.cpp, but not exposed to Arduino
// sketches or other libraries which may include OneWire.h.
#include <stdint.h>
// Platform specific I/O definitions
#if defined(__AVR__)
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_BASE_ATTR asm("r30")
#define IO_REG_MASK_ATTR
#if defined(__AVR_ATmega4809__)
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base)-8)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)-8)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base)-4)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)-4)) |= (mask))
#else
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask))
#endif
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__)
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (1)
#define IO_REG_TYPE uint8_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR __attribute__ ((unused))
#define DIRECT_READ(base, mask) (*((base)+512))
#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0)
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1)
#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1)
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1)
#elif defined(__MKL26Z64__)
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask))
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) ((*((base)+2) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) (*((base)+1) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+1) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) (*((base)+34) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+33) = (mask))
#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__)
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
// If you have trouble with OneWire on Arduino Due, please check the
// status of delayMicroseconds() before reporting a bug in OneWire!
#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask))
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
#endif
#elif defined(__PIC32MX__)
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10
#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08
#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04
#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24
#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28
#elif defined(ARDUINO_ARCH_ESP8266)
// Special note: I depend on the ESP community to maintain these definitions and
// submit good pull requests. I can not answer any ESP questions or help you
// resolve any problems related to ESP chips. Please do not contact me and please
// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked
// on ESP community forums.
#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO)
#define PIN_TO_BITMASK(pin) (1 << pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS
#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS
#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS
#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS
#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS
#elif defined(ARDUINO_ARCH_ESP32)
#include <driver/rtc_io.h>
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline))
IO_REG_TYPE directRead(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
return (GPIO.in.val >> pin) & 0x1;
#else // plain ESP32
if ( pin < 32 )
return (GPIO.in >> pin) & 0x1;
else if ( pin < 46 )
return (GPIO.in1.val >> (pin - 32)) & 0x1;
#endif
return 0;
}
static inline __attribute__((always_inline))
void directWriteLow(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.out_w1tc.val = ((uint32_t)1 << pin);
#else // plain ESP32
if ( pin < 32 )
GPIO.out_w1tc = ((uint32_t)1 << pin);
else if ( pin < 46 )
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
#endif
}
static inline __attribute__((always_inline))
void directWriteHigh(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.out_w1ts.val = ((uint32_t)1 << pin);
#else // plain ESP32
if ( pin < 32 )
GPIO.out_w1ts = ((uint32_t)1 << pin);
else if ( pin < 46 )
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
#endif
}
static inline __attribute__((always_inline))
void directModeInput(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.enable_w1tc.val = ((uint32_t)1 << (pin));
#else
if ( digitalPinIsValid(pin) )
{
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if ( rtc_reg ) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
#endif
// Input
if ( pin < 32 )
GPIO.enable_w1tc = ((uint32_t)1 << pin);
else
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
}
#endif
}
static inline __attribute__((always_inline))
void directModeOutput(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C3
GPIO.enable_w1ts.val = ((uint32_t)1 << (pin));
#else
if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs
{
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if ( rtc_reg ) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
#endif
// Output
if ( pin < 32 )
GPIO.enable_w1ts = ((uint32_t)1 << pin);
else // already validated to pins <= 33
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
}
#endif
}
#define DIRECT_READ(base, pin) directRead(pin)
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin)
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin)
#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin)
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin)
// https://github.com/PaulStoffregen/OneWire/pull/47
// https://github.com/stickbreaker/OneWire/commit/6eb7fc1c11a15b6ac8c60e5671cf36eb6829f82c
#ifdef interrupts
#undef interrupts
#endif
#ifdef noInterrupts
#undef noInterrupts
#endif
#define noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux)
#define interrupts() portEXIT_CRITICAL(&mux);}
//#warning "ESP32 OneWire testing"
#elif defined(ARDUINO_ARCH_STM32)
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) ((uint32_t)digitalPinToPinName(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) digitalReadFast((PinName)pin)
#define DIRECT_WRITE_LOW(base, pin) digitalWriteFast((PinName)pin, LOW)
#define DIRECT_WRITE_HIGH(base, pin) digitalWriteFast((PinName)pin, HIGH)
#define DIRECT_MODE_INPUT(base, pin) pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0))
#define DIRECT_MODE_OUTPUT(base, pin) pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0))
#elif defined(__SAMD21G18A__)
#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask))
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask))
#elif defined(__ASR6501__)
#define PIN_IN_PORT(pin) (pin % PIN_NUMBER_IN_PORT)
#define PORT_FROM_PIN(pin) (pin / PIN_NUMBER_IN_PORT)
#define PORT_OFFSET(port) (PORT_REG_SHFIT * port)
#define PORT_ADDRESS(pin) (CYDEV_GPIO_BASE + PORT_OFFSET(PORT_FROM_PIN(pin)))
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) CY_SYS_PINS_READ_PIN(PORT_ADDRESS(pin)+4, PIN_IN_PORT(pin))
#define DIRECT_WRITE_LOW(base, pin) CY_SYS_PINS_CLEAR_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin))
#define DIRECT_WRITE_HIGH(base, pin) CY_SYS_PINS_SET_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin))
#define DIRECT_MODE_INPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin)+8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_DIG_HIZ)
#define DIRECT_MODE_OUTPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin)+8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_STRONG)
#elif defined(RBL_NRF51822)
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin)
#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin)
#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin)
#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL)
#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin)
#elif defined(__arc__) /* Arduino101/Genuino101 specifics */
#include "scss_registers.h"
#include "portable.h"
#include "avr/pgmspace.h"
#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId)
#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType)
#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase)
#define DIR_OFFSET_SS 0x01
#define DIR_OFFSET_SOC 0x04
#define EXT_PORT_OFFSET_SS 0x0A
#define EXT_PORT_OFFSET_SOC 0x50
/* GPIO registers base address */
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase)
#define PIN_TO_BITMASK(pin) pin
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline))
IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
{
IO_REG_TYPE ret;
if (SS_GPIO == GPIO_TYPE(pin)) {
ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS));
} else {
ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC);
}
return ((ret >> GPIO_ID(pin)) & 0x01);
}
static inline __attribute__((always_inline))
void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
{
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)),
((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
} else {
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin));
}
}
static inline __attribute__((always_inline))
void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
{
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)),
((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
} else {
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin));
}
}
static inline __attribute__((always_inline))
void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
{
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base);
} else {
MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin));
}
}
static inline __attribute__((always_inline))
void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
{
if (SS_GPIO == GPIO_TYPE(pin)) {
WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base);
} else {
MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin));
}
}
#define DIRECT_READ(base, pin) directRead(base, pin)
#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin)
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin)
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin)
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin)
#elif defined(__riscv)
/*
* Tested on highfive1
*
* Stable results are achieved operating in the
* two high speed modes of the highfive1. It
* seems to be less reliable in slow mode.
*/
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline))
IO_REG_TYPE directRead(IO_REG_TYPE mask)
{
return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0;
}
static inline __attribute__((always_inline))
void directModeInput(IO_REG_TYPE mask)
{
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
GPIO_REG(GPIO_IOF_EN) &= ~mask;
GPIO_REG(GPIO_INPUT_EN) |= mask;
GPIO_REG(GPIO_OUTPUT_EN) &= ~mask;
}
static inline __attribute__((always_inline))
void directModeOutput(IO_REG_TYPE mask)
{
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
GPIO_REG(GPIO_IOF_EN) &= ~mask;
GPIO_REG(GPIO_INPUT_EN) &= ~mask;
GPIO_REG(GPIO_OUTPUT_EN) |= mask;
}
static inline __attribute__((always_inline))
void directWriteLow(IO_REG_TYPE mask)
{
GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask;
}
static inline __attribute__((always_inline))
void directWriteHigh(IO_REG_TYPE mask)
{
GPIO_REG(GPIO_OUTPUT_VAL) |= mask;
}
#define DIRECT_READ(base, mask) directRead(mask)
#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask)
#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask)
#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask)
#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask)
#else
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE unsigned int
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, pin) digitalRead(pin)
#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW)
#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH)
#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT)
#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT)
#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture."
#endif
#endif

View File

@@ -0,0 +1,55 @@
#ifndef OneWire_Direct_RegType_h
#define OneWire_Direct_RegType_h
#include <stdint.h>
// Platform specific I/O register type
#if defined(__AVR__)
#define IO_REG_TYPE uint8_t
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__)
#define IO_REG_TYPE uint8_t
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
#define IO_REG_TYPE uint32_t
#elif defined(__MKL26Z64__)
#define IO_REG_TYPE uint8_t
#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__)
#define IO_REG_TYPE uint32_t
#elif defined(__PIC32MX__)
#define IO_REG_TYPE uint32_t
#elif defined(ARDUINO_ARCH_ESP8266)
#define IO_REG_TYPE uint32_t
#elif defined(ARDUINO_ARCH_ESP32)
#define IO_REG_TYPE uint32_t
#define IO_REG_MASK_ATTR
#elif defined(ARDUINO_ARCH_STM32)
#define IO_REG_TYPE uint32_t
#elif defined(__SAMD21G18A__)
#define IO_REG_TYPE uint32_t
#elif defined(__ASR6501__)
#define IO_REG_TYPE uint32_t
#elif defined(RBL_NRF51822)
#define IO_REG_TYPE uint32_t
#elif defined(__arc__) /* Arduino101/Genuino101 specifics */
#define IO_REG_TYPE uint32_t
#elif defined(__riscv)
#define IO_REG_TYPE uint32_t
#else
#define IO_REG_TYPE unsigned int
#endif
#endif