June 23, 2026

The Dallas 1-wire protocol saga -- first experiments

I spent some time debating which ARM single board computer to use for these "Dallas" experiments. I settled on an Orange Pi PC2 board, which uses the Allwinner H5 chip. This is an ARM64 system. My main reason for the choice is that this system was handy and mounted nicely on a board with a reset switch.

I did some work back in 2021 (5 years ago!) on a NanoPi board which uses the Allwinner H3. A quick look at dallas.c from this effort shows me that I didn't get too far and I am just going to start over.

A central concern is the nature of the GPIO. A place to start is the H5 TRM. On page 291 a section starts entitle "Port Controller (CPUx-PORT). This is the GPIO. A configure register supplies 3 bits per port bit. We can select Input or Output here, or special functions. We have a data register where we can read the pin state when the port is configured as an input. We have a "multi-driving" register where we can pick level 0,1,2, or 3 ad the drive level, whatever the heck that does. Finally we have a "pull" control register where we can enable pullup, pulldown, both, or neither.

What API do I provide in my gpio.c?

gpio_config ( bit, val) sets the config register field (static)
gpio_out_init ( bit ) - configures as output
gpio_dir_out ( bit ) - same as above
gpio_in_init ( bit ) - configures as input
gpio_dir_in ( bit ) - same as above
gpio_output ( gpio, pin, val ) - write to data register (static)
gpio_clear_bit ( bit ) - clear a bit
gpio_set_bit ( bit ) - set a bit
gpio_input ( gpio, pin ) - read from data register (static)
gpio_read_bit ( bit ) - read a bit
gpio_pull ( bit, val ) - set pullup configuration (static)
I provide no ability to change the "drive" register.
Currently I provide no routines to access the pull register in a general way, but I will need to for this project.

I just added this routine:

void
gpio_one_wire ( int bit )
{
    gpio_config ( bit, GPIO_INPUT );
    gpio_clear_bit ( bit );
    gpio_pull ( bit, GPIO_PULL_DISABLE );
}
What I plan to do to "emulate" an open drain drive is to leave the port in input mode when I want to write a 1. This way the driver is high impedance, and the external pullup will provide a "1". The write a 0, I will put the port into output mode, which will enable the driver and the "0" lurking in the data register will drive the bus low.

Some soldering

I need to attach 3 wires to the H5 board. Ground, 3.3 volts, and some GPIO pin. I settle on A8. I solder some path wires using quality female pin connectors. I have a small breadboard, and plug the patch wires into it. I add a 4.7K pullup resistor from 3.3 volts to the GPIO signal. I dig out a scope probe and hook up my Rigol oscilloscope.

A test hook for the Dallas one-wire

The Kyu IO test menu has an entry 19 "generic board test". Type "i 19" to run this. This will call board_test_generic() in h5/board.c Here I replace the previous test call with a call to "dallas_test()" and I am in business.

This gets me started coding up dallas.c -- to start I just set up a scope loop like this:

    for ( ;; ) {
        gpio_dir_out ( dallas_pin );
        delay_us ( 10 );
        gpio_dir_in ( dallas_pin );
        delay_us ( 10 );
    }
The main point of this is to check the timing in delay_us(), but this turns up some surprises, which is the topic of the next section.


Have any comments? Questions? Drop me a line!

Tom's software pages / tom@mmto.org