+static byte ds_recv_byte(void)
+{
+ LL_TIM_SetAutoReload(TIM3, 79); // Each read slot takes 80μs
+ LL_TIM_OC_SetCompareCH2(TIM3, 1); // Generate 1μs pulse to start read slot
+ LL_TIM_OC_SetCompareCH1(TIM3, 8); // Sample data 8μs after start of slot
+ LL_TIM_EnableDMAReq_CC1(TIM3);
+
+ uint out = 0;
+ for (uint m=1; m < 0x100; m <<= 1)
+ {
+ ds_dma_buffer = 0xdeadbeef;
+ LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, 1);
+ LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
+ LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_FORCED_ACTIVE);
+ LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE);
+ LL_TIM_EnableCounter(TIM3);
+ while (LL_TIM_IsEnabledCounter(TIM3))
+ ;
+ // FIXME: Using the Pin constant directly is fragile!
+ // debug_printf("XXX %08x\r\n", ds_dma_buffer);
+ if (ds_dma_buffer & THERMO_Pin)
+ out |= m;
+ LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);
+ }
+
+ LL_TIM_DisableDMAReq_CC1(TIM3);
+ // debug_printf("DS read: %02x\r\n", out);
+ return out;
+}
+
+static byte ds_buf[10];
+
+static int ds_recv_block(uint n)
+{
+ uint crc = 0;
+ for (uint i=0; i<n; i++)
+ {
+ uint b = ds_recv_byte();
+ ds_buf[i] = b;
+ for (uint j=0; j<8; j++)
+ {
+ uint k = (b & 1) ^ (crc >> 7);
+ crc = (crc << 1) & 0xff;
+ if (k)
+ crc ^= 0x31;
+ b >>= 1;
+ }
+ }
+
+ if (crc)
+ {
+ debug_printf("WARNING: Invalid CRC %02x\r\n", crc);
+ return 0;
+ }
+ return 1;
+}
+