]> mj.ucw.cz Git - home-hw.git/commitdiff
SSR: Temperature measurement over USB
authorMartin Mares <mj@ucw.cz>
Wed, 8 Aug 2018 14:18:02 +0000 (16:18 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 8 Aug 2018 14:18:02 +0000 (16:18 +0200)
ssr/Inc/app.h
ssr/Src/ds18b20.c
ssr/Src/main.c
ssr/Src/stm32f1xx_it.c
ssr/host/test.c

index f57ee6dae50bdda562f197145294207bb517c045..65b1e94dd50dd44e66ea4a18f3d763ffea81a3a7 100644 (file)
@@ -1,6 +1,6 @@
 // main.c
 
-extern volatile byte led_trigger;
+extern volatile byte timer_ticked;
 
 // usbdev.c
 
@@ -12,4 +12,8 @@ void tx_packet_send(void);
 
 // ds18b20.c
 
-void ds_test(void);
+extern int ds_current_temp;
+#define DS_TEMP_UNKNOWN 0x7fffffff
+
+void ds_init(void);
+void ds_step(void);
index 0b9b49b00f8d4ebb7a30dffafca0f735a47c7d60..5fa25a129f0ab4249676ea06473694dbffb7b295 100644 (file)
@@ -12,6 +12,7 @@ static volatile u32 ds_dma_buffer;
 #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
@@ -19,9 +20,18 @@ static volatile u32 ds_dma_buffer;
 #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);
 
@@ -66,19 +76,32 @@ static void ds_reset(void)
   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))
        ;
     }
@@ -98,30 +121,32 @@ static byte ds_recv_byte(void)
       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++)
        {
@@ -132,54 +157,79 @@ static int ds_recv_block(uint n)
          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;
     }
 }
index cb54168bf568f2a3eefd43d293dcc229cacfadeb..490bcf171669946241f292df4ce184125357c7ea 100644 (file)
@@ -56,7 +56,7 @@ PCD_HandleTypeDef hpcd_USB_FS;
 /* USER CODE BEGIN PV */
 /* Private variables ---------------------------------------------------------*/
 struct usb usb;
-volatile byte led_trigger;
+volatile byte timer_ticked;
 
 /* USER CODE END PV */
 
@@ -109,6 +109,11 @@ static void process_packet(void)
          put_u32_be(tx_packet, 0);
        }
       break;
+
+    case 2:
+      put_u32_be(tx_packet, 0);
+      put_u32_be(tx_packet+4, ds_current_temp);
+      break;
     }
 
   debug_printf(">> status %08x\n", get_u32_be(tx_packet));
@@ -170,7 +175,7 @@ int main(void)
   LL_TIM_EnableIT_UPDATE(TIM4);
   LL_TIM_GenerateEvent_UPDATE(TIM4);
 
-  ds_test();
+  ds_init();
 
   /* USER CODE END 2 */
 
@@ -178,15 +183,16 @@ int main(void)
   /* USER CODE BEGIN WHILE */
   while (1)
   {
-    if (led_trigger)
+    if (timer_ticked)
       {
-       led_trigger = 0;
+       timer_ticked = 0;
        static byte led_state;
        if (led_state)
          LL_GPIO_SetOutputPin(LED_GPIO_Port, LED_Pin);
        else
          LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin);
        led_state ^= 1;
+       ds_step();
       }
 
     if (rx_packet_state == 1 && !tx_packet_state)
index 2b98e27dbb2dcaa555cfea907f595594cec7ffe0..b8a4457e4746ac26b46fde1715546b79d1273e9e 100644 (file)
@@ -257,7 +257,7 @@ void TIM4_IRQHandler(void)
   /* USER CODE BEGIN TIM4_IRQn 0 */
   if (LL_TIM_IsActiveFlag_UPDATE(TIM4))
     {
-      led_trigger = 1;
+      timer_ticked = 1;
       LL_TIM_ClearFlag_UPDATE(TIM4);
     }
 
index 402db87d37b4a07f1f1dbe107251a1a4ef5ec5ae..6e67f8e43ae755bef47520d92a51917d67f21726 100644 (file)
@@ -94,6 +94,23 @@ int main(void)
       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);
     }