1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
// arch/attiny1616.h: attiny1616 support header
// Copyright (C) 2023 Selene ToyKeeper
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
// FIXME: remove this
#define AVRXMEGA3
////////// clock speed / delay stuff //////////
#define F_CPU 10000000UL
#define BOGOMIPS (F_CPU/4350)
#define DELAY_ZERO_TIME 1020
inline void mcu_clock_speed();
///// clock dividers
// this should work, but needs further validation
inline void clock_prescale_set(uint8_t n);
// TODO: allow hwdef to define a base clock speed,
// and adjust these values accordingly
typedef enum
{
// Actual clock is 20 MHz, but assume that 10 MHz is the top speed and work from there
// TODO: measure PWM speed and power use at 1.25/2.5/5/10 MHz, to determine which speeds are optimal
clock_div_1 = (CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm), // 10 MHz
clock_div_2 = (CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm), // 5 MHz
clock_div_4 = (CLKCTRL_PDIV_8X_gc | CLKCTRL_PEN_bm), // 2.5 MHz
clock_div_8 = (CLKCTRL_PDIV_16X_gc | CLKCTRL_PEN_bm), // 1.25 MHz
clock_div_16 = (CLKCTRL_PDIV_32X_gc | CLKCTRL_PEN_bm), // 625 kHz
clock_div_32 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz, max without changing to the 32 kHz ULP
clock_div_64 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz
clock_div_128 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz
clock_div_256 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm) // 312 kHz
} clock_div_t;
////////// DAC controls //////////
#define DAC_LVL DAC0.DATA // 0 to 255, for 0V to Vref
#define DAC_VREF VREF.CTRLA // 0.55V, 1.1V, 1.5V, 2.5V, or 4.3V
// set only the relevant bits of the Vref register
#define mcu_set_dac_vref(x) \
VREF.CTRLA = x | (VREF.CTRLA & (~VREF_DAC0REFSEL_gm));
// Vref values
// (for the DAC bits, not the ADC bits)
#define V05 V055
#define V055 VREF_DAC0REFSEL_0V55_gc
#define V11 VREF_DAC0REFSEL_1V1_gc
#define V25 VREF_DAC0REFSEL_2V5_gc
#define V43 VREF_DAC0REFSEL_4V34_gc
#define V15 VREF_DAC0REFSEL_1V5_gc
////////// ADC voltage / temperature //////////
// set only the relevant bits of the Vref register
#define mcu_set_adc0_vref(x) \
VREF.CTRLA = x | (VREF.CTRLA & (~VREF_ADC0REFSEL_gm));
#define hwdef_set_admux_therm mcu_set_admux_therm
inline void mcu_set_admux_therm();
#define hwdef_set_admux_voltage mcu_set_admux_voltage
inline void mcu_set_admux_voltage();
inline void mcu_adc_sleep_mode();
inline void mcu_adc_start_measurement();
//inline void mcu_adc_on();
inline void mcu_adc_off();
#define ADC_vect ADC0_RESRDY_vect
inline void mcu_adc_vect_clear();
//// both readings are left-aligned
//inline uint16_t mcu_adc_result();
// read ADC differently for temperature and voltage
#define MCU_ADC_RESULT_PER_TYPE
inline uint16_t mcu_adc_result_temp();
inline uint16_t mcu_adc_result_volts();
// return Volts * 40, range 0 to 6.375V
#define voltage_raw2cooked mcu_vdd_raw2cooked
inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement);
inline uint8_t mcu_vdivider_raw2cooked(uint16_t measurement);
// return (temp in Kelvin << 6)
#define temp_raw2cooked mcu_temp_raw2cooked
inline uint16_t mcu_temp_raw2cooked(uint16_t measurement);
inline uint8_t mcu_adc_lsb();
////////// WDT //////////
inline void mcu_wdt_active();
inline void mcu_wdt_standby();
inline void mcu_wdt_stop();
// *** Note for the AVRXMEGA3 (1-Series, eg 816 and 817), the WDT
// is not used for time-based interrupts. A new peripheral, the
// Periodic Interrupt Timer ("PIT") is used for this purpose.
#define WDT_vect RTC_PIT_vect
inline void mcu_wdt_vect_clear();
////////// PCINT - pin change interrupt (e-switch) //////////
// set these in hwdef
//#define SWITCH_PORT PINA
//#define SWITCH_VECT PCINT0_vect
inline void mcu_switch_vect_clear();
inline void mcu_pcint_on();
inline void mcu_pcint_off();
////////// misc //////////
void reboot();
inline void prevent_reboot_loop();
|