aboutsummaryrefslogtreecommitdiff
path: root/arch/attiny1616.h
blob: 940973ee83763469bc7ca64ad2b20aafe8f64f28 (plain)
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();