From 3489015ff245861355f73674f79801279d95ea39 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 3 Nov 2023 11:05:59 -0600 Subject: renamed tk*.h to arch/*.h or fsm/*.h (part 1) to get them out of the root dir, and to start cleaning up mcu/arch code --- arch/adc-calibration.h | 64 ++++++++++++++++++ arch/delay.h | 58 ++++++++++++++++ arch/mcu.h | 157 +++++++++++++++++++++++++++++++++++++++++++ arch/random.h | 14 ++++ arch/voltage.h | 178 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 471 insertions(+) create mode 100644 arch/adc-calibration.h create mode 100644 arch/delay.h create mode 100644 arch/mcu.h create mode 100644 arch/random.h create mode 100644 arch/voltage.h (limited to 'arch') diff --git a/arch/adc-calibration.h b/arch/adc-calibration.h new file mode 100644 index 0000000..f0b05ab --- /dev/null +++ b/arch/adc-calibration.h @@ -0,0 +1,64 @@ +// tk-calibration.h: Attiny calibration header. +// Copyright (C) 2015-2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +// This allows using a single set of hardcoded values across multiple projects. + +/********************** Voltage ADC calibration **************************/ +// These values were measured using RMM's FET+7135. +// See battcheck/readings.txt for reference values. +// the ADC values we expect for specific voltages +#define ADC_44 194 +#define ADC_43 189 +#define ADC_42 184 +#define ADC_41 178 +#define ADC_40 173 +#define ADC_39 168 +#define ADC_38 163 +#define ADC_37 158 +#define ADC_36 152 +#define ADC_35 147 +#define ADC_34 142 +#define ADC_33 137 +#define ADC_32 131 +#define ADC_31 126 +#define ADC_30 121 +#define ADC_29 116 +#define ADC_28 111 +#define ADC_27 105 +#define ADC_26 100 +#define ADC_25 95 +#define ADC_24 90 +#define ADC_23 84 +#define ADC_22 79 +#define ADC_21 74 +#define ADC_20 69 + +#define ADC_100p ADC_42 // the ADC value for 100% full (resting) +#define ADC_75p ADC_40 // the ADC value for 75% full (resting) +#define ADC_50p ADC_38 // the ADC value for 50% full (resting) +#define ADC_25p ADC_35 // the ADC value for 25% full (resting) +#define ADC_0p ADC_30 // the ADC value for 0% full (resting) +#define ADC_LOW ADC_30 // When do we start ramping down +#define ADC_CRIT ADC_27 // When do we shut the light off + + +/********************** Offtime capacitor calibration ********************/ +// Values are between 1 and 255, and can be measured with offtime-cap.c +// See battcheck/otc-readings.txt for reference values. +// These #defines are the edge boundaries, not the center of the target. +#ifdef OFFTIM3 +// The OTC value 0.5s after being disconnected from power +// (anything higher than this is a "short press") +#define CAP_SHORT 190 +// The OTC value 1.5s after being disconnected from power +// Between CAP_MED and CAP_SHORT is a "medium press" +#define CAP_MED 94 +// Below CAP_MED is a long press +#else +// The OTC value 1.0s after being disconnected from power +// Anything higher than this is a short press, lower is a long press +#define CAP_SHORT 115 +#endif + diff --git a/arch/delay.h b/arch/delay.h new file mode 100644 index 0000000..502e6ab --- /dev/null +++ b/arch/delay.h @@ -0,0 +1,58 @@ +// tk-delay.h: Smaller, more flexible _delay_ms() functions. +// Copyright (C) 2015-2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#ifdef OWN_DELAY +#include "tk-attiny.h" +#include +#ifdef USE_DELAY_MS +// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input +#define delay_ms _delay_ms +void _delay_ms(uint16_t n) +{ + // TODO: make this take tenths of a ms instead of ms, + // for more precise timing? + //#ifdef USE_FINE_DELAY + //if (n==0) { _delay_loop_2(BOGOMIPS/3); } + //else { + // while(n-- > 0) _delay_loop_2(BOGOMIPS); + //} + //#else + while(n-- > 0) _delay_loop_2(BOGOMIPS); + //#endif +} +#endif +#if defined(USE_FINE_DELAY) || defined(USE_DELAY_ZERO) +#define delay_zero _delay_zero +void _delay_zero() { + //_delay_loop_2((BOGOMIPS/3) & 0xff00); + _delay_loop_2(DELAY_ZERO_TIME); +} +#endif +#ifdef USE_DELAY_4MS +#ifndef delay_4ms +#define delay_4ms _delay_4ms +void _delay_4ms(uint8_t n) // because it saves a bit of ROM space to do it this way +{ + while(n-- > 0) _delay_loop_2(BOGOMIPS*4); +} +#endif +#endif +#ifdef USE_DELAY_S +#define delay_s _delay_s +void _delay_s() // because it saves a bit of ROM space to do it this way +{ + #ifdef USE_DELAY_4MS + _delay_4ms(250); + #else + #ifdef USE_DELAY_MS + _delay_ms(1000); + #endif + #endif +} +#endif +#else +#include +#endif + diff --git a/arch/mcu.h b/arch/mcu.h new file mode 100644 index 0000000..9532ed5 --- /dev/null +++ b/arch/mcu.h @@ -0,0 +1,157 @@ +// tk-attiny.h: Attiny portability header. +// Copyright (C) 2014-2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +// This helps abstract away the differences between various attiny MCUs. + +// Choose your MCU here, or in the main .c file, or in the build script +//#define ATTINY 13 +//#define ATTINY 25 + +/******************** hardware-specific values **************************/ +#if (ATTINY == 13) + #define F_CPU 4800000UL + //#define EEPSIZE 64 + #define V_REF REFS0 + #define BOGOMIPS 950 + #define ADMUX_VCC 0b00001100 + #define DELAY_ZERO_TIME 252 + #define SWITCH_PORT PINB // PINA or PINB or PINC + #define VOLTAGE_ADC_DIDR DIDR0 // this MCU only has one DIDR +#elif (ATTINY == 25) + // TODO: Use 6.4 MHz instead of 8 MHz? + #define F_CPU 8000000UL + //#define EEPSIZE 128 + #define V_REF REFS1 + #define BOGOMIPS (F_CPU/4000) + #define ADMUX_VCC 0b00001100 + #define ADMUX_THERM 0b10001111 + #define DELAY_ZERO_TIME 1020 + #define SWITCH_PORT PINB // PINA or PINB or PINC + #define VOLTAGE_ADC_DIDR DIDR0 // this MCU only has one DIDR +#elif (ATTINY == 85) + // TODO: Use 6.4 MHz instead of 8 MHz? + #define F_CPU 8000000UL + //#define EEPSIZE 512 + #define V_REF REFS1 + #define BOGOMIPS (F_CPU/4000) + // (1 << V_REF) | (0 << ADLAR) | (VCC_CHANNEL) + #define ADMUX_VCC 0b00001100 + // (1 << V_REF) | (0 << ADLAR) | (THERM_CHANNEL) + #define ADMUX_THERM 0b10001111 + #define DELAY_ZERO_TIME 1020 + #define SWITCH_PORT PINB // PINA or PINB or PINC + #define VOLTAGE_ADC_DIDR DIDR0 // this MCU only has one DIDR +#elif (ATTINY == 1634) + #define F_CPU 8000000UL + #define V_REF REFS1 + #define BOGOMIPS (F_CPU/4000) + // DS table 19-3, 19-4, 1.1V ref / VCC + #define ADMUX_VCC 0b00001101 + // (1 << V_REF) | (THERM_CHANNEL) + // DS table 19-3, 19-4, internal sensor / 1.1V ref + #define ADMUX_THERM 0b10001110 + #define DELAY_ZERO_TIME 1020 + //#define SWITCH_PORT PINA // set this in hwdef + //#define VOLTAGE_ADC_DIDR DIDR0 // set this in hwdef +#elif (ATTINY == 412) || (ATTINY == 416) || (ATTINY == 417) || (ATTINY == 816) || (ATTINY == 817) || (ATTINY == 1616) || (ATTINY == 1617) || (ATTINY == 3216) || (ATTINY == 3217) + #define AVRXMEGA3 + #define F_CPU 10000000UL + #define BOGOMIPS (F_CPU/4700) + #define EEPSIZE 128 + #define DELAY_ZERO_TIME 1020 +#else + #error Hey, you need to define ATTINY. +#endif + +// auto-detect eeprom size from avr-libc headers +#ifndef EEPSIZE +#ifdef E2SIZE +#define EEPSIZE E2SIZE +#else +#define EEPSIZE (E2END+1) +#endif +#endif + + +#include + +/******************** I/O pin and register layout ************************/ +#ifdef HWDEFFILE +#include "tk.h" +#include incfile(HWDEFFILE) +#endif + +#if 0 // placeholder + +#elif defined(NANJG_LAYOUT) +#include "hwdef-nanjg.h" + +#elif defined(FET_7135_LAYOUT) +#include "hwdef-FET_7135.h" + +#elif defined(TRIPLEDOWN_LAYOUT) +#include "hwdef-Tripledown.h" + +#elif defined(FERRERO_ROCHER_LAYOUT) +#include "hwdef-Ferrero_Rocher.h" + +#endif // no more recognized driver types + +#ifndef LAYOUT_DEFINED +#error Hey, you need to define an I/O pin layout. +#endif + +#if (ATTINY==13) + // no changes needed +#elif (ATTINY==25) || (ATTINY==45) || (ATTINY==85) + // use clock_prescale_set(n) instead; it's safer + //#define CLOCK_DIVIDER_SET(n) {CLKPR = 1<>6); // ADLAR=1 + ADCSRA |= 0x10; // clear ADIF flag, else only first reading works + return ADC; // ADLAR=0 +} +#endif + +#ifdef USE_BATTCHECK +#ifdef BATTCHECK_4bars +PROGMEM const uint8_t voltage_blinks[] = { + // 0 blinks for less than 1% + ADC_0p, // 1 blink for 1%-25% + ADC_25p, // 2 blinks for 25%-50% + ADC_50p, // 3 blinks for 50%-75% + ADC_75p, // 4 blinks for 75%-100% + ADC_100p, // 5 blinks for >100% + 255, // Ceiling, don't remove (6 blinks means "error") +}; +#endif // BATTCHECK_4bars +#ifdef BATTCHECK_8bars +PROGMEM const uint8_t voltage_blinks[] = { + // 0 blinks for less than 1% + ADC_30, // 1 blink for 1%-12.5% + ADC_33, // 2 blinks for 12.5%-25% + ADC_35, // 3 blinks for 25%-37.5% + ADC_37, // 4 blinks for 37.5%-50% + ADC_38, // 5 blinks for 50%-62.5% + ADC_39, // 6 blinks for 62.5%-75% + ADC_40, // 7 blinks for 75%-87.5% + ADC_41, // 8 blinks for 87.5%-100% + ADC_42, // 9 blinks for >100% + 255, // Ceiling, don't remove (10 blinks means "error") +}; +#endif // BATTCHECK_8bars +#ifdef BATTCHECK_VpT +/* +PROGMEM const uint8_t v_whole_blinks[] = { + // 0 blinks for (shouldn't happen) + 0, // 1 blink for (shouldn't happen) + ADC_20, // 2 blinks for 2V + ADC_30, // 3 blinks for 3V + ADC_40, // 4 blinks for 4V + 255, // Ceiling, don't remove +}; +PROGMEM const uint8_t v_tenth_blinks[] = { + // 0 blinks for less than 1% + ADC_30, + ADC_33, + ADC_35, + ADC_37, + ADC_38, + ADC_39, + ADC_40, + ADC_41, + ADC_42, + 255, // Ceiling, don't remove +}; +*/ +PROGMEM const uint8_t voltage_blinks[] = { + // 0 blinks for (shouldn't happen) + ADC_25,(2<<5)+5, + ADC_26,(2<<5)+6, + ADC_27,(2<<5)+7, + ADC_28,(2<<5)+8, + ADC_29,(2<<5)+9, + ADC_30,(3<<5)+0, + ADC_31,(3<<5)+1, + ADC_32,(3<<5)+2, + ADC_33,(3<<5)+3, + ADC_34,(3<<5)+4, + ADC_35,(3<<5)+5, + ADC_36,(3<<5)+6, + ADC_37,(3<<5)+7, + ADC_38,(3<<5)+8, + ADC_39,(3<<5)+9, + ADC_40,(4<<5)+0, + ADC_41,(4<<5)+1, + ADC_42,(4<<5)+2, + ADC_43,(4<<5)+3, + ADC_44,(4<<5)+4, + 255, (1<<5)+1, // Ceiling, don't remove +}; +inline uint8_t battcheck() { + // Return an composite int, number of "blinks", for approximate battery charge + // Uses the table above for return values + // Return value is 3 bits of whole volts and 5 bits of tenths-of-a-volt + uint8_t i, voltage; + voltage = get_voltage(); + // figure out how many times to blink + for (i=0; + voltage > pgm_read_byte(voltage_blinks + i); + i += 2) {} + return pgm_read_byte(voltage_blinks + i + 1); +} +#else // #ifdef BATTCHECK_VpT +inline uint8_t battcheck() { + // Return an int, number of "blinks", for approximate battery charge + // Uses the table above for return values + uint8_t i, voltage; + voltage = get_voltage(); + // figure out how many times to blink + for (i=0; + voltage > pgm_read_byte(voltage_blinks + i); + i ++) {} + return i; +} +#endif // BATTCHECK_VpT +#endif + -- cgit v1.2.3