93 lines
2.9 KiB
C
93 lines
2.9 KiB
C
#include "ds18b20.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
uint8_t scratchpad[DS18B20_SCRATCHPAD_SIZE];
|
|
uint16_t read_call;
|
|
uint32_t max_delay_us;
|
|
uint16_t copy_delay_chunks;
|
|
uint8_t critical_active;
|
|
} mock_port_t;
|
|
|
|
static void drive_low(void *context) { (void)context; }
|
|
static void release_line(void *context) { (void)context; }
|
|
|
|
static uint8_t read_line(void *context)
|
|
{
|
|
mock_port_t *port = (mock_port_t *)context;
|
|
uint16_t call = port->read_call++;
|
|
assert(port->critical_active); /* Presence and data sampling must be protected. */
|
|
if (call == 0U) return 0U; /* Read Scratchpad reset presence. */
|
|
if (call <= 72U) {
|
|
uint16_t bit = (uint16_t)(call - 1U);
|
|
return (uint8_t)((port->scratchpad[bit / 8U] >> (bit % 8U)) & 1U);
|
|
}
|
|
/* Write Scratchpad and Copy Scratchpad reset presence pulses. */
|
|
return 0U;
|
|
}
|
|
|
|
static void delay_us(void *context, uint32_t us)
|
|
{
|
|
mock_port_t *port = (mock_port_t *)context;
|
|
if (us > port->max_delay_us) port->max_delay_us = us;
|
|
if (us == 100U) port->copy_delay_chunks++;
|
|
}
|
|
|
|
static void critical_enter(void *context)
|
|
{
|
|
mock_port_t *port = (mock_port_t *)context;
|
|
assert(!port->critical_active);
|
|
port->critical_active = 1U;
|
|
}
|
|
|
|
static void critical_exit(void *context)
|
|
{
|
|
mock_port_t *port = (mock_port_t *)context;
|
|
assert(port->critical_active);
|
|
port->critical_active = 0U;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
static const ds18b20_onewire_ops_t ops = {
|
|
drive_low, release_line, read_line, delay_us, NULL, critical_enter, critical_exit, NULL
|
|
};
|
|
ds18b20_t bus;
|
|
mock_port_t port;
|
|
uint8_t roms[1][DS18B20_ROM_SIZE] = {{0}};
|
|
|
|
memset(&port, 0, sizeof(port));
|
|
roms[0][0] = 0x28U;
|
|
roms[0][1] = 0x11U;
|
|
roms[0][7] = ds18b20_crc8(roms[0], 7U);
|
|
port.scratchpad[0] = 0x50U;
|
|
port.scratchpad[1] = 0x05U;
|
|
port.scratchpad[2] = 0x4BU;
|
|
port.scratchpad[3] = 0x46U;
|
|
port.scratchpad[4] = 0x7FU;
|
|
port.scratchpad[5] = 0xFFU;
|
|
port.scratchpad[6] = 0x0CU;
|
|
port.scratchpad[7] = 0x10U;
|
|
port.scratchpad[8] = ds18b20_crc8(port.scratchpad, 8U);
|
|
|
|
assert(ds18b20_init(&bus, &ops, &port, roms, 1U) == DS18B20_OK);
|
|
bus.rom_count = 1U;
|
|
assert(ds18b20_set_resolution(&bus, roms[0], 9U) == DS18B20_OK);
|
|
/* Regression: a 10 ms callback overflows the 16-bit 72 MHz timer port. */
|
|
assert(port.max_delay_us <= 480U);
|
|
assert(port.copy_delay_chunks >= 100U);
|
|
bus.rom_count = 0U;
|
|
assert(ds18b20_search_retry_due(&bus, 0U, 1999U, 0U, 2000U) == 0U);
|
|
assert(ds18b20_search_retry_due(&bus, 0U, 2000U, 0U, 2000U) == 1U);
|
|
assert(ds18b20_search_retry_due(&bus, 1U, 4000U, 0U, 2000U) == 0U);
|
|
/* Wrap-safe deadline: 0x20 - 0xFFFFFF00 = 0x120 ms. */
|
|
assert(ds18b20_search_retry_due(&bus, 0U, 0x20U, 0xFFFFFF00U, 0x120U) == 1U);
|
|
bus.rom_count = 1U;
|
|
assert(ds18b20_search_retry_due(&bus, 0U, 4000U, 0U, 2000U) == 0U);
|
|
puts("DS18B20 copy delay regression: OK");
|
|
return 0;
|
|
}
|