]> the.earth.li Git - temper-clone.git/commitdiff
Poll temperature on a 10s basis
authorJonathan McDowell <noodles@earth.li>
Thu, 10 May 2018 19:58:29 +0000 (20:58 +0100)
committerJonathan McDowell <noodles@earth.li>
Thu, 10 May 2018 20:00:21 +0000 (21:00 +0100)
Rather than polling the temperature sensor when the host requests it
use a timer to poll every 10s and store the result. This means we can
reply quicker when requests, reducing the number of errors we see on
the host due to USB issues. Fixes interaction with the double request
python-temperusb does for every check.

Makefile
main.c
timer.c [new file with mode: 0644]
timer.h [new file with mode: 0644]

index 2a0028f4a4f598250af2cd38f32b549abf38b031..db8e4a5cf2c3488c5220db10c97188ca12e09a27 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CFLAGS = -Iusbdrv -Ilibs-device -I.
 AVRCC = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
 
 OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \
-       libs-device/osccalASM.o main.o w1.o
+       libs-device/osccalASM.o main.o timer.o w1.o
 
 all: main.hex
 
diff --git a/main.c b/main.c
index 4e3d72c3c4667e5a55a9713d8eff3466b8d9e0b8..ee6b1a17b7e60d4a90236151df4b11fa9e6b04ac 100644 (file)
--- a/main.c
+++ b/main.c
@@ -30,6 +30,7 @@
 #include "usbdrv.h"
 #include "libs-device/osccal.h"
 
+#include "timer.h"
 #include "w1.h"
 
 typedef struct {
@@ -40,6 +41,8 @@ typedef struct {
 keyboard_report_t keyboard_report;
 
 uint8_t temp_state = 0;
+uint16_t last_temp = 0xFFFD;
+#define TEMP_INTERVAL (10 * 1000)
 
 uint8_t temp_report[8];
 bool have_temp_int = false;
@@ -335,9 +338,11 @@ usbMsgLen_t usbFunctionWrite(uint8_t * data, uchar len)
                if (data[1] == 0x80 && data[2] == 0x33 && data[3] == 1) {
                        /* Temperature query */
                        memset(temp_report, 0, 8);
-                       temp_state = 1;
+                       have_temp_int = true;
                        temp_report[0] = 0x80;
                        temp_report[1] = 2;
+                       temp_report[2] = last_temp >> 8;
+                       temp_report[3] = last_temp & 0xFF;
                } else if (data[1] == 0x82 && data[2] == 0x77 &&
                                data[3] == 1) {
                        /* Initialisation Query #1 */
@@ -369,11 +374,13 @@ int main(void)
 {
        unsigned char i;
        uint8_t buf[9];
+       unsigned long last_temp_time = 0;
 
        wdt_enable(WDTO_1S);
 
        w1_setup();
        set_serial();
+       timer_init();
 
        usbDeviceDisconnect();
        i = 0;
@@ -413,9 +420,6 @@ int main(void)
                        if (w1_reset()) {
                                temp_state = 2;
                        } else {
-                               temp_report[2] = 0xFF;
-                               temp_report[3] = 0xFF;
-                               have_temp_int = true;
                                temp_state = 0;
                        }
                } else if (temp_state == 2) {
@@ -431,9 +435,6 @@ int main(void)
                        if (w1_reset()) {
                                temp_state = 6;
                        } else {
-                               temp_report[2] = 0xFF;
-                               temp_report[3] = 0xFE;
-                               have_temp_int = true;
                                temp_state = 0;
                        }
                } else if (temp_state == 6) {
@@ -446,10 +447,14 @@ int main(void)
                        buf[temp_state - 8] = w1_read_byte();
                        temp_state++;
                } else if (temp_state == 17) {
-                       temp_report[2] = buf[1] << 4 | buf[0] >> 4;
-                       temp_report[3] = buf[0] << 4;
-                       have_temp_int = true;
+                       last_temp = buf[1] << 12 | buf[0] << 4;
                        temp_state = 0;
+                       last_temp_time = millis();
+               }
+
+               if (temp_state == 0 &&
+                               (millis() - last_temp_time) > TEMP_INTERVAL) {
+                       temp_state = 1;
                }
        }
 }
diff --git a/timer.c b/timer.c
new file mode 100644 (file)
index 0000000..421d763
--- /dev/null
+++ b/timer.c
@@ -0,0 +1,106 @@
+/*
+ * Timer1 functions for ATTiny85
+ *
+ * Heavily based on code from Ardunio:
+ * https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c
+ *
+ * Copyright (c) 2005-2006 David A. Mellis
+ * Copyright 2018 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include <avr/pgmspace.h>
+
+#include "timer.h"
+
+#define clockCyclesPerMicrosecond() (F_CPU / 1000000L)
+/* Prescaler of 64 from CPU_CLK */
+#define MICROSECONDS_PER_TIMER1_OVERFLOW (64 * 256 / clockCyclesPerMicrosecond())
+#define MILLIS_INC (MICROSECONDS_PER_TIMER1_OVERFLOW / 1000)
+#define FRACT_INC ((MICROSECONDS_PER_TIMER1_OVERFLOW % 1000) >> 3)
+#define FRACT_MAX (1000 >> 3)
+
+volatile unsigned long timer1_overflow_count = 0;
+volatile unsigned long timer1_millis = 0;
+static unsigned char timer1_fract = 0;
+
+void timer_init(void)
+{
+       /*
+        * bit 7:   0  (CTC1: Disabled CTC)
+        * bit 6/5: 00 (COM1A1/COM1A0: Disconnect counter from OC1A output)
+        * bit 3-0: 0111 (CS13/CS12/CS11/CS10: CPU_CK/64)
+        */
+       TCCR1 = (1 << CS12) | (1 << CS11) | (1 << CS10);
+
+       /* Initialise counter */
+       TCNT1 = 0;
+
+       /* Disable Timer 1 output compare match interrupt */
+       TIMSK &= ~(OCIE1A | OCIE1B);
+       /* Enable Timer 1 overflow interrupt */
+       TIMSK |= _BV(TOIE1);
+}
+
+unsigned long micros(void)
+{
+       unsigned long m;
+       uint8_t oldSREG = SREG, t;
+
+       cli();
+       m = timer1_overflow_count;
+       t = TCNT1;
+
+       if ((TIFR & _BV(TOV1)) & (t < 255))
+               m++;
+
+       SREG = oldSREG;
+
+       return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
+}
+
+unsigned long millis(void)
+{
+       unsigned long m;
+       uint8_t oldSREG = SREG;
+
+       cli();
+       m = timer1_millis;
+       SREG = oldSREG;
+
+       return m;
+}
+
+SIGNAL(TIMER1_OVF_vect)
+{
+       unsigned long m = timer1_millis;
+       unsigned char f = timer1_fract;
+
+       m += MILLIS_INC;
+       f += FRACT_INC;
+       if (f >= FRACT_MAX) {
+               f -= FRACT_MAX;
+               m++;
+       }
+
+       timer1_fract = f;
+       timer1_millis = m;
+       timer1_overflow_count++;
+}
diff --git a/timer.h b/timer.h
new file mode 100644 (file)
index 0000000..65647f5
--- /dev/null
+++ b/timer.h
@@ -0,0 +1,8 @@
+#ifndef __TIMER_H_
+#define __TIMER_H_
+
+void timer_init(void);
+unsigned long micros(void);
+unsigned long millis(void);
+
+#endif /* __TIMER_H_ */