Add pio onewire example (#334)
* Adds PIO onewire example Co-authored-by: martin <admin@crossleys.biz>
This commit is contained in:
@@ -216,12 +216,14 @@ App|Description
|
|||||||
---|---
|
---|---
|
||||||
[hello_pio](pio/hello_pio) | Absolutely minimal example showing how to control an LED by pushing values into a PIO FIFO.
|
[hello_pio](pio/hello_pio) | Absolutely minimal example showing how to control an LED by pushing values into a PIO FIFO.
|
||||||
[apa102](pio/apa102) | Rainbow pattern on on a string of APA102 addressable RGB LEDs.
|
[apa102](pio/apa102) | Rainbow pattern on on a string of APA102 addressable RGB LEDs.
|
||||||
|
[clocked_input](pio/clocked_input) | Shift in serial data, sampling with an external clock.
|
||||||
[differential_manchester](pio/differential_manchester) | Send and receive differential Manchester-encoded serial (BMC).
|
[differential_manchester](pio/differential_manchester) | Send and receive differential Manchester-encoded serial (BMC).
|
||||||
[hub75](pio/hub75) | Display an image on a 128x64 HUB75 RGB LED matrix.
|
[hub75](pio/hub75) | Display an image on a 128x64 HUB75 RGB LED matrix.
|
||||||
[i2c](pio/i2c) | Scan an I2C bus.
|
[i2c](pio/i2c) | Scan an I2C bus.
|
||||||
[ir_nec](pio/ir_nec) | Sending and receiving IR (infra-red) codes using the PIO.
|
[ir_nec](pio/ir_nec) | Sending and receiving IR (infra-red) codes using the PIO.
|
||||||
[logic_analyser](pio/logic_analyser) | Use PIO and DMA to capture a logic trace of some GPIOs, whilst a PWM unit is driving them.
|
[logic_analyser](pio/logic_analyser) | Use PIO and DMA to capture a logic trace of some GPIOs, whilst a PWM unit is driving them.
|
||||||
[manchester_encoding](pio/manchester_encoding) | Send and receive Manchester-encoded serial.
|
[manchester_encoding](pio/manchester_encoding) | Send and receive Manchester-encoded serial.
|
||||||
|
[onewire](pio/onewire)| A library for interfacing to 1-Wire devices, with an example for the DS18B20 temperature sensor.
|
||||||
[pio_blink](pio/pio_blink) | Set up some PIO state machines to blink LEDs at different frequencies, according to delay counts pushed into their FIFOs.
|
[pio_blink](pio/pio_blink) | Set up some PIO state machines to blink LEDs at different frequencies, according to delay counts pushed into their FIFOs.
|
||||||
[pwm](pio/pwm) | Pulse width modulation on PIO. Use it to gradually fade the brightness of an LED.
|
[pwm](pio/pwm) | Pulse width modulation on PIO. Use it to gradually fade the brightness of an LED.
|
||||||
[spi](pio/spi) | Use PIO to erase, program and read an external SPI flash chip. A second example runs a loopback test with all four CPHA/CPOL combinations.
|
[spi](pio/spi) | Use PIO to erase, program and read an external SPI flash chip. A second example runs a loopback test with all four CPHA/CPOL combinations.
|
||||||
@@ -232,7 +234,6 @@ App|Description
|
|||||||
[uart_tx](pio/uart_tx) | Implement the transmit component of a UART serial port, and print hello world.
|
[uart_tx](pio/uart_tx) | Implement the transmit component of a UART serial port, and print hello world.
|
||||||
[ws2812](pio/ws2812) | Examples of driving WS2812 addressable RGB LEDs.
|
[ws2812](pio/ws2812) | Examples of driving WS2812 addressable RGB LEDs.
|
||||||
[addition](pio/addition) | Add two integers together using PIO. Only around 8 billion times slower than Cortex-M0+.
|
[addition](pio/addition) | Add two integers together using PIO. Only around 8 billion times slower than Cortex-M0+.
|
||||||
[clocked_input](pio/clocked_input) | Shift in serial data, sampling with an external clock.
|
|
||||||
|
|
||||||
### PWM
|
### PWM
|
||||||
|
|
||||||
|
|||||||
15
pio/onewire/CMakeLists.txt
Normal file
15
pio/onewire/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
add_executable(pio_onewire)
|
||||||
|
|
||||||
|
target_sources(pio_onewire PRIVATE onewire.c)
|
||||||
|
|
||||||
|
add_subdirectory(onewire_library)
|
||||||
|
|
||||||
|
target_link_libraries(pio_onewire PRIVATE
|
||||||
|
pico_stdlib
|
||||||
|
hardware_pio
|
||||||
|
onewire_library)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(pio_onewire)
|
||||||
|
|
||||||
|
# add url via pico_set_program_url
|
||||||
|
example_auto_set_url(pio_onewire)
|
||||||
57
pio/onewire/README.adoc
Normal file
57
pio/onewire/README.adoc
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
= Interfacing 1-Wire devices to the Pico
|
||||||
|
|
||||||
|
This example demonstrates how to use link:https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html[1-Wire] devices with the Raspberry Pi Pico (RP2040).
|
||||||
|
1-Wire is an interface that enables a master to control several slave devices over a simple shared serial bus.
|
||||||
|
|
||||||
|
The example provides a 1-Wire library that is used to take readings from a set of connected link:https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf[DS18B20] 1-Wire temperature sensors. The results are sent to the default serial terminal connected via USB or UART as configured in the SDK.
|
||||||
|
|
||||||
|
The library uses a driver based on the RP2040 PIO state machine to generate accurate bus timings and control the 1-Wire bus via a GPIO pin.
|
||||||
|
|
||||||
|
_1-Wire(R) is a registered trademark of Maxim Integrated Products, Inc._
|
||||||
|
|
||||||
|
== Wiring information
|
||||||
|
|
||||||
|
Connect one or more DS18B20 sensors to the Pico as shown in the diagram and table below.
|
||||||
|
|
||||||
|
Connect GPIO 15 to 3V3(OUT) with a pull-up resistor of about 4k ohms.
|
||||||
|
|
||||||
|
[[pio_onewire_wiring-diagram]]
|
||||||
|
[pdfwidth=75%]
|
||||||
|
.Wiring diagram
|
||||||
|
image::pio_onewire.png[]
|
||||||
|
|
||||||
|
[[pio_onewire_connections-table]]
|
||||||
|
.Connections table
|
||||||
|
[options="header,footer"]
|
||||||
|
|==================================================
|
||||||
|
|Pico |pin |DS18B20 |pin / sensor wire
|
||||||
|
|GND |38 or equivalent |GND |1 / Black
|
||||||
|
|GPIO 15 |20 |DQ |2 / Yellow
|
||||||
|
|3V3(OUT)|36 |VDD |3 / Red
|
||||||
|
|==================================================
|
||||||
|
|
||||||
|
== Bill of materials
|
||||||
|
|
||||||
|
.A list of materials for the example circuit
|
||||||
|
[[pio_onewire_bom-table]]
|
||||||
|
[cols=3]
|
||||||
|
|===
|
||||||
|
| *Item* | *Quantity* | *Details*
|
||||||
|
| Breadboard | 1 | generic part
|
||||||
|
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
|
||||||
|
| DS18B20 | 3 | chip or wired sensor
|
||||||
|
| 3900 ohm resistor | 1 | generic part
|
||||||
|
| M/M jumper wire | 13 | generic part
|
||||||
|
|===
|
||||||
|
|
||||||
|
== List of files
|
||||||
|
[[pio_onewire_file-list]]
|
||||||
|
CMakeLists.txt:: CMake file to incorporate the example in the build tree.
|
||||||
|
onewire.c:: Source code for the example program.
|
||||||
|
ow_rom.h:: Header file with generic ROM command codes for 1-Wire devices.
|
||||||
|
ds18b20.h:: Header file with function command codes for the DS18B20 device.
|
||||||
|
onewire_library/:: Subdirectory containing the 1-Wire library and driver.
|
||||||
|
onewire_library/CMakeLists.txt:: CMake file to build the 1-Wire library and driver.
|
||||||
|
onewire_library/onewire_library.c:: Source code for the 1-Wire user functions.
|
||||||
|
onewire_library/onewire_library.h:: Header file for the 1-Wire user functions and types.
|
||||||
|
onewire_library/onewire_library.pio:: PIO assembly code for the 1-Wire driver.
|
||||||
9
pio/onewire/ds18b20.h
Normal file
9
pio/onewire/ds18b20.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// Function commands for d218b20 1-Wire temperature sensor
|
||||||
|
// https://www.analog.com/en/products/ds18b20.html
|
||||||
|
//
|
||||||
|
#define DS18B20_CONVERT_T 0x44
|
||||||
|
#define DS18B20_WRITE_SCRATCHPAD 0x4e
|
||||||
|
#define DS18B20_READ_SCRATCHPAD 0xbe
|
||||||
|
#define DS18B20_COPY_SCRATCHPAD 0x48
|
||||||
|
#define DS18B20_RECALL_EE 0xb8
|
||||||
|
#define DS18B20_READ_POWER_SUPPLY 0xb4
|
||||||
77
pio/onewire/onewire.c
Normal file
77
pio/onewire/onewire.c
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 mjcross
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/binary_info.h"
|
||||||
|
|
||||||
|
#include "onewire_library.h" // onewire library functions
|
||||||
|
#include "ow_rom.h" // onewire ROM command codes
|
||||||
|
#include "ds18b20.h" // ds18b20 function codes
|
||||||
|
|
||||||
|
// Demonstrates the PIO onewire driver by taking readings from a set of
|
||||||
|
// ds18b20 1-wire temperature sensors.
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
PIO pio = pio0;
|
||||||
|
uint gpio = 15;
|
||||||
|
|
||||||
|
OW ow;
|
||||||
|
uint offset;
|
||||||
|
// add the program to the PIO shared address space
|
||||||
|
if (pio_can_add_program (pio, &onewire_program)) {
|
||||||
|
offset = pio_add_program (pio, &onewire_program);
|
||||||
|
|
||||||
|
// claim a state machine and initialise a driver instance
|
||||||
|
if (ow_init (&ow, pio, offset, gpio)) {
|
||||||
|
|
||||||
|
// find and display 64-bit device addresses
|
||||||
|
int maxdevs = 10;
|
||||||
|
uint64_t romcode[maxdevs];
|
||||||
|
int num_devs = ow_romsearch (&ow, romcode, maxdevs, OW_SEARCH_ROM);
|
||||||
|
|
||||||
|
printf("Found %d devices\n", num_devs);
|
||||||
|
for (int i = 0; i < num_devs; i += 1) {
|
||||||
|
printf("\t%d: 0x%llx\n", i, romcode[i]);
|
||||||
|
}
|
||||||
|
putchar ('\n');
|
||||||
|
|
||||||
|
while (num_devs > 0) {
|
||||||
|
// start temperature conversion in parallel on all devices
|
||||||
|
// (see ds18b20 datasheet)
|
||||||
|
ow_reset (&ow);
|
||||||
|
ow_send (&ow, OW_SKIP_ROM);
|
||||||
|
ow_send (&ow, DS18B20_CONVERT_T);
|
||||||
|
|
||||||
|
// wait for the conversions to finish
|
||||||
|
while (ow_read(&ow) == 0);
|
||||||
|
|
||||||
|
// read the result from each device
|
||||||
|
for (int i = 0; i < num_devs; i += 1) {
|
||||||
|
ow_reset (&ow);
|
||||||
|
ow_send (&ow, OW_MATCH_ROM);
|
||||||
|
for (int b = 0; b < 64; b += 8) {
|
||||||
|
ow_send (&ow, romcode[i] >> b);
|
||||||
|
}
|
||||||
|
ow_send (&ow, DS18B20_READ_SCRATCHPAD);
|
||||||
|
int16_t temp = 0;
|
||||||
|
temp = ow_read (&ow) | (ow_read (&ow) << 8);
|
||||||
|
printf ("\t%d: %f", i, temp / 16.0);
|
||||||
|
}
|
||||||
|
putchar ('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
puts ("could not initialise the driver");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
puts ("could not add the program");
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true);
|
||||||
|
}
|
||||||
18
pio/onewire/onewire_library/CMakeLists.txt
Normal file
18
pio/onewire/onewire_library/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
add_library(onewire_library INTERFACE)
|
||||||
|
target_sources(onewire_library onewire_library.c)
|
||||||
|
|
||||||
|
# invoke pio_asm to assemble the state machine programs
|
||||||
|
#
|
||||||
|
pico_generate_pio_header(onewire_library ${CMAKE_CURRENT_LIST_DIR}/onewire_library.pio)
|
||||||
|
|
||||||
|
target_link_libraries(onewire_library INTERFACE
|
||||||
|
pico_stdlib
|
||||||
|
hardware_pio
|
||||||
|
)
|
||||||
|
|
||||||
|
# add the `binary` directory so that the generated headers are included in the project
|
||||||
|
#
|
||||||
|
target_include_directories(onewire_library INTERFACE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
135
pio/onewire/onewire_library/onewire_library.c
Normal file
135
pio/onewire/onewire_library/onewire_library.c
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 mjcross
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
|
||||||
|
#include "onewire_library.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Create a driver instance and populate the provided OW structure.
|
||||||
|
// Returns: True on success.
|
||||||
|
// ow: A pointer to a blank OW structure to hold the driver parameters.
|
||||||
|
// pio: The PIO hardware instance to use.
|
||||||
|
// offset: The location of the onewire program in the PIO shared address space.
|
||||||
|
// gpio: The pin to use for the bus (NB: see the README).
|
||||||
|
bool ow_init (OW *ow, PIO pio, uint offset, uint gpio) {
|
||||||
|
int sm = pio_claim_unused_sm (pio, false);
|
||||||
|
if (sm == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gpio_init (gpio); // enable the gpio and clear any output value
|
||||||
|
pio_gpio_init (pio, gpio); // set the function to PIO output
|
||||||
|
ow->gpio = gpio;
|
||||||
|
ow->pio = pio;
|
||||||
|
ow->offset = offset;
|
||||||
|
ow->sm = (uint)sm;
|
||||||
|
ow->jmp_reset = onewire_reset_instr (ow->offset); // assemble the bus reset instruction
|
||||||
|
onewire_sm_init (ow->pio, ow->sm, ow->offset, ow->gpio, 8); // set 8 bits per word
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Send a binary word on the bus (LSB first).
|
||||||
|
// ow: A pointer to an OW driver struct.
|
||||||
|
// data: The word to be sent.
|
||||||
|
void ow_send (OW *ow, uint data) {
|
||||||
|
pio_sm_put_blocking (ow->pio, ow->sm, (uint32_t)data);
|
||||||
|
pio_sm_get_blocking (ow->pio, ow->sm); // discard the response
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read a binary word from the bus.
|
||||||
|
// Returns: the word read (LSB first).
|
||||||
|
// ow: pointer to an OW driver struct
|
||||||
|
uint8_t ow_read (OW *ow) {
|
||||||
|
pio_sm_put_blocking (ow->pio, ow->sm, 0xff); // generate read slots
|
||||||
|
return (uint8_t)(pio_sm_get_blocking (ow->pio, ow->sm) >> 24); // shift response into bits 0..7
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reset the bus and detect any connected slaves.
|
||||||
|
// Returns: true if any slaves responded.
|
||||||
|
// ow: pointer to an OW driver struct
|
||||||
|
bool ow_reset (OW *ow) {
|
||||||
|
pio_sm_exec_wait_blocking (ow->pio, ow->sm, ow->jmp_reset);
|
||||||
|
if ((pio_sm_get_blocking (ow->pio, ow->sm) & 1) == 0) { // apply pin mask (see pio program)
|
||||||
|
return true; // a slave pulled the bus low
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find ROM codes (64-bit hardware addresses) of all connected devices.
|
||||||
|
// See https://www.analog.com/en/app-notes/1wire-search-algorithm.html
|
||||||
|
// Returns: the number of devices found (up to maxdevs) or -1 if an error occurrred.
|
||||||
|
// ow: pointer to an OW driver struct
|
||||||
|
// romcodes: location at which store the addresses (NULL means don't store)
|
||||||
|
// maxdevs: maximum number of devices to find (0 means no limit)
|
||||||
|
// command: 1-Wire search command (e.g. OW_SEARCHROM or OW_ALARM_SEARCH)
|
||||||
|
int ow_romsearch (OW *ow, uint64_t *romcodes, int maxdevs, uint command) {
|
||||||
|
int index;
|
||||||
|
uint64_t romcode = 0ull;
|
||||||
|
int branch_point;
|
||||||
|
int next_branch_point = -1;
|
||||||
|
int num_found = 0;
|
||||||
|
bool finished = false;
|
||||||
|
|
||||||
|
onewire_sm_init (ow->pio, ow->sm, ow->offset, ow->gpio, 1); // set driver to 1-bit mode
|
||||||
|
|
||||||
|
while (finished == false && (maxdevs == 0 || num_found < maxdevs )) {
|
||||||
|
finished = true;
|
||||||
|
branch_point = next_branch_point;
|
||||||
|
if (ow_reset (ow) == false) {
|
||||||
|
num_found = 0; // no slaves present
|
||||||
|
finished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 8; i += 1) { // send search command as single bits
|
||||||
|
ow_send (ow, command >> i);
|
||||||
|
}
|
||||||
|
for (index = 0; index < 64; index += 1) { // determine romcode bits 0..63 (see ref)
|
||||||
|
uint a = ow_read (ow);
|
||||||
|
uint b = ow_read (ow);
|
||||||
|
if (a == 0 && b == 0) { // (a, b) = (0, 0)
|
||||||
|
if (index == branch_point) {
|
||||||
|
ow_send (ow, 1);
|
||||||
|
romcode |= (1ull << index);
|
||||||
|
} else {
|
||||||
|
if (index > branch_point || (romcode & (1ull << index)) == 0) {
|
||||||
|
ow_send(ow, 0);
|
||||||
|
finished = false;
|
||||||
|
romcode &= ~(1ull << index);
|
||||||
|
next_branch_point = index;
|
||||||
|
} else { // index < branch_point or romcode[index] = 1
|
||||||
|
ow_send (ow, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (a != 0 && b != 0) { // (a, b) = (1, 1) error (e.g. device disconnected)
|
||||||
|
num_found = -2; // function will return -1
|
||||||
|
finished = true;
|
||||||
|
break; // terminate for loop
|
||||||
|
} else {
|
||||||
|
if (a == 0) { // (a, b) = (0, 1) or (1, 0)
|
||||||
|
ow_send (ow, 0);
|
||||||
|
romcode &= ~(1ull << index);
|
||||||
|
} else {
|
||||||
|
ow_send (ow, 1);
|
||||||
|
romcode |= (1ull << index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end of for loop
|
||||||
|
|
||||||
|
if (romcodes != NULL) {
|
||||||
|
romcodes[num_found] = romcode; // store the romcode
|
||||||
|
}
|
||||||
|
num_found += 1;
|
||||||
|
} // end of while loop
|
||||||
|
|
||||||
|
onewire_sm_init (ow->pio, ow->sm, ow->offset, ow->gpio, 8); // restore 8-bit mode
|
||||||
|
return num_found;
|
||||||
|
}
|
||||||
17
pio/onewire/onewire_library/onewire_library.h
Normal file
17
pio/onewire/onewire_library/onewire_library.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "hardware/pio.h"
|
||||||
|
#include "hardware/clocks.h" // for clock_get_hz() in generated header
|
||||||
|
#include "onewire_library.pio.h" // generated by pioasm
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PIO pio;
|
||||||
|
uint sm;
|
||||||
|
uint jmp_reset;
|
||||||
|
int offset;
|
||||||
|
int gpio;
|
||||||
|
} OW;
|
||||||
|
|
||||||
|
bool ow_init (OW *ow, PIO pio, uint offset, uint gpio);
|
||||||
|
void ow_send (OW *ow, uint data);
|
||||||
|
uint8_t ow_read (OW *ow);
|
||||||
|
bool ow_reset (OW *ow);
|
||||||
|
int ow_romsearch (OW *ow, uint64_t *romcodes, int maxdevs, uint command);
|
||||||
96
pio/onewire/onewire_library/onewire_library.pio
Normal file
96
pio/onewire/onewire_library/onewire_library.pio
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
;
|
||||||
|
; Copyright (c) 2023 mjcross
|
||||||
|
;
|
||||||
|
; SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
;
|
||||||
|
|
||||||
|
; Implements a Maxim 1-Wire bus with a GPIO pin.
|
||||||
|
;
|
||||||
|
; Place data words to be transmitted in the TX FIFO and read the results from the
|
||||||
|
; RX FIFO. To reset the bus execute a jump to 'reset_bus' using the opcode from
|
||||||
|
; the provided function.
|
||||||
|
;
|
||||||
|
; At 1us per cycle as initialised below the timings are those recommended by:
|
||||||
|
; https://www.analog.com/en/technical-articles/1wire-communication-through-software.html
|
||||||
|
;
|
||||||
|
; Notes:
|
||||||
|
; (1) The code will stall with the bus in a safe state if the FIFOs are empty/full.
|
||||||
|
; (2) The bus must be pulled up with an external pull-up resistor of about 4k.
|
||||||
|
; The internal GPIO resistors are too high (~50k) to work reliably for this.
|
||||||
|
; (3) Do not connect the GPIO pin directly to a bus powered at more than 3.3V.
|
||||||
|
|
||||||
|
.program onewire
|
||||||
|
.side_set 1 pindirs
|
||||||
|
|
||||||
|
PUBLIC reset_bus:
|
||||||
|
set x, 28 side 1 [15] ; pull bus low 16
|
||||||
|
loop_a: jmp x-- loop_a side 1 [15] ; 29 x 16
|
||||||
|
set x, 8 side 0 [6] ; release bus 7
|
||||||
|
loop_b: jmp x-- loop_b side 0 [6] ; 9 x 7
|
||||||
|
|
||||||
|
mov isr, pins side 0 ; read all pins to ISR (avoids autopush) 1
|
||||||
|
push side 0 ; push result manually 1
|
||||||
|
set x, 24 side 0 [7] ; 8
|
||||||
|
loop_c: jmp x-- loop_c side 0 [15] ; 25 x 16
|
||||||
|
|
||||||
|
.wrap_target
|
||||||
|
PUBLIC fetch_bit:
|
||||||
|
out x, 1 side 0 ; shift next bit from OSR (autopull) 1
|
||||||
|
jmp !x send_0 side 1 [5] ; pull bus low, branch if sending '0' 6
|
||||||
|
|
||||||
|
send_1: ; send a '1' bit
|
||||||
|
set x, 2 side 0 [8] ; release bus, wait for slave response 9
|
||||||
|
in pins, 1 side 0 [4] ; read bus, shift bit to ISR (autopush) 5
|
||||||
|
loop_e: jmp x-- loop_e side 0 [15] ; 3 x 16
|
||||||
|
jmp fetch_bit side 0 ; 1
|
||||||
|
|
||||||
|
send_0: ; send a '0' bit
|
||||||
|
set x, 2 side 1 [5] ; continue pulling bus low 6
|
||||||
|
loop_d: jmp x-- loop_d side 1 [15] ; 3 x 16
|
||||||
|
in null, 1 side 0 [8] ; release bus, shift 0 to ISR (autopush) 9
|
||||||
|
.wrap
|
||||||
|
;; (17 instructions)
|
||||||
|
|
||||||
|
|
||||||
|
% c-sdk {
|
||||||
|
static inline void onewire_sm_init (PIO pio, uint sm, uint offset, uint pin_num, uint bits_per_word) {
|
||||||
|
|
||||||
|
// create a new state machine configuration
|
||||||
|
pio_sm_config c = onewire_program_get_default_config (offset);
|
||||||
|
|
||||||
|
// Input Shift Register configuration settings
|
||||||
|
sm_config_set_in_shift (
|
||||||
|
&c,
|
||||||
|
true, // shift direction: right
|
||||||
|
true, // autopush: enabled
|
||||||
|
bits_per_word // autopush threshold
|
||||||
|
);
|
||||||
|
|
||||||
|
// Output Shift Register configuration settings
|
||||||
|
sm_config_set_out_shift (
|
||||||
|
&c,
|
||||||
|
true, // shift direction: right
|
||||||
|
true, // autopull: enabled
|
||||||
|
bits_per_word // autopull threshold
|
||||||
|
);
|
||||||
|
|
||||||
|
// configure the input and sideset pin groups to start at `pin_num`
|
||||||
|
sm_config_set_in_pins (&c, pin_num);
|
||||||
|
sm_config_set_sideset_pins (&c, pin_num);
|
||||||
|
|
||||||
|
// configure the clock divider for 1 usec per instruction
|
||||||
|
float div = clock_get_hz (clk_sys) * 1e-6;
|
||||||
|
sm_config_set_clkdiv (&c, div);
|
||||||
|
|
||||||
|
// apply the configuration and initialise the program counter
|
||||||
|
pio_sm_init (pio, sm, offset + onewire_offset_fetch_bit, &c);
|
||||||
|
|
||||||
|
// enable the state machine
|
||||||
|
pio_sm_set_enabled (pio, sm, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint onewire_reset_instr (uint offset) {
|
||||||
|
// encode a "jmp reset_bus side 0" instruction for the state machine
|
||||||
|
return pio_encode_jmp (offset + onewire_offset_reset_bus) | pio_encode_sideset (1, 0);
|
||||||
|
}
|
||||||
|
%}
|
||||||
8
pio/onewire/ow_rom.h
Normal file
8
pio/onewire/ow_rom.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Generic ROM commands for 1-Wire devices
|
||||||
|
// https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html
|
||||||
|
//
|
||||||
|
#define OW_READ_ROM 0x33
|
||||||
|
#define OW_MATCH_ROM 0x55
|
||||||
|
#define OW_SKIP_ROM 0xCC
|
||||||
|
#define OW_ALARM_SEARCH 0xEC
|
||||||
|
#define OW_SEARCH_ROM 0xF0
|
||||||
BIN
pio/onewire/pio_onewire.fzz
Normal file
BIN
pio/onewire/pio_onewire.fzz
Normal file
Binary file not shown.
BIN
pio/onewire/pio_onewire.png
Normal file
BIN
pio/onewire/pio_onewire.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 160 KiB |
Reference in New Issue
Block a user