From: Jonathan McDowell Date: Thu, 10 May 2018 19:58:29 +0000 (+0100) Subject: Poll temperature on a 10s basis X-Git-Url: https://the.earth.li/gitweb/?p=temper-clone.git;a=commitdiff_plain;h=6b61bdbca74f12def23fc5f7099cc633aba420b3;hp=f259a83606c7e6692970cd0ec814a7414a481938 Poll temperature on a 10s basis 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. --- diff --git a/Makefile b/Makefile index 2a0028f..db8e4a5 100644 --- 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 4e3d72c..ee6b1a1 100644 --- 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 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 + * + * 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 . + */ +#include +#include +#include +#include +#include + +#include + +#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 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_ */