PaulStoffregen / OneWire

Library for Dallas/Maxim 1-Wire Chips
http://www.pjrc.com/teensy/td_libs_OneWire.html
579 stars 382 forks source link

Doesn't work on xMega, Mega-0 or "XTiny" AVRs (including "Arduino Uno WiFi 2") #64

Open WestfW opened 5 years ago

WestfW commented 5 years ago

http://forum.arduino.cc/index.php?topic=580188.0

THe OneWire_direct_gpio.h file contains code like:

#if defined(__AVR__)
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))

#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))

This assumes that All "AVR" processors have a similar structure for their IO registers, which isn't true of the "XTiny", XMega, and Mega-0 chips. In particular, the OneWire library doesn't work on the new "Arduino Uno WiFi 2", which uses the ATmega4809 (mega-0 series.)

The 4809, at least, has a set of VPORTs that I believe are compatible with the older AVR port layouts. You can convert from the "standard" Arduino data structures to VPORTs with something like:

static inline  __attribute__((always_inline)) void _dwfast(int pin, int val) {
/*
 * Mega-0, Tiny-1 style IOPORTs
 * (assumes VPORTs exist starting at 0 for each PORT structure)
 */
    uint8_t mask = 1<<digital_pin_to_bit_position[pin];
    uint8_t port = digital_pin_to_port[pin];
    VPORT_t *vport;
    /*
     * Old style port logic is a small integer 0 for PORTA, 1 for PORTB, etc. 
     */
    vport = (VPORT_t *)(port * 4);
    if (val) {
    vport->OUT |= mask;
    } else {
    vport->OUT &= ~mask;
    }
}
WestfW commented 5 years ago

So the VPORTs are laid out DIR, OUT, IN, which means that they are NOT compatible with the IN, DIR, OUT layout of the old-style ports. (Sigh.)

PaulStoffregen commented 5 years ago

@WestfW - Any chance you could give these defines a try?

https://github.com/PaulStoffregen/SerialFlash/commit/218cecdae12b806cfb665309f15fe5b3668f81e2

I'm currently bringing up new hardware, so can't put time into testing right now. But if you can confirm they work, I'll merge them here.

WestfW commented 5 years ago

I've ordered some OneWire parts from Maxim, so I should be able to do testing "soon." If the holidays don't interfere. (hah!)

PaulStoffregen commented 5 years ago

Is this issue fully resolved? (by #66)

PaulStoffregen commented 5 years ago

@WestfW - can you confirm if this issue is resolved? Should I close it?

wayfrae commented 5 years ago

@PaulStoffregen I used those defines and it works on my Arduino Wifi Rev 2. Thank you.

rglory commented 3 years ago

I have similar issue with Attiny202/402. Changing macros to:

#define DIRECT_READ(base, mask)         (((*((base))) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)-6)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)-7)) = (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)-2)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)-3)) = (mask))

makes it work. Variant for __AVR_ATmega4809__ should work too, but I think this one will be shorter and save valuable space.

Regards