398 lines
13 KiB
C
398 lines
13 KiB
C
// #################################################################################################
|
|
// # << NEORV32: neorv32_onewire.c - 1-Wire Interface Controller HW Driver HW Driver (Source) >> #
|
|
// # ********************************************************************************************* #
|
|
// # BSD 3-Clause License #
|
|
// # #
|
|
// # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
|
// # #
|
|
// # Redistribution and use in source and binary forms, with or without modification, are #
|
|
// # permitted provided that the following conditions are met: #
|
|
// # #
|
|
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
|
// # conditions and the following disclaimer. #
|
|
// # #
|
|
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
|
|
// # conditions and the following disclaimer in the documentation and/or other materials #
|
|
// # provided with the distribution. #
|
|
// # #
|
|
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
|
|
// # endorse or promote products derived from this software without specific prior written #
|
|
// # permission. #
|
|
// # #
|
|
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
|
|
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
|
|
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
|
|
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
|
|
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
|
|
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
|
|
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
|
|
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
|
|
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
|
|
// # ********************************************************************************************* #
|
|
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
|
|
// #################################################################################################
|
|
|
|
|
|
/**********************************************************************//**
|
|
* @file neorv32_onewire.c
|
|
* @brief 1-Wire Interface Controller (ONEWIRE) HW driver source file.
|
|
*
|
|
* @note These functions should only be used if the ONEWIRE unit was synthesized (IO_ONEWIRE_EN = true).
|
|
**************************************************************************/
|
|
|
|
#include "neorv32.h"
|
|
#include "neorv32_onewire.h"
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Check if ONEWIRE controller was synthesized.
|
|
*
|
|
* @return 0 if ONEWIRE was not synthesized, 1 if ONEWIRE is available.
|
|
**************************************************************************/
|
|
int neorv32_onewire_available(void) {
|
|
|
|
if (NEORV32_SYSINFO->SOC & (1 << SYSINFO_SOC_IO_ONEWIRE)) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Reset, configure and enable ONEWIRE interface controller.
|
|
*
|
|
* @param[in] t_base Base tick time in ns.
|
|
* @return 0 if configuration failed, otherwise the actual t_base time in ns is returned.
|
|
**************************************************************************/
|
|
int neorv32_onewire_setup(uint32_t t_base) {
|
|
|
|
const uint8_t PRSC_LUT[4] = {2, 4, 8, 64}; // subset of system clock prescalers
|
|
|
|
// reset
|
|
NEORV32_ONEWIRE->CTRL = 0;
|
|
NEORV32_ONEWIRE->DATA = 0;
|
|
|
|
uint32_t t_tick;
|
|
uint32_t clkdiv;
|
|
uint32_t clk_prsc_sel = 0; // initial prsc = CLK/2
|
|
uint32_t t_clock_x250ps = (4 * 1000 * 1000 * 1000U) / NEORV32_SYSINFO->CLK; // t_clock in multiples of 0.25 ns
|
|
|
|
// find best base tick configuration
|
|
while (1) {
|
|
|
|
t_tick = t_clock_x250ps * PRSC_LUT[clk_prsc_sel];
|
|
clkdiv = (4*t_base) / t_tick;
|
|
|
|
if ((clkdiv > 0) && (clkdiv <= 255)) { // 8-bit
|
|
break;
|
|
}
|
|
else if (clk_prsc_sel < 3) {
|
|
clk_prsc_sel++; // try next-higher clock prescaler
|
|
}
|
|
else {
|
|
return 0; // failed
|
|
}
|
|
}
|
|
|
|
// set new configuration
|
|
uint32_t ctrl = 0;
|
|
ctrl |= 1 << ONEWIRE_CTRL_EN; // module enable
|
|
ctrl |= (clk_prsc_sel & 0x3) << ONEWIRE_CTRL_PRSC0; // clock prescaler
|
|
ctrl |= ((clkdiv - 1) & 0xff) << ONEWIRE_CTRL_CLKDIV0; // clock divider
|
|
NEORV32_ONEWIRE->CTRL = ctrl;
|
|
|
|
return (int)((t_clock_x250ps / 4) * PRSC_LUT[clk_prsc_sel] * clkdiv);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Enable ONEWIRE controller.
|
|
**************************************************************************/
|
|
void neorv32_onewire_enable(void) {
|
|
|
|
NEORV32_ONEWIRE->CTRL |= (1 << ONEWIRE_CTRL_EN);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Disable ONEWIRE controller.
|
|
**************************************************************************/
|
|
void neorv32_onewire_disable(void) {
|
|
|
|
NEORV32_ONEWIRE->CTRL &= ~(1 << ONEWIRE_CTRL_EN);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Get current bus state.
|
|
*
|
|
* @return 1 if bus is high, 0 if bus is low.
|
|
**************************************************************************/
|
|
int neorv32_onewire_sense(void) {
|
|
|
|
if (NEORV32_ONEWIRE->CTRL & (1 << ONEWIRE_CTRL_SENSE)) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------
|
|
// NON-BLOCKING functions
|
|
// ----------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Check if ONEWIRE module is busy.
|
|
*
|
|
* @note This function is non-blocking.
|
|
*
|
|
* @return 0 if not busy, 1 if busy.
|
|
**************************************************************************/
|
|
int neorv32_onewire_busy(void) {
|
|
|
|
// check busy flag
|
|
if (NEORV32_ONEWIRE->CTRL & (1 << ONEWIRE_CTRL_BUSY)) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Initiate reset pulse.
|
|
*
|
|
* @note This function is non-blocking.
|
|
**************************************************************************/
|
|
void neorv32_onewire_reset(void) {
|
|
|
|
// trigger reset-pulse operation
|
|
NEORV32_ONEWIRE->CTRL |= 1 << ONEWIRE_CTRL_TRIG_RST;
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Get bus presence (after RESET).
|
|
*
|
|
* @note This function is non-blocking.
|
|
*
|
|
* @return 0 if at lest one device is present, -1 otherwise
|
|
**************************************************************************/
|
|
int neorv32_onewire_reset_get_presence(void) {
|
|
|
|
// check presence bit
|
|
if (NEORV32_ONEWIRE->CTRL & (1 << ONEWIRE_CTRL_PRESENCE)) {
|
|
return 0;
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Initiate single-bit read.
|
|
*
|
|
* @note This function is non-blocking.
|
|
**************************************************************************/
|
|
void neorv32_onewire_read_bit(void) {
|
|
|
|
// output all-one
|
|
NEORV32_ONEWIRE->DATA = 0xff;
|
|
|
|
// trigger bit operation
|
|
NEORV32_ONEWIRE->CTRL |= (1 << ONEWIRE_CTRL_TRIG_BIT);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Get bit from previous single-bit read operation
|
|
*
|
|
* @note This function is non-blocking.
|
|
*
|
|
* @return Read bit in bit 0.
|
|
**************************************************************************/
|
|
uint8_t neorv32_onewire_read_bit_get(void) {
|
|
|
|
// return read bit
|
|
if (NEORV32_ONEWIRE->DATA & (1 << 7)) { // LSB first -> read bit is in MSB
|
|
return 1;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Initiate single-bit write.
|
|
*
|
|
* @note This function is non-blocking.
|
|
*
|
|
* @param[in] bit Bit to be send.
|
|
**************************************************************************/
|
|
void neorv32_onewire_write_bit(uint8_t bit) {
|
|
|
|
// set replicated bit
|
|
if (bit) {
|
|
NEORV32_ONEWIRE->DATA = 0xff;
|
|
}
|
|
else {
|
|
NEORV32_ONEWIRE->DATA = 0x00;
|
|
}
|
|
|
|
// trigger bit operation
|
|
NEORV32_ONEWIRE->CTRL |= (1 << ONEWIRE_CTRL_TRIG_BIT);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Initiate read byte.
|
|
*
|
|
* @note This function is non-blocking.
|
|
**************************************************************************/
|
|
void neorv32_onewire_read_byte(void) {
|
|
|
|
// output all-one
|
|
NEORV32_ONEWIRE->DATA = 0xff;
|
|
|
|
//trigger byte operation
|
|
NEORV32_ONEWIRE->CTRL |= (1 << ONEWIRE_CTRL_TRIG_BYTE);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Get data from previous read byte operation.
|
|
*
|
|
* @note This function is non-blocking.
|
|
*
|
|
* @return Read byte.
|
|
**************************************************************************/
|
|
uint8_t neorv32_onewire_read_byte_get(void) {
|
|
|
|
// return read bit
|
|
return (uint8_t)(NEORV32_ONEWIRE->DATA);
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Initiate write byte.
|
|
*
|
|
* @note This function is non-blocking.
|
|
*
|
|
* @param[in] byte Byte to be send.
|
|
**************************************************************************/
|
|
void neorv32_onewire_write_byte(uint8_t byte) {
|
|
|
|
// TX data
|
|
NEORV32_ONEWIRE->DATA = (uint32_t)byte;
|
|
|
|
// and trigger byte operation
|
|
NEORV32_ONEWIRE->CTRL |= (1 << ONEWIRE_CTRL_TRIG_BYTE);
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------
|
|
// BLOCKING functions
|
|
// ----------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Generate reset pulse and check if any bus device is present.
|
|
*
|
|
* @warning This function is blocking!
|
|
*
|
|
* @return 0 if at lest one device is present, -1 otherwise
|
|
**************************************************************************/
|
|
int neorv32_onewire_reset_blocking(void) {
|
|
|
|
// trigger reset-pulse operation
|
|
neorv32_onewire_reset();
|
|
|
|
// wait for operation to complete
|
|
while (neorv32_onewire_busy());
|
|
|
|
// check presence bit
|
|
return neorv32_onewire_reset_get_presence();
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Read single bit.
|
|
*
|
|
* @warning This function is blocking!
|
|
*
|
|
* @return Read bit in bit 0.
|
|
**************************************************************************/
|
|
uint8_t neorv32_onewire_read_bit_blocking(void) {
|
|
|
|
// trigger read-bit operation
|
|
neorv32_onewire_read_bit();
|
|
|
|
// wait for operation to complete
|
|
while (neorv32_onewire_busy());
|
|
|
|
// return read bit
|
|
return neorv32_onewire_read_bit_get();
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Write single bit.
|
|
*
|
|
* @warning This function is blocking!
|
|
*
|
|
* @param[in] bit Bit to be send.
|
|
**************************************************************************/
|
|
void neorv32_onewire_write_bit_blocking(uint8_t bit) {
|
|
|
|
// start single-bit write
|
|
neorv32_onewire_write_bit(bit);
|
|
|
|
// wait for operation to complete
|
|
while (neorv32_onewire_busy());
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Read byte.
|
|
*
|
|
* @warning This function is blocking!
|
|
*
|
|
* @return Read byte.
|
|
**************************************************************************/
|
|
uint8_t neorv32_onewire_read_byte_blocking(void) {
|
|
|
|
// initiate read byte
|
|
neorv32_onewire_read_byte();
|
|
|
|
// wait for operation to complete
|
|
while (neorv32_onewire_busy());
|
|
|
|
// return read byte
|
|
return neorv32_onewire_read_byte_get();
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Write byte.
|
|
*
|
|
* @warning This function is blocking!
|
|
*
|
|
* @param[in] byte Byte to be send.
|
|
**************************************************************************/
|
|
void neorv32_onewire_write_byte_blocking(uint8_t byte) {
|
|
|
|
// initiate write byte
|
|
neorv32_onewire_write_byte(byte);
|
|
|
|
// wait for operation to complete
|
|
while (neorv32_onewire_busy());
|
|
}
|