You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
4.3 KiB
224 lines
4.3 KiB
6 years ago
|
//
|
||
|
// Created by MightyPork on 2018/01/29.
|
||
|
//
|
||
|
// 1-Wire unit low level functions
|
||
|
//
|
||
|
|
||
|
#include "platform.h"
|
||
|
|
||
|
#define OW_INTERNAL
|
||
|
#include "_ow_internal.h"
|
||
|
#include "_ow_low_level.h"
|
||
|
|
||
|
static inline uint8_t crc8_bits(uint8_t data)
|
||
|
{
|
||
|
uint8_t crc = 0;
|
||
|
if(data & 1) crc ^= 0x5e;
|
||
|
if(data & 2) crc ^= 0xbc;
|
||
|
if(data & 4) crc ^= 0x61;
|
||
|
if(data & 8) crc ^= 0xc2;
|
||
|
if(data & 0x10) crc ^= 0x9d;
|
||
|
if(data & 0x20) crc ^= 0x23;
|
||
|
if(data & 0x40) crc ^= 0x46;
|
||
|
if(data & 0x80) crc ^= 0x8c;
|
||
|
return crc;
|
||
|
}
|
||
|
|
||
|
static uint8_t crc8_add(uint8_t cksum, uint8_t byte)
|
||
|
{
|
||
|
return crc8_bits(byte ^ cksum);
|
||
|
}
|
||
|
|
||
|
uint8_t ow_checksum(const uint8_t *buff, uint32_t len)
|
||
|
{
|
||
|
uint8_t cksum = 0;
|
||
|
for(uint32_t i = 0; i < len; i++) {
|
||
|
cksum = crc8_add(cksum, buff[i]);
|
||
|
}
|
||
|
return cksum;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------
|
||
|
|
||
|
static inline void ow_pull_high(Unit *unit)
|
||
|
{
|
||
|
struct priv *priv = unit->data;
|
||
|
LL_GPIO_SetOutputPin(priv->port, priv->ll_pin);
|
||
|
LL_GPIO_SetPinMode(priv->port, priv->ll_pin, LL_GPIO_MODE_OUTPUT);
|
||
|
}
|
||
|
|
||
|
static inline void ow_pull_low(Unit *unit)
|
||
|
{
|
||
|
struct priv *priv = unit->data;
|
||
|
LL_GPIO_ResetOutputPin(priv->port, priv->ll_pin);
|
||
|
LL_GPIO_SetPinMode(priv->port, priv->ll_pin, LL_GPIO_MODE_OUTPUT);
|
||
|
}
|
||
|
|
||
|
static inline void ow_release_line(Unit *unit)
|
||
|
{
|
||
|
struct priv *priv = unit->data;
|
||
|
LL_GPIO_SetPinMode(priv->port, priv->ll_pin, LL_GPIO_MODE_INPUT);
|
||
|
}
|
||
|
|
||
|
static inline bool ow_sample_line(Unit *unit)
|
||
|
{
|
||
|
struct priv *priv = unit->data;
|
||
|
return (bool) LL_GPIO_IsInputPinSet(priv->port, priv->ll_pin);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reset the 1-wire bus
|
||
|
*/
|
||
|
bool ow_reset(Unit *unit)
|
||
|
{
|
||
|
ow_pull_low(unit);
|
||
|
PTIM_MicroDelay(500);
|
||
|
|
||
|
bool presence;
|
||
|
vPortEnterCritical();
|
||
|
{
|
||
|
// Strong pull-up (for parasitive power)
|
||
|
ow_pull_high(unit);
|
||
|
PTIM_MicroDelay(2);
|
||
|
|
||
|
// switch to open-drain
|
||
|
ow_release_line(unit);
|
||
|
PTIM_MicroDelay(118);
|
||
|
|
||
|
presence = !ow_sample_line(unit);
|
||
|
}
|
||
|
vPortExitCritical();
|
||
|
|
||
|
PTIM_MicroDelay(130);
|
||
|
return presence;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write a bit to the 1-wire bus
|
||
|
*/
|
||
|
void ow_write_bit(Unit *unit, bool bit)
|
||
|
{
|
||
|
vPortEnterCritical();
|
||
|
{
|
||
|
// start mark
|
||
|
ow_pull_low(unit);
|
||
|
PTIM_MicroDelay(2);
|
||
|
|
||
|
if (bit) ow_pull_high(unit);
|
||
|
PTIM_MicroDelay(70);
|
||
|
|
||
|
// Strong pull-up (for parasitive power)
|
||
|
ow_pull_high(unit);
|
||
|
}
|
||
|
vPortExitCritical();
|
||
|
|
||
|
PTIM_MicroDelay(2);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Read a bit from the 1-wire bus
|
||
|
*/
|
||
|
bool ow_read_bit(Unit *unit)
|
||
|
{
|
||
|
bool bit;
|
||
|
|
||
|
vPortEnterCritical();
|
||
|
{
|
||
|
// start mark
|
||
|
ow_pull_low(unit);
|
||
|
PTIM_MicroDelay(2);
|
||
|
|
||
|
ow_release_line(unit);
|
||
|
PTIM_MicroDelay(20);
|
||
|
|
||
|
bit = ow_sample_line(unit);
|
||
|
}
|
||
|
vPortExitCritical();
|
||
|
|
||
|
PTIM_MicroDelay(40);
|
||
|
|
||
|
return bit;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write a byte to the 1-wire bus
|
||
|
*/
|
||
|
void ow_write_u8(Unit *unit, uint8_t byte)
|
||
|
{
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
ow_write_bit(unit, 0 != (byte & (1 << i)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write a halfword to the 1-wire bus
|
||
|
*/
|
||
|
void ow_write_u16(Unit *unit, uint16_t halfword)
|
||
|
{
|
||
|
ow_write_u8(unit, (uint8_t) (halfword & 0xFF));
|
||
|
ow_write_u8(unit, (uint8_t) ((halfword >> 8) & 0xFF));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write a word to the 1-wire bus
|
||
|
*/
|
||
|
void ow_write_u32(Unit *unit, uint32_t word)
|
||
|
{
|
||
|
ow_write_u16(unit, (uint16_t) (word));
|
||
|
ow_write_u16(unit, (uint16_t) (word >> 16));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Write a doubleword to the 1-wire bus
|
||
|
*/
|
||
|
void ow_write_u64(Unit *unit, uint64_t dword)
|
||
|
{
|
||
|
ow_write_u32(unit, (uint32_t) (dword));
|
||
|
ow_write_u32(unit, (uint32_t) (dword >> 32));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Read a byte form the 1-wire bus
|
||
|
*/
|
||
|
uint8_t ow_read_u8(Unit *unit)
|
||
|
{
|
||
|
uint8_t buf = 0;
|
||
|
for (int i = 0; i < 8; i++) {
|
||
|
buf |= (1 & ow_read_bit(unit)) << i;
|
||
|
}
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Read a halfword form the 1-wire bus
|
||
|
*/
|
||
|
uint16_t ow_read_u16(Unit *unit)
|
||
|
{
|
||
|
uint16_t acu = 0;
|
||
|
acu |= ow_read_u8(unit);
|
||
|
acu |= ow_read_u8(unit) << 8;
|
||
|
return acu;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Read a word form the 1-wire bus
|
||
|
*/
|
||
|
uint32_t ow_read_u32(Unit *unit)
|
||
|
{
|
||
|
uint32_t acu = 0;
|
||
|
acu |= ow_read_u16(unit);
|
||
|
acu |= (uint32_t)ow_read_u16(unit) << 16;
|
||
|
return acu;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Read a doubleword form the 1-wire bus
|
||
|
*/
|
||
|
uint64_t ow_read_u64(Unit *unit)
|
||
|
{
|
||
|
uint64_t acu = 0;
|
||
|
acu |= ow_read_u32(unit);
|
||
|
acu |= (uint64_t)ow_read_u32(unit) << 32;
|
||
|
return acu;
|
||
|
}
|