remove unused library
This commit is contained in:
parent
af666455bd
commit
8d0dfeef32
|
@ -1,267 +0,0 @@
|
|||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/** library to communicate with a Titan Micro MAX7219 IC attached to a 4-digit 7-segment (code)
|
||||
* @file led_max7219.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2017
|
||||
* @note peripherals used: GPIO @ref led_max7219_gpio, timer @ref led_tm1637_timer
|
||||
* @warning all calls are blocking
|
||||
*
|
||||
* bit vs segment: 0bpabcdefg
|
||||
* +a+
|
||||
* f b
|
||||
* +g+
|
||||
* e c p
|
||||
* +d+
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
#include <stdlib.h> // general utilities
|
||||
#include <string.h> // string utilities
|
||||
|
||||
/* STM32 (including CM3) libraries */
|
||||
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
|
||||
#include <libopencm3/stm32/rcc.h> // real-time control clock library
|
||||
#include <libopencm3/stm32/gpio.h> // general purpose input output library
|
||||
#include <libopencm3/stm32/spi.h> // SPI library
|
||||
#include <libopencm3/stm32/timer.h> // timer library
|
||||
|
||||
#include "global.h" // global utilities
|
||||
#include "led_max7219.h" // MAX7219 header and definitions
|
||||
|
||||
/** @defgroup led_max7219_gpio GPIO used to control MAX7219 IC load line
|
||||
* @{
|
||||
*/
|
||||
#define LED_MAX7219_LOAD_PORT B /**< port for load line */
|
||||
#define LED_MAX7219_LOAD_PIN 12 /**< pin for load line */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup led_max7219_spi SPI used to communication with MAX7219 IC
|
||||
* @{
|
||||
*/
|
||||
#define LED_MAX7219_SPI 2 /**< SPI to send data */
|
||||
/** @} */
|
||||
|
||||
/** ASCII characters encoded for the 7 segments digit block
|
||||
* @note starts with space
|
||||
*/
|
||||
static const uint8_t ascii_7segments[] = {
|
||||
0x00, // space
|
||||
0x06, // ! (I)
|
||||
0x22, // "
|
||||
0x1d, // # (o)
|
||||
0x5b, // $ (s)
|
||||
0x25, // % (/)
|
||||
0x5f, // & (6)
|
||||
0x02, // '
|
||||
0x4e, // ( ([)
|
||||
0x78, // )
|
||||
0x07, // *
|
||||
0x31, // +
|
||||
0x04, // ,
|
||||
0x01, // -
|
||||
0x04, // . (,)
|
||||
0x25, // /
|
||||
0x7e, // 0
|
||||
0x30, // 1
|
||||
0x6d, // 2
|
||||
0x79, // 3
|
||||
0x33, // 4
|
||||
0x5b, // 5
|
||||
0x5f, // 6
|
||||
0x70, // 7
|
||||
0x7f, // 8
|
||||
0x7b, // 9
|
||||
0x09, // : (=)
|
||||
0x09, // ; (=)
|
||||
0x0d, // <
|
||||
0x09, // =
|
||||
0x19, // >
|
||||
0x65, // ?
|
||||
0x6f, // @
|
||||
0x77, // A
|
||||
0x7f, // B
|
||||
0x4e, // C
|
||||
0x3d, // D
|
||||
0x4f, // E
|
||||
0x47, // F
|
||||
0x5e, // G
|
||||
0x37, // H
|
||||
0x06, // I
|
||||
0x3c, // J
|
||||
0x37, // K
|
||||
0x0e, // L
|
||||
0x76, // M
|
||||
0x76, // N
|
||||
0x7e, // O
|
||||
0x67, // P
|
||||
0x6b, // Q
|
||||
0x66, // R
|
||||
0x5b, // S
|
||||
0x0f, // T
|
||||
0x3e, // U
|
||||
0x3e, // V (U)
|
||||
0x3e, // W (U)
|
||||
0x37, // X (H)
|
||||
0x3b, // Y
|
||||
0x6d, // Z
|
||||
0x4e, // [
|
||||
0x13, // '\'
|
||||
0x78, // /
|
||||
0x62, // ^
|
||||
0x08, // _
|
||||
0x20, // `
|
||||
0x7d, // a
|
||||
0x1f, // b
|
||||
0x0d, // c
|
||||
0x3d, // d
|
||||
0x6f, // e
|
||||
0x47, // f
|
||||
0x7b, // g
|
||||
0x17, // h
|
||||
0x04, // i
|
||||
0x18, // j
|
||||
0x37, // k
|
||||
0x06, // l
|
||||
0x15, // m
|
||||
0x15, // n
|
||||
0x1d, // o
|
||||
0x67, // p
|
||||
0x73, // q
|
||||
0x05, // r
|
||||
0x5b, // s
|
||||
0x0f, // t
|
||||
0x1c, // u
|
||||
0x1c, // v (u)
|
||||
0x1c, // w (u)
|
||||
0x37, // x
|
||||
0x3b, // y
|
||||
0x6d, // z
|
||||
0x4e, // { ([)
|
||||
0x06, // |
|
||||
0x78, // } ([)
|
||||
0x01, // ~
|
||||
};
|
||||
|
||||
/** number of display in the chain */
|
||||
uint8_t lex_max7219_displays = 0;
|
||||
|
||||
/** write data on SPI bus and handle load signal
|
||||
* @param[in] data bytes to write
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
*/
|
||||
static void led_max7219_write(uint16_t data, uint8_t display)
|
||||
{
|
||||
if (lex_max7219_displays<=display && 0xff!=display) { // display no in chain
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_clear(GPIO(LED_MAX7219_LOAD_PORT), GPIO(LED_MAX7219_LOAD_PIN)); // ensure load pin is low (data is put in MAX7219 register on rising edge)
|
||||
for (uint8_t i=lex_max7219_displays; i>0; i--) { // go though all displays
|
||||
while (SPI_SR(SPI(LED_MAX7219_SPI))&SPI_SR_BSY); // wait until not busy
|
||||
if (0xff==display || i==(display+1)) { // right display or broadcast message
|
||||
spi_send(SPI(LED_MAX7219_SPI), data); // send data
|
||||
} else {
|
||||
spi_send(SPI(LED_MAX7219_SPI), 0x0000); // send no-op command to shift command to correct display or out
|
||||
}
|
||||
while (!(SPI_SR(SPI(LED_MAX7219_SPI))&SPI_SR_TXE)); // wait until Tx is empty (reference manual says BSY should also cover this, but it doesn't)
|
||||
while (SPI_SR(SPI(LED_MAX7219_SPI))&SPI_SR_BSY); // wait until not busy (= transmission completed)
|
||||
}
|
||||
gpio_set(GPIO(LED_MAX7219_LOAD_PORT), GPIO(LED_MAX7219_LOAD_PIN)); // create rising edge on load pin for data to be set in MAX7219 register
|
||||
}
|
||||
|
||||
void led_max7219_setup(uint8_t displays)
|
||||
{
|
||||
// saved number of displays
|
||||
lex_max7219_displays = displays;
|
||||
|
||||
// configure GPIO for load line
|
||||
rcc_periph_clock_enable(RCC_GPIO(LED_MAX7219_LOAD_PORT)); // enable clock for GPIO peripheral
|
||||
gpio_clear(GPIO(LED_MAX7219_LOAD_PORT), GPIO(LED_MAX7219_LOAD_PIN)); // idle low (load on rising edge)
|
||||
gpio_set_mode(GPIO(LED_MAX7219_LOAD_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(LED_MAX7219_LOAD_PIN)); // set as output
|
||||
|
||||
// configure SPI peripheral
|
||||
rcc_periph_clock_enable(RCC_SPI_SCK_PORT(LED_MAX7219_SPI)); // enable clock for GPIO peripheral for clock signal
|
||||
gpio_set_mode(SPI_SCK_PORT(LED_MAX7219_SPI), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, SPI_SCK_PIN(LED_MAX7219_SPI)); // set as output (max clock speed for MAX7219 is 10 MHz)
|
||||
rcc_periph_clock_enable(RCC_SPI_MOSI_PORT(LED_MAX7219_SPI)); // enable clock for GPIO peripheral for MOSI signal
|
||||
gpio_set_mode(SPI_MOSI_PORT(LED_MAX7219_SPI), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, SPI_MOSI_PIN(LED_MAX7219_SPI)); // set as output
|
||||
rcc_periph_clock_enable(RCC_AFIO); // enable clock for SPI alternate function
|
||||
rcc_periph_clock_enable(RCC_SPI(LED_MAX7219_SPI)); // enable clock for SPI peripheral
|
||||
spi_reset(SPI(LED_MAX7219_SPI)); // clear SPI values to default
|
||||
spi_init_master(SPI(LED_MAX7219_SPI), SPI_CR1_BAUDRATE_FPCLK_DIV_8, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST); // initialise SPI as master, divide clock by 8 since max MAX7219 clock is 10 MHz and max SPI PCLK clock is 72 Mhz, depending on which SPI is used, set clock polarity to idle low (as in the datasheet of the MAX7219, but not that important), set clock phase to go high when bit is set (depends on polarity) as data is stored on MAX7219 on rising edge), use 16 bits frames (as used by MAX7219), use MSB first
|
||||
spi_set_unidirectional_mode(SPI(LED_MAX7219_SPI)); // we only need to transmit data
|
||||
spi_enable(SPI(LED_MAX7219_SPI)); // enable SPI
|
||||
}
|
||||
|
||||
void led_max7219_on(uint8_t display)
|
||||
{
|
||||
led_max7219_write(0x0C01, display); // put in normal operation more (registers remain as set)
|
||||
}
|
||||
|
||||
void led_max7219_off(uint8_t display)
|
||||
{
|
||||
led_max7219_write(0x0C00, display); // put in shutdown mode (registers remain as set)
|
||||
}
|
||||
|
||||
void led_max7219_test(bool test, uint8_t display)
|
||||
{
|
||||
if (test) {
|
||||
led_max7219_write(0x0F01, display); // go into display test mode
|
||||
} else {
|
||||
led_max7219_write(0x0F00, display); // go into normal operation mode
|
||||
}
|
||||
}
|
||||
|
||||
void led_max7219_intensity(uint8_t intensity, uint8_t digits, uint8_t display)
|
||||
{
|
||||
if (intensity>15) { // intensity must be 0-15 (corresponds to (2*brightness+1)/32)
|
||||
return;
|
||||
}
|
||||
if (digits<1 || digits>8) { // scan limit must bit 0-7
|
||||
return;
|
||||
}
|
||||
led_max7219_write(0x0A00+intensity, display); // set brightness
|
||||
led_max7219_write(0x0B00+digits-1, display); // set scan limit to display digits
|
||||
}
|
||||
|
||||
bool led_max7219_text(char* text, uint8_t display)
|
||||
{
|
||||
for (uint8_t i=0; i<8; i++) { // input text should only contain printable character (8th bit is used for dots)
|
||||
if ((text[i]&0x7f)<' ' || (text[i]&0x7f)>=' '+LENGTH(ascii_7segments)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
led_max7219_write(0x0900, display); // disable BCD decoding on all 7 digits
|
||||
for (uint8_t i=0; i<8; i++) { // display text
|
||||
led_max7219_write(((i+1)<<8)+(ascii_7segments[(text[7-i]&0x7f)-' '])+(text[7-i]&0x80), display); // send digit (in reverse order)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void led_max7219_number(uint32_t number, uint8_t dots, uint8_t display)
|
||||
{
|
||||
led_max7219_write(0x09FF, display); // enable BCD decoding on all 7 digits
|
||||
for (uint8_t digit=0; digit<8; digit++) { // go through digits
|
||||
if (0==digit) { // display 0 on 0 only to first digit
|
||||
led_max7219_write(((digit+1)<<8) + (number%10) + (((dots>>digit)&0x01)<<7), display); // display digit
|
||||
} else if (0==number) { // display blank on other digits
|
||||
led_max7219_write(((digit+1)<<8) + 0x0F + (((dots>>digit)&0x01)<<7), display); // display blank
|
||||
} else {
|
||||
led_max7219_write(((digit+1)<<8) + (number%10) + (((dots>>digit)&0x01)<<7), display); // display digit
|
||||
}
|
||||
number /= 10; // get next digit
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/** library to communicate with a Maxim MAX7219 IC attached to a 8-digit 7-segment (API)
|
||||
* @file led_max7219.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2017
|
||||
* @note peripherals used: GPIO @ref led_max7219_gpio, SPI @ref led_max7219_spi
|
||||
* @warning all calls are blocking
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/** setup communication with MAX7219 IC
|
||||
* @param[in] displays number of displays in the chain
|
||||
*/
|
||||
void led_max7219_setup(uint8_t displays);
|
||||
/** do nothing (no operation)
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
* @note send it to the last display in the chain to clear the previous command from the chain
|
||||
*/
|
||||
void led_max7219_nop(uint8_t display);
|
||||
/** switch display on
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
*/
|
||||
void led_max7219_on(uint8_t display);
|
||||
/** switch display off
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
*/
|
||||
void led_max7219_off(uint8_t display);
|
||||
/** switch display in test or normal operation mode
|
||||
* @param[in] test switch in test mode (else normal operation)
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
*/
|
||||
void led_max7219_test(bool test, uint8_t display);
|
||||
/** set display intensity
|
||||
* @param[in] intensity level to set (0-15)
|
||||
* @param[in] digits number of digits to display (1-8)
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
*/
|
||||
void led_max7219_intensity(uint8_t intensity, uint8_t digits, uint8_t display);
|
||||
/** display text
|
||||
* @param[in] text text to display (8 characters)
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
* @note use first bit of each character to enable dot
|
||||
* @return false if string has unsupported characters
|
||||
*/
|
||||
bool led_max7219_text(char* text, uint8_t display);
|
||||
/** display number
|
||||
* @param[in] number number to display (8 digits max)
|
||||
* @param[in] dots set bit if dot on corresponding digit should be displayed
|
||||
* @param[in] display display number in chain (0xff for all)
|
||||
*/
|
||||
void led_max7219_number(uint32_t number, uint8_t dots, uint8_t display);
|
|
@ -1,409 +0,0 @@
|
|||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/** library for 1-wire protocol as master (code)
|
||||
* @file onewire_slave.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2017
|
||||
* @note peripherals used: GPIO and timer @ref onewire_slave_timer, GPIO @ref onewire_slave_gpio
|
||||
* @note overdrive mode is not supported
|
||||
* @implements 1-Wire protocol description from Book of iButton Standards
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
#include <stdbool.h> // boolean type
|
||||
#include <stddef.h> // NULL definition
|
||||
|
||||
/* STM32 (including CM3) libraries */
|
||||
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
|
||||
#include <libopencm3/cm3/nvic.h> // interrupt handler
|
||||
#include <libopencm3/stm32/rcc.h> // real-time control clock library
|
||||
#include <libopencm3/stm32/gpio.h> // general purpose input output library
|
||||
#include <libopencm3/stm32/timer.h> // timer library
|
||||
#include <libopencm3/stm32/exti.h> // external interrupt library
|
||||
|
||||
/* own libraries */
|
||||
#include "global.h" // help macros
|
||||
#include "onewire_slave.h" // own definitions
|
||||
|
||||
/** @defgroup onewire_slave_timer timer used to measure 1-wire signal timing
|
||||
* @{
|
||||
*/
|
||||
#define ONEWIRE_SLAVE_TIMER 2 /**< timer ID */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup onewire_slave_gpio GPIO used for 1-wire signal
|
||||
* @warning ensure no same pin number on other parts are used for external interrupts
|
||||
* @note external pull-up resistor on pin is required (< 5 kOhm), generally provided by the master
|
||||
* @{
|
||||
*/
|
||||
#define ONEWIRE_SLAVE_PORT A /**< GPIO port */
|
||||
#define ONEWIRE_SLAVE_PIN 4 /**< GPIO pin */
|
||||
/** @} */
|
||||
|
||||
/** state of 1-Wire communication */
|
||||
static volatile enum {
|
||||
ONEWIRE_STATE_IDLE, /**< no current communication */
|
||||
ONEWIRE_STATE_RESET, /**< reset pulse has been detected */
|
||||
ONEWIRE_STATE_WAIT_PRESENCE, /**< waiting before sending the presence pulse */
|
||||
ONEWIRE_STATE_PULSE_PRESENCE, /**< sending the presence pulse */
|
||||
ONEWIRE_STATE_ROM_COMMAND, /**< slave is reading ROM command bits */
|
||||
ONEWIRE_STATE_ROM_READ, /**< slave is sending ROM code in response to ROM command READ ROM */
|
||||
ONEWIRE_STATE_ROM_MATCH, /**< master is sending ROM code to select slave */
|
||||
ONEWIRE_STATE_ROM_SEARCH_TRUE, /**< master is searching ROM code, slave will send first bit (not negated) */
|
||||
ONEWIRE_STATE_ROM_SEARCH_FALSE, /**< master is searching ROM code, slave will send first bit (not negated) */
|
||||
ONEWIRE_STATE_ROM_SEARCH_SELECT, /**< master is searching ROM code, slave will read selected bit */
|
||||
ONEWIRE_STATE_FUNCTION_COMMAND, /**< slave is reading function command bits */
|
||||
ONEWIRE_STATE_FUNCTION_DATA, /**< waiting for user to provide data to transfer */
|
||||
ONEWIRE_STATE_FUNCTION_READ, /**< slave is reading bits */
|
||||
ONEWIRE_STATE_FUNCTION_WRITE, /**< slave is writing bits */
|
||||
ONEWIRE_MAX /** to count the number of possible states */
|
||||
} onewire_slave_state = ONEWIRE_STATE_IDLE;
|
||||
|
||||
static uint8_t onewire_slave_rom_code[8] = {0}; /**< slave ROM code */
|
||||
|
||||
volatile bool onewire_slave_function_code_received = false;
|
||||
volatile uint8_t onewire_slave_function_code = 0;
|
||||
volatile bool onewire_slave_transfer_complete = false;
|
||||
|
||||
static volatile uint8_t bits_buffer = 0; /**< buffer for the incoming bits (up to one byte) */
|
||||
static volatile uint32_t bits_bit = 0; /**< number of incoming bits */
|
||||
static volatile uint8_t* onewire_slave_transfer_data = NULL; /**< data to transfer (read or write) */
|
||||
static volatile uint32_t onewire_slave_transfer_bits = 0; /**< number of bits to transfer */
|
||||
|
||||
/** compute CRC for 1-Wire
|
||||
* @note this CRC-8 uses normal polynomial 0x31, reverse polynomial 0x8C, start value 0x00
|
||||
* @param[in] data bytes on which to calculate CRC checksum on
|
||||
* @param[in] length number of bytes in data
|
||||
* @return computed CRC checksum
|
||||
*/
|
||||
static uint8_t onewire_slave_crc(uint8_t* data, uint32_t length)
|
||||
{
|
||||
if (NULL==data || 0==length) { // check input
|
||||
return 0; // wrong input
|
||||
}
|
||||
|
||||
uint8_t crc = 0x00; // initial value
|
||||
for (uint8_t i=0; i<length; i++) { // go through every byte
|
||||
crc ^= data[i]; // XOR byte
|
||||
for (uint8_t b=0; b<8; b++) { // go through every bit
|
||||
if (crc&0x01) { // least significant bit is set (we are using the reverse way)
|
||||
crc = (crc>>1)^0x8C; // // shift to the right (for the next bit) and XOR with (reverse) polynomial
|
||||
} else {
|
||||
crc >>= 1; // just shift right (for the next bit)
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void onewire_slave_setup(uint8_t family, uint64_t serial)
|
||||
{
|
||||
// save ROM code (LSB first)
|
||||
onewire_slave_rom_code[0] = family;
|
||||
onewire_slave_rom_code[1] = serial >> 40;
|
||||
onewire_slave_rom_code[2] = serial >> 32;
|
||||
onewire_slave_rom_code[3] = serial >> 24;
|
||||
onewire_slave_rom_code[4] = serial >> 16;
|
||||
onewire_slave_rom_code[5] = serial >> 8;
|
||||
onewire_slave_rom_code[6] = serial >> 0;
|
||||
onewire_slave_rom_code[7] = onewire_slave_crc(onewire_slave_rom_code, 7); // calculate CRC
|
||||
|
||||
// setup timer to generate/measure signal timing
|
||||
rcc_periph_clock_enable(RCC_TIM(ONEWIRE_SLAVE_TIMER)); // enable clock for timer peripheral
|
||||
timer_reset(TIM(ONEWIRE_SLAVE_TIMER)); // reset timer state
|
||||
timer_set_mode(TIM(ONEWIRE_SLAVE_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
|
||||
timer_set_prescaler(TIM(ONEWIRE_SLAVE_TIMER), 1-1); // don't use prescale since this 16 bits timer allows to wait > 480 us used for the reset pulse ( 1/(72E6/1/(2**16))=910us )
|
||||
|
||||
// use comparator to time signal (without using the output), starting at slot start
|
||||
timer_set_period(TIM(ONEWIRE_SLAVE_TIMER), 480*(rcc_ahb_frequency/1000000)-1-1300); // minimum time needed for a reset pulse (480 < Trst), plus hand tuning
|
||||
timer_set_oc_mode(TIM(ONEWIRE_SLAVE_TIMER), TIM_OC1, TIM_OCM_FROZEN);
|
||||
timer_set_oc_value(TIM(ONEWIRE_SLAVE_TIMER), TIM_OC1, 16*(rcc_ahb_frequency/1000000)-1); // time to wait before sending the presence pulse, after the rising edge of the reset pulse (15 < Tpdh < 60)
|
||||
timer_set_oc_mode(TIM(ONEWIRE_SLAVE_TIMER), TIM_OC2, TIM_OCM_FROZEN);
|
||||
timer_set_oc_value(TIM(ONEWIRE_SLAVE_TIMER), TIM_OC2, 45*(rcc_ahb_frequency/1000000)-1-350); // time to sample the bit after being set (1 < Tlow1 < 15, 60 < Tslot < 120), or stop sending the bit use compare function to detect slave presence (15 = Trdv + 0 < Trelease < 45), plus hand tuning
|
||||
timer_set_oc_value(TIM(ONEWIRE_SLAVE_TIMER), TIM_OC3, 90*(rcc_ahb_frequency/1000000)-1); // time to stop the presence pulse (60 < Tpdl < 120)
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF); // clear all interrupt flags
|
||||
timer_update_on_overflow(TIM(ONEWIRE_SLAVE_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
|
||||
timer_enable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_UIE); // enable update interrupt for overflow
|
||||
nvic_enable_irq(NVIC_TIM_IRQ(ONEWIRE_SLAVE_TIMER)); // catch interrupt in service routine
|
||||
|
||||
onewire_slave_function_code_received = false; // reset state
|
||||
onewire_slave_state = ONEWIRE_STATE_IDLE; // reset state
|
||||
onewire_slave_transfer_complete = false; // reset state
|
||||
|
||||
// setup GPIO with external interrupt
|
||||
rcc_periph_clock_enable(RCC_GPIO(ONEWIRE_SLAVE_PORT)); // enable clock for GPIO peripheral
|
||||
gpio_set(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN)); // idle is high (using pull-up resistor)
|
||||
gpio_set_mode(GPIO(ONEWIRE_SLAVE_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(ONEWIRE_SLAVE_PIN)); // control output using open drain (this mode also allows to read the input signal)
|
||||
rcc_periph_clock_enable(RCC_AFIO); // enable alternate function clock for external interrupt
|
||||
exti_select_source(EXTI(ONEWIRE_SLAVE_PIN), GPIO(ONEWIRE_SLAVE_PORT)); // mask external interrupt of this pin only for this port
|
||||
exti_set_trigger(EXTI(ONEWIRE_SLAVE_PIN), EXTI_TRIGGER_BOTH); // trigger on signal change
|
||||
exti_enable_request(EXTI(ONEWIRE_SLAVE_PIN)); // enable external interrupt
|
||||
nvic_enable_irq(NVIC_EXTI_IRQ(ONEWIRE_SLAVE_PIN)); // enable interrupt
|
||||
}
|
||||
|
||||
bool onewire_slave_function_read(uint8_t* data, size_t size)
|
||||
{
|
||||
if (NULL==data || 0==size) { // verify input
|
||||
return false;
|
||||
}
|
||||
if (UINT32_MAX/8<size) { // too many bits to transfer
|
||||
return false;
|
||||
}
|
||||
if (onewire_slave_state!=ONEWIRE_STATE_FUNCTION_DATA) { // not in the right state to transfer data
|
||||
return false;
|
||||
}
|
||||
onewire_slave_transfer_data = data; // save buffer to write to
|
||||
onewire_slave_transfer_bits = size*8; // number of bits to read
|
||||
onewire_slave_transfer_complete = false; // reset state
|
||||
bits_bit = 0; // reset number of bits read
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_READ; // read data
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onewire_slave_function_write(const uint8_t* data, size_t size)
|
||||
{
|
||||
if (NULL==data || 0==size) { // verify input
|
||||
return false;
|
||||
}
|
||||
if (onewire_slave_state!=ONEWIRE_STATE_FUNCTION_DATA) { // not in the right state to transfer data
|
||||
return false;
|
||||
}
|
||||
if (UINT32_MAX/8<size) { // too many bits to transfer
|
||||
return false;
|
||||
}
|
||||
onewire_slave_transfer_data = (uint8_t*)data; // save buffer to read from
|
||||
onewire_slave_transfer_bits = size*8; // number of bits to write
|
||||
onewire_slave_transfer_complete = false; // reset state
|
||||
bits_bit = 0; // reset number of bits written
|
||||
bits_buffer = onewire_slave_transfer_data[0]; // prepare byte to write
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_WRITE; // write data
|
||||
return true;
|
||||
}
|
||||
|
||||
/** interrupt service routine called when 1-Wire signal changes */
|
||||
void EXTI_ISR(ONEWIRE_SLAVE_PIN)(void)
|
||||
{
|
||||
exti_reset_request(EXTI(ONEWIRE_SLAVE_PIN)); // reset interrupt
|
||||
if (gpio_get(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN))) { // it's a rising edge
|
||||
switch (onewire_slave_state) {
|
||||
case ONEWIRE_STATE_RESET: // reset pulse has ended
|
||||
timer_disable_counter(TIM(ONEWIRE_SLAVE_TIMER)); // stop timer for reconfiguration
|
||||
timer_set_counter(TIM(ONEWIRE_SLAVE_TIMER), 0); // reset timer counter
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC1IF); // clear flag
|
||||
timer_enable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC1IE); // enable compare interrupt for presence pulse
|
||||
timer_enable_counter(TIM(ONEWIRE_SLAVE_TIMER)); // start timer to generate timing
|
||||
onewire_slave_state = ONEWIRE_STATE_WAIT_PRESENCE; // set new stated
|
||||
break;
|
||||
case ONEWIRE_STATE_PULSE_PRESENCE: // we stopped sending the presence pulse
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_COMMAND; // we now expect a ROM command
|
||||
bits_bit = 0; // reset buffer bit count
|
||||
break; // no need to stop the time, the reset will be checked correctly
|
||||
default: // rising edge is not important is the other cases
|
||||
break; // nothing to do
|
||||
}
|
||||
} else { // it's a falling edge, the beginning of a new signal
|
||||
timer_disable_counter(TIM(ONEWIRE_SLAVE_TIMER)); // stop timer for reconfiguration
|
||||
timer_set_counter(TIM(ONEWIRE_SLAVE_TIMER), 0); // reset timer counter
|
||||
timer_disable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE); // disable all timers
|
||||
switch (onewire_slave_state) {
|
||||
case ONEWIRE_STATE_PULSE_PRESENCE: // we started sending the presence pulse
|
||||
timer_enable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC3IE); // enable timer for end of pulse
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_COMMAND: // read ROM command bits
|
||||
case ONEWIRE_STATE_ROM_MATCH: // read ROM code bits
|
||||
case ONEWIRE_STATE_FUNCTION_COMMAND: // read function command bits
|
||||
case ONEWIRE_STATE_ROM_SEARCH_SELECT: // read selected ROM code bit
|
||||
case ONEWIRE_STATE_FUNCTION_READ: // read function data bit
|
||||
timer_enable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC2IE); // enable timer for reading bit
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_READ: // send ROM code bit
|
||||
case ONEWIRE_STATE_ROM_SEARCH_TRUE: // send ROM code bit while searching ROM, not negated
|
||||
case ONEWIRE_STATE_ROM_SEARCH_FALSE: // send ROM code bit while searching ROM, already negated
|
||||
case ONEWIRE_STATE_FUNCTION_WRITE: // write function data bit
|
||||
timer_enable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC2IE); // enable timer for reading bit
|
||||
if (0==(bits_buffer&(1<<(bits_bit%8)))) { // need to send a 0 bit
|
||||
gpio_clear(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN)); // hold low to send 0 bit
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_IDLE: // we only expect a reset
|
||||
default: // we don't expect any falling edge in other states
|
||||
onewire_slave_state = ONEWIRE_STATE_IDLE; // unexpected signal, reset to idle state
|
||||
break; // the timer overflow will confirm detect reset pulses
|
||||
}
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF); // clear all flags
|
||||
timer_enable_counter(TIM(ONEWIRE_SLAVE_TIMER)); // start timer to measure the configured timeouts
|
||||
}
|
||||
}
|
||||
|
||||
/** interrupt service routine called for timer */
|
||||
void TIM_ISR(ONEWIRE_SLAVE_TIMER)(void)
|
||||
{
|
||||
if (timer_interrupt_source(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF)) { // reset timer triggered, verify if it's a reset
|
||||
if (0==gpio_get(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN))) { // signal it still low, thus it must be a reset
|
||||
onewire_slave_state = ONEWIRE_STATE_RESET; // update state
|
||||
}
|
||||
timer_disable_counter(TIM(ONEWIRE_SLAVE_TIMER)); // stop timer since there is nothing more to measure
|
||||
timer_disable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE); // disable all timers
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF); // clear all flag (I have no idea why the others are get too, even when the interrupt is not enabled)
|
||||
}
|
||||
if (timer_interrupt_source(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC1IF)) { // wait for presence pulse timer triggered
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC1IF); // clear flag
|
||||
if (ONEWIRE_STATE_WAIT_PRESENCE==onewire_slave_state) { // we can now send the pulse
|
||||
onewire_slave_state = ONEWIRE_STATE_PULSE_PRESENCE; // save new state
|
||||
gpio_clear(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN)); // send presence pulse (will also trigger the timer start)
|
||||
}
|
||||
}
|
||||
if (timer_interrupt_source(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC2IF)) { // time to read the bit, or stop writing it
|
||||
// read/write bit depending on bit
|
||||
switch (onewire_slave_state) {
|
||||
case ONEWIRE_STATE_ROM_COMMAND: // read ROM command code bit
|
||||
case ONEWIRE_STATE_ROM_MATCH: // read ROM code
|
||||
case ONEWIRE_STATE_FUNCTION_COMMAND: // read function command code bit
|
||||
case ONEWIRE_STATE_ROM_SEARCH_SELECT: // read selected ROM code bit
|
||||
case ONEWIRE_STATE_FUNCTION_READ: // read function data bit
|
||||
if (gpio_get(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN))) { // bit is set to 1
|
||||
bits_buffer |= (1<<(bits_bit%8)); // set bit
|
||||
} else { // bit is set to 0
|
||||
bits_buffer &= ~(1<<(bits_bit%8)); // clear bit
|
||||
}
|
||||
bits_bit++; // go to next bit
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_READ: // write ROM code
|
||||
case ONEWIRE_STATE_FUNCTION_WRITE: // write function data bit
|
||||
gpio_set(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN)); // stop sending bit
|
||||
bits_bit++; // go to next bit
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_SEARCH_TRUE: // ROM code bit is sent
|
||||
case ONEWIRE_STATE_ROM_SEARCH_FALSE: // ROM code bit is sent
|
||||
gpio_set(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN)); // stop sending bit
|
||||
break;
|
||||
default: // these states don't need read/write
|
||||
break;
|
||||
}
|
||||
static uint8_t rom_code_byte; // which byte of the ROM code is processed
|
||||
// act on bit count
|
||||
switch (onewire_slave_state) {
|
||||
case ONEWIRE_STATE_ROM_COMMAND: // read ROM command
|
||||
if (bits_bit>7) { // complete ROM command code received
|
||||
bits_bit = 0; // reset buffer
|
||||
rom_code_byte = 0; // reset ROM code byte index
|
||||
switch (bits_buffer) { // act depending on ROM command code
|
||||
case 0x33: // READ ROM
|
||||
bits_buffer = onewire_slave_rom_code[rom_code_byte]; // prepare to send the first byte
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_READ; // write ROM code
|
||||
break;
|
||||
case 0xcc: // SKIP ROM
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_COMMAND; // now read function command code
|
||||
break;
|
||||
case 0x55: // MATCH ROM
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_MATCH; // read ROM code
|
||||
break;
|
||||
case 0xf0: // SEARCH ROM
|
||||
bits_buffer = onewire_slave_rom_code[rom_code_byte]; // prepare to search code
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_TRUE; // prepare to start sending first new bit
|
||||
break;
|
||||
default: // unknown ROM code
|
||||
onewire_slave_state = ONEWIRE_STATE_IDLE; // go back to default idle state
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_READ: // send ROM code
|
||||
if (bits_bit>7) { // complete byte transmitted
|
||||
rom_code_byte++; // go to next ROM code byte
|
||||
if (rom_code_byte>LENGTH(onewire_slave_rom_code)) { // complete ROM code send
|
||||
onewire_slave_state = ONEWIRE_STATE_IDLE; // go back to default idle state
|
||||
} else {
|
||||
bits_bit = 0; // reset buffer
|
||||
bits_buffer = onewire_slave_rom_code[rom_code_byte]; // send next ROM code byte
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_MATCH: // compare ROM code
|
||||
if (bits_bit>7) { // complete byte received
|
||||
if (bits_buffer==onewire_slave_rom_code[rom_code_byte]) { // ROM code byte matches
|
||||
bits_bit = 0; // reset buffer
|
||||
rom_code_byte++; // go to next ROM code byte
|
||||
if (rom_code_byte>=LENGTH(onewire_slave_rom_code)) { // complete ROM code matches
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_COMMAND; // now read function command code
|
||||
}
|
||||
} else { // ROM code does not match
|
||||
onewire_slave_state = ONEWIRE_STATE_IDLE; // stop comparing and go back to idle
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_SEARCH_TRUE: // ROM code bit is send, prepare to send negated version
|
||||
bits_buffer ^= (1<<bits_bit); // negate bit
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_FALSE; // send negated version
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_SEARCH_FALSE: // negated ROM code bit is send, prepare to read selected bit
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_SELECT; // read selected
|
||||
break;
|
||||
case ONEWIRE_STATE_ROM_SEARCH_SELECT: // check if we are selected
|
||||
if ((bits_buffer&(1<<(bits_bit-1)))==(onewire_slave_rom_code[rom_code_byte]&(1<<(bits_bit-1)))) { // we have been selected
|
||||
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_TRUE; // prepare to compare next bit
|
||||
} else { // we are no selected
|
||||
onewire_slave_state = ONEWIRE_STATE_IDLE; // go back to idle
|
||||
}
|
||||
if (bits_bit>7) { // complete byte searched
|
||||
bits_bit = 0; // reset buffer
|
||||
rom_code_byte++; // go to next ROM code byte
|
||||
if (rom_code_byte>=LENGTH(onewire_slave_rom_code)) { // complete ROM code search
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_COMMAND; // now read function command code
|
||||
} else {
|
||||
bits_buffer = onewire_slave_rom_code[rom_code_byte]; // prepare next ROM code byte
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_FUNCTION_COMMAND: // read function command
|
||||
if (bits_bit>7) { // complete function command code received
|
||||
onewire_slave_function_code = bits_buffer; // save function command code to user buffer
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_DATA; // let the user transfer data
|
||||
onewire_slave_function_code_received = true; // notify user
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_FUNCTION_READ: // save function data bit
|
||||
if (0==bits_bit%8) { // complete byte received
|
||||
onewire_slave_transfer_data[(bits_bit-1)/8] = bits_buffer; // save received bytes
|
||||
}
|
||||
if (bits_bit>=onewire_slave_transfer_bits) { // read transfer complete
|
||||
onewire_slave_transfer_data[(bits_bit-1)/8] = bits_buffer; // save last bits
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_DATA; // let the user transfer more data
|
||||
onewire_slave_transfer_complete = true; // notify user
|
||||
}
|
||||
break;
|
||||
case ONEWIRE_STATE_FUNCTION_WRITE: // update function data bit to write
|
||||
if (0==bits_bit%8) { // complete byte transfer
|
||||
bits_buffer = onewire_slave_transfer_data[bits_bit/8]; // prepare next byte to write
|
||||
}
|
||||
if (bits_bit>=onewire_slave_transfer_bits) { // write transfer complete
|
||||
onewire_slave_state = ONEWIRE_STATE_FUNCTION_DATA; // let the user transfer more data
|
||||
onewire_slave_transfer_complete = true; // notify user
|
||||
}
|
||||
break;
|
||||
default: // no action needed
|
||||
break;
|
||||
}
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC2IF); // clear flag
|
||||
}
|
||||
if (timer_interrupt_source(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC3IF)) { // end of presence pulse timer triggered
|
||||
timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC3IF); // clear flag
|
||||
if (ONEWIRE_STATE_PULSE_PRESENCE==onewire_slave_state) {
|
||||
gpio_set(GPIO(ONEWIRE_SLAVE_PORT), GPIO(ONEWIRE_SLAVE_PIN)); // stop sending presence pulse
|
||||
// if the pin stays low the reset timer will catch it
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/** library for 1-wire protocol as slave (API)
|
||||
* @file onewire_slave.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2017
|
||||
* @note peripherals used: timer @ref onewire_slave_timer, GPIO @ref onewire_slave_gpio
|
||||
* @note overdrive mode is not supported
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/** set when a function command code has been received
|
||||
* @note needs to be cleared by user
|
||||
*/
|
||||
extern volatile bool onewire_slave_function_code_received;
|
||||
/** last function command code received */
|
||||
extern volatile uint8_t onewire_slave_function_code;
|
||||
/** set when data read/write transfer has been completed
|
||||
* @note needs to be cleared by user
|
||||
*/
|
||||
extern volatile bool onewire_slave_transfer_complete;
|
||||
|
||||
/** setup 1-wire peripheral
|
||||
* @param[in] family family code for slave ROM code (8 bits)
|
||||
* @param[in] serial serial number for slave ROM code (48 bits)
|
||||
*/
|
||||
void onewire_slave_setup(uint8_t family, uint64_t serial);
|
||||
/** read data from master
|
||||
* @param[out] data buffer to save read bits
|
||||
* @param[in] size number of bytes to read
|
||||
* @return if transfer initialization succeeded
|
||||
* @note onewire_slave_transfer_complete is set when transfer is completed
|
||||
*/
|
||||
bool onewire_slave_function_read(uint8_t* data, size_t size);
|
||||
/** write data to master
|
||||
* @param[in] data data to write
|
||||
* @param[in] size number of bytes to write
|
||||
* @return if transfer initialization succeeded
|
||||
* @note onewire_slave_transfer_complete is set when transfer is completed
|
||||
*/
|
||||
bool onewire_slave_function_write(const uint8_t* data, size_t size);
|
Loading…
Reference in New Issue