#include "ds18b20.h" #include #include #include 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; }