#define DS_DMA DMA1
#define DS_DMA_CHANNEL LL_DMA_CHANNEL_6
#undef DS_DEBUG
+#undef DS_DEBUG2
#ifdef DS_DEBUG
#define DEBUG debug_printf
#define DEBUG(xxx, ...) do { } while (0)
#endif
-static void ds_reset(void)
+#ifdef DS_DEBUG2
+#define DEBUG2 debug_printf
+#else
+#define DEBUG2(xxx, ...) do { } while (0)
+#endif
+
+// Current temperature
+int ds_current_temp = DS_TEMP_UNKNOWN;
+
+static bool ds_reset(void)
{
- DEBUG("DS18B20: Reset\n");
+ DEBUG2("DS18B20: Reset\n");
LL_TIM_DisableCounter(TIM3);
LL_TIM_SetOnePulseMode(TIM3, LL_TIM_ONEPULSEMODE_SINGLE);
LL_TIM_DisableDMAReq_CC1(TIM3);
LL_DMA_DisableChannel(DS_DMA, DS_DMA_CHANNEL);
- DEBUG("Init DMA: %08x [%u] (%u remains)\n", ds_dma_buffer, !!(ds_dma_buffer & DS_PIN_MASK), LL_DMA_GetDataLength(DS_DMA, DS_DMA_CHANNEL));
+ DEBUG2("Init DMA: %08x [%u] (%u remains)\n", ds_dma_buffer, !!(ds_dma_buffer & DS_PIN_MASK), LL_DMA_GetDataLength(DS_DMA, DS_DMA_CHANNEL));
+
+ // Did the device respond?
+ if (ds_dma_buffer & DS_PIN_MASK)
+ {
+ DEBUG("DS18B20: Initialization failed\n");
+ return 0;
+ }
+ else
+ return 1;
}
static void ds_send_byte(byte b)
{
- DEBUG("DS write: %02x\n", b);
+ DEBUG2("DS write: %02x\n", b);
LL_TIM_SetAutoReload(TIM3, 99); // Each write slot takes 100μs
for (uint m=1; m < 0x100; m <<= 1)
{
LL_TIM_OC_SetCompareCH2(TIM3, ((b & m) ? 1 : 89)); // 1: 1μs pulse, 0: 89μs pulse
LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_FORCED_ACTIVE);
+ __disable_irq();
+ // XXX: On STM32F1, we must configure the OC channel _after_ we enable the counter,
+ // otherwise OC triggers immediately. Reasons?
LL_TIM_EnableCounter(TIM3);
LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE);
+ __enable_irq();
while (LL_TIM_IsEnabledCounter(TIM3))
;
}
LL_DMA_SetDataLength(DS_DMA, DS_DMA_CHANNEL, 1);
LL_DMA_EnableChannel(DS_DMA, DS_DMA_CHANNEL);
LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_FORCED_ACTIVE);
+ __disable_irq();
LL_TIM_EnableCounter(TIM3);
LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE);
+ __enable_irq();
while (LL_TIM_IsEnabledCounter(TIM3))
;
- DEBUG("XXX %08x\n", ds_dma_buffer);
+ DEBUG2("XXX %08x\n", ds_dma_buffer);
if (ds_dma_buffer & DS_PIN_MASK)
out |= m;
LL_DMA_DisableChannel(DS_DMA, DS_DMA_CHANNEL);
}
LL_TIM_DisableDMAReq_CC1(TIM3);
- DEBUG("DS read: %02x\n", out);
+ DEBUG2("DS read: %02x\n", out);
return out;
}
static byte ds_buf[10];
-static int ds_recv_block(uint n)
+static bool ds_recv_block(uint n)
{
uint crc = 0;
for (uint i=0; i<n; i++)
{
uint b = ds_recv_byte();
- // debug_printf("%02x ", b);
+ // DEBUG("%02x ", b);
ds_buf[i] = b;
for (uint j=0; j<8; j++)
{
b >>= 1;
}
}
- // debug_printf("\n");
if (crc)
{
- debug_printf("WARNING: Invalid CRC %02x\n", crc);
+ DEBUG("DS18B20: Invalid CRC %02x\n", crc);
return 0;
}
return 1;
}
-void ds_test(void)
+void ds_init(void)
{
- uint cnt = 0;
-
- debug_puts("Init\n");
+ DEBUG("DS18B20: Init\n");
NVIC_DisableIRQ(TIM3_IRQn); // One day, we will handle everything from interrupts...
// Identify device
- ds_reset();
+ if (!ds_reset())
+ return;
ds_send_byte(0x33);
ds_recv_block(8);
// FIXME: Configure precision
+}
- for (;;)
- {
- LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin);
- // debug_printf("Tick tock: %d\n", cnt);
+void ds_step(void)
+{
+ static byte ds_running;
+ static byte ds_timeout;
+ if (!ds_running)
+ {
// Start measurement
- ds_reset();
+ if (!ds_reset())
+ {
+ ds_current_temp = DS_TEMP_UNKNOWN;
+ return;
+ }
ds_send_byte(0xcc);
ds_send_byte(0x44);
- while (ds_recv_byte() != 0xff)
- LL_mDelay(10);
+ ds_running = 1;
+ ds_timeout = 255;
+ }
+ else
+ {
+ // Still running?
+ if (ds_recv_byte() != 0xff)
+ {
+ if (!ds_timeout--)
+ {
+ ds_current_temp = DS_TEMP_UNKNOWN;
+ ds_running = 0;
+ DEBUG("DS18B20: Timeout\n");
+ }
+ return;
+ }
+ ds_running = 0;
// Read scratch pad
- ds_reset();
+ if (!ds_reset())
+ {
+ ds_current_temp = DS_TEMP_UNKNOWN;
+ return;
+ }
ds_send_byte(0xcc);
ds_send_byte(0xbe);
- ds_recv_block(9);
+ if (!ds_recv_block(9))
+ {
+ ds_current_temp = DS_TEMP_UNKNOWN;
+ return;
+ }
int t = (int16_t)(ds_buf[0] | (ds_buf[1] << 8));
t = t*1000/16;
- LL_GPIO_SetOutputPin(LED_GPIO_Port, LED_Pin);
- debug_printf("Temp: %d.%03d degC\n", t/1000, t%1000);
-
- LL_mDelay(1000);
- cnt++;
+ DEBUG("DS18B20: %d.%03d degC\n", t/1000, t%1000);
+ ds_current_temp = t;
}
}
else
msg(L_ERROR, "Received short packet");
+ put_u32_be(req, 2);
+ put_u32_be(req+4, 0);
+ if (err = libusb_bulk_transfer(devh, 0x01, req, 8, &transferred, 2000))
+ die("Transfer failed: error %d\n", err);
+ if (err = libusb_bulk_transfer(devh, 0x82, resp, 64, &received, 2000))
+ die("Receive failed: error %d\n", err);
+ if (received >= 4)
+ {
+ int status = get_u32_be(resp);
+ if (status)
+ msg(L_ERROR, "Received error status %08x", status);
+ else
+ msg(L_INFO, "Temperature: %d\n", get_u32_be(resp+4));
+ }
+ else
+ msg(L_ERROR, "Received short packet");
+
sleep(1);
}