Add support for ATtiny 3224/7 (#1535)

* Add hal for megaAvrs

* Add mcu selector setting

* Register hal

* Pull up pins to save power

* Remove dead code

* Add before/after sleep delegates

* Remove pin turn stable state setting

* Make hardware messages mysensors alike

* Enable route size reduction for devices with smaller eeprom

* Add macro for routes size to keywords

* Fix keyworkds.txt - using tabs instead of spaces

* Remove tinyAVR hardware debugging

* Remove unused macros

* Remove .history folder

* Fix formatting according to astyle

* Remove unused count variable

* Update MyTransportHAL.cpp

---------

Co-authored-by: Olivier <tekka007@users.noreply.github.com>
This commit is contained in:
lyuboasenov
2023-10-12 09:47:53 +03:00
committed by GitHub
parent aa3583c50f
commit 8d45e7bad7
13 changed files with 579 additions and 27 deletions

View File

@@ -24,15 +24,15 @@
doNothing:
nop
.size doNothing, .-doNothing
#elif defined(ARDUINO_ARCH_NRF5)
/* workaround to prevent compiler error */
.thumb_func
doNothing:
nop
.size doNothing, .-doNothing
#elif defined(ARDUINO_ARCH_AVR)
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
#include "hal/crypto/AVR/drivers/SHA256/SHA256.S"

View File

@@ -2607,6 +2607,12 @@
*/
#define ARDUINO_ARCH_AVR
/**
* @def ARDUINO_ARCH_MEGAAVR
* @brief Automatically set when building for megaAVR targets
*/
#define ARDUINO_ARCH_MEGAAVR
/**
* @def ARDUINO_ARCH_STM32F1
* @brief Automatically set when building for STM32F1 targets
@@ -2778,5 +2784,12 @@
#define MY_SX126x_MAX_POWER_LEVEL_DBM
// SOFT-SPI
#define MY_SOFTSPI
/**
* @def MY_ROUTES_SIZE
* @brief Specifies the size allocated for routing table
*/
#define MY_ROUTES_SIZE
#endif
/** @}*/ // End of MyConfig group

View File

@@ -63,6 +63,9 @@
#elif defined(ARDUINO_ARCH_AVR)
#include "hal/architecture/AVR/MyHwAVR.cpp"
#include "hal/crypto/AVR/MyCryptoAVR.cpp"
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "hal/architecture/AVR/MyHwMegaAVR.cpp"
#include "hal/crypto/AVR/MyCryptoAVR.cpp"
#elif defined(ARDUINO_ARCH_SAMD)
#include "drivers/extEEPROM/extEEPROM.cpp"
#include "hal/architecture/SAMD/MyHwSAMD.cpp"
@@ -335,8 +338,8 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
// activate feature based on architecture
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_NRF5) || defined(ARDUINO_ARCH_STM32F1) || defined(TEENSYDUINO) || defined(__linux__) || defined(__ASR6501__) || defined (__ASR6502__)
#define MY_RAM_ROUTING_TABLE_ENABLED
#elif defined(ARDUINO_ARCH_AVR)
#if defined(__avr_atmega1280__) || defined(__avr_atmega1284__) || defined(__avr_atmega2560__)
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
#if defined(__avr_atmega1280__) || defined(__avr_atmega1284__) || defined(__avr_atmega2560__) || defined(__avr_attiny3224__) || defined(__avr_attiny3227__)
// >4kb, enable it
#define MY_RAM_ROUTING_TABLE_ENABLED
#else
@@ -457,6 +460,8 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
// HW mains
#if defined(ARDUINO_ARCH_AVR)
#include "hal/architecture/AVR/MyMainAVR.cpp"
#elif defined(ARDUINO_ARCH_MEGAAVR)
#include "hal/architecture/AVR/MyMainAVR.cpp"
#elif defined(ARDUINO_ARCH_SAMD)
#include "hal/architecture/SAMD/MyMainSAMD.cpp"
#elif defined(ARDUINO_ARCH_ESP8266)

View File

@@ -163,7 +163,7 @@
#define MY_CAP_ARCH "E"
#elif defined(ARDUINO_ARCH_ESP32)
#define MY_CAP_ARCH "F"
#elif defined(ARDUINO_ARCH_AVR)
#elif defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
#define MY_CAP_ARCH "A"
#elif defined(ARDUINO_ARCH_STM32F1)
#define MY_CAP_ARCH "M"

View File

@@ -32,22 +32,26 @@
#define MyEepromAddresses_h
// EEPROM variable sizes, in bytes
#define SIZE_NODE_ID (1u) //!< Size node ID
#define SIZE_PARENT_NODE_ID (1u) //!< Size parent node ID
#define SIZE_DISTANCE (1u) //!< Size GW distance
#define SIZE_ROUTES (256u) //!< Size routing table
#define SIZE_CONTROLLER_CONFIG (23u) //!< Size controller config
#define SIZE_PERSONALIZATION_CHECKSUM (1u) //!< Size personalization checksum
#define SIZE_FIRMWARE_TYPE (2u) //!< Size firmware type
#define SIZE_FIRMWARE_VERSION (2u) //!< Size firmware version
#define SIZE_FIRMWARE_BLOCKS (2u) //!< Size firmware blocks
#define SIZE_FIRMWARE_CRC (2u) //!< Size firmware CRC
#define SIZE_NODE_ID (1u) //!< Size node ID
#define SIZE_PARENT_NODE_ID (1u) //!< Size parent node ID
#define SIZE_DISTANCE (1u) //!< Size GW distance
#ifdef MY_ROUTES_SIZE
#define SIZE_ROUTES (MY_ROUTES_SIZE) //!< Size routing table 148 is the
#else
#define SIZE_ROUTES (256u) //!< Size routing table 148 is the
#endif
#define SIZE_CONTROLLER_CONFIG (23u) //!< Size controller config
#define SIZE_PERSONALIZATION_CHECKSUM (1u) //!< Size personalization checksum
#define SIZE_FIRMWARE_TYPE (2u) //!< Size firmware type
#define SIZE_FIRMWARE_VERSION (2u) //!< Size firmware version
#define SIZE_FIRMWARE_BLOCKS (2u) //!< Size firmware blocks
#define SIZE_FIRMWARE_CRC (2u) //!< Size firmware CRC
#define SIZE_SIGNING_REQUIREMENT_TABLE (32u) //!< Size signing requirement table
#define SIZE_WHITELIST_REQUIREMENT_TABLE (32u) //!< Size whitelist requirement table
#define SIZE_SIGNING_SOFT_HMAC_KEY (32u) //!< Size soft signing HMAC key
#define SIZE_SIGNING_SOFT_SERIAL (9u) //!< Size soft signing serial
#define SIZE_RF_ENCRYPTION_AES_KEY (16u) //!< Size RF AES encryption key
#define SIZE_NODE_LOCK_COUNTER (1u) //!< Size node lock counter
#define SIZE_SIGNING_SOFT_HMAC_KEY (32u) //!< Size soft signing HMAC key
#define SIZE_SIGNING_SOFT_SERIAL (9u) //!< Size soft signing serial
#define SIZE_RF_ENCRYPTION_AES_KEY (16u) //!< Size RF AES encryption key
#define SIZE_NODE_LOCK_COUNTER (1u) //!< Size node lock counter
/** @brief EEPROM start address */

View File

@@ -4,7 +4,7 @@
/* Local data and function prototypes */
static uint8_t device_pin;
#ifdef ARDUINO_ARCH_AVR
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
static volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN;
#endif
static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc);
@@ -416,7 +416,7 @@ static uint8_t sha204c_check_crc(uint8_t *response)
void atsha204_init(uint8_t pin)
{
#if defined(ARDUINO_ARCH_AVR)
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin
uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers

View File

@@ -225,7 +225,7 @@
/* Low level HW access macros */
/* function calls is not working, as it will have too much overhead */
#if !defined(ARDUINO_ARCH_AVR) // For everything else than AVR use pinMode / digitalWrite
#if !defined(ARDUINO_ARCH_AVR) && !defined(ARDUINO_ARCH_MEGAAVR) // For everything else than AVR use pinMode / digitalWrite
#define SHA204_SET_OUTPUT() pinMode(device_pin, OUTPUT)
#define SHA204_SET_INPUT() pinMode(device_pin, INPUT)
#define SHA204_POUT_HIGH() digitalWrite(device_pin, HIGH)

View File

@@ -1343,6 +1343,8 @@ static void probe_and_print_peripherals(void)
F("+--------------+--------------+--------------+------------------------------+--------+"));
#if defined(ARDUINO_ARCH_AVR)
Serial.print(F("| AVR | DETECTED | N/A | "));
#elif defined(ARDUINO_ARCH_MEGAAVR)
Serial.print(F("| megaAVR | DETECTED | N/A | "));
#elif defined(ARDUINO_ARCH_ESP8266)
Serial.print(F("| ESP8266 | DETECTED | N/A | "));
#elif defined(ARDUINO_ARCH_SAMD)
@@ -1869,4 +1871,4 @@ static void dump_detailed_atsha204a_configuration(void)
#define RESET_EEPROM_PERSONALIZATION
#endif
/** @}*/
/** @}*/

View File

@@ -11,7 +11,7 @@
atsha204Class::atsha204Class(uint8_t pin)
{
#if defined(ARDUINO_ARCH_AVR)
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin
uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers

View File

@@ -283,7 +283,7 @@
/* Low level HW access macros */
/* function calls is not working, as it will have too much overhead */
#if !defined(ARDUINO_ARCH_AVR) // For everything else than AVR use pinMode / digitalWrite
#if !defined(ARDUINO_ARCH_AVR) && !defined(ARDUINO_ARCH_MEGAAVR) // For everything else than AVR use pinMode / digitalWrite
#define SHA204_SET_OUTPUT() pinMode(device_pin, OUTPUT)
#define SHA204_SET_INPUT() pinMode(device_pin, INPUT)
#define SHA204_POUT_HIGH() digitalWrite(device_pin, HIGH)
@@ -304,7 +304,7 @@ class atsha204Class
{
private:
uint8_t device_pin;
#ifdef ARDUINO_ARCH_AVR
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN;
#endif
void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc);

View File

@@ -0,0 +1,432 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2022 Sensnology AB
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include "MyHwMegaAVR.h"
void hwRtcInit(void)
{
// Initialize RTC to 1kHz internal oscillator
while (RTC.STATUS > 0) { } /* Wait for all register to be synchronized */
RTC.CTRLA = RTC_PRESCALER_DIV32768_gc /* 32768 */
| 0 << RTC_RTCEN_bp /* Enable: disabled */
| 0 << RTC_RUNSTDBY_bp; /* Run In Standby: disabled */
RTC.CLKSEL = RTC_CLKSEL_INT1K_gc; /* 32KHz divided by 32 */
}
bool hwInit(void)
{
hwRtcInit();
#if !defined(MY_DISABLED_SERIAL)
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#if defined(MY_GATEWAY_SERIAL)
while (!MY_SERIALDEVICE) {}
#endif
#endif
return true;
}
#define PIT_SLEEP_FOREVER 0
volatile uint8_t _wokeUpByInterrupt =
INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu.
volatile uint8_t _wakeUp1Interrupt =
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback.
volatile uint8_t _wakeUp2Interrupt =
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback.
static uint32_t sleepRemainingMs = 0ul;
void wakeUp1(void)
{
// Disable sleep. When an interrupt occurs after attachInterrupt,
// but before sleeping the CPU would not wake up.
// Ref: http://playground.arduino.cc/Learning/ArduinoSleepCode
sleep_disable();
detachInterrupt(_wakeUp1Interrupt);
// First interrupt occurred will be reported only
if (INVALID_INTERRUPT_NUM == _wokeUpByInterrupt) {
_wokeUpByInterrupt = _wakeUp1Interrupt;
}
}
void wakeUp2(void)
{
sleep_disable();
detachInterrupt(_wakeUp2Interrupt);
// First interrupt occurred will be reported only
if (INVALID_INTERRUPT_NUM == _wokeUpByInterrupt) {
_wokeUpByInterrupt = _wakeUp2Interrupt;
}
}
inline bool interruptWakeUp(void)
{
return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM;
}
void clearPendingInterrupt(const uint8_t interrupt)
{
// TODO: Check do I need that
//EIFR = _BV(interrupt);
}
void pit_reset()
{
RTC.PITCTRLA = 0;
RTC.PITINTCTRL = 0;
}
void hwPitRtcInit(uint8_t cycles)
{
while (RTC.PITSTATUS > 0) { }/* Wait for all register to be synchronized */
/*
RTC_PERIOD_CYC16_gc = (0x03<<3), /* RTC Clock Cycles 16
RTC_PERIOD_CYC32_gc = (0x04<<3), /* RTC Clock Cycles 32
RTC_PERIOD_CYC64_gc = (0x05<<3), /* RTC Clock Cycles 64
RTC_PERIOD_CYC128_gc = (0x06<<3), /* RTC Clock Cycles 128
RTC_PERIOD_CYC256_gc = (0x07<<3), /* RTC Clock Cycles 256
RTC_PERIOD_CYC512_gc = (0x08<<3), /* RTC Clock Cycles 512
RTC_PERIOD_CYC1024_gc = (0x09<<3), /* RTC Clock Cycles 1024
RTC_PERIOD_CYC2048_gc = (0x0A<<3), /* RTC Clock Cycles 2048
RTC_PERIOD_CYC4096_gc = (0x0B<<3), /* RTC Clock Cycles 4096
RTC_PERIOD_CYC8192_gc = (0x0C<<3), /* RTC Clock Cycles 8192
RTC_PERIOD_CYC16384_gc = (0x0D<<3), /* RTC Clock Cycles 16384
RTC_PERIOD_CYC32768_gc = (0x0E<<3), /* RTC Clock Cycles 32768
*/
RTC.PITCTRLA = cycles
| 1 << RTC_PITEN_bp; /* Enable: enabled */
RTC.PITINTCTRL = 1 << RTC_PI_bp; /* Periodic Interrupt: enabled */
}
uint8_t getSleepingPeriod(uint32_t ms)
{
for (uint8_t period = 14u; period > 2; --period) {
const uint16_t comparatorMS = (32768 >> (15 - period));
if (ms >= comparatorMS) {
return period;
}
}
return 3; // 16ms with 1kHz internal oscillator
}
uint32_t hwPowerDown(uint32_t ms)
{
// Let serial prints finish (debug, log etc)
#ifndef MY_DISABLED_SERIAL
MY_SERIALDEVICE.flush();
#endif
if (_beforeSleep) {
_beforeSleep();
}
ADC0.CTRLA &= ~ADC_ENABLE_bm; // ADC off
if (ms != PIT_SLEEP_FOREVER) {
// Sleeping with watchdog only supports multiples of 16ms.
// Round up to next multiple of 16ms, to assure we sleep at least the
// requested amount of time. Sleep of 0ms will not sleep at all!
ms += 15u;
while (!interruptWakeUp() && ms >= 16) {
uint8_t period = getSleepingPeriod(ms);
const uint16_t comparatorMS = 32768 >> (15 - period);
cli();
hwPitRtcInit(period << 3);
sei();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
sleep_disable();
cli();
RTC.PITCTRLA = 0; /* RTC Clock Cycles Off, Enable: disabled */
sei();
ms -= comparatorMS;
}
} else {
// Eternal sleep
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
sleep_disable();
sei();
}
ADC0.CTRLA |= ADC_ENABLE_bm; // ADC on
if (_afterSleep) {
_afterSleep();
}
if (interruptWakeUp()) {
return ms;
}
return 0ul;
}
ISR (RTC_PIT_vect)
{
RTC.PITINTFLAGS = 1; // Clear interrupt flag
}
int8_t hwSleep(uint32_t ms)
{
// Return what woke the mcu.
// Default: no interrupt triggered, timer wake up
int8_t ret = MY_WAKE_UP_BY_TIMER;
sleepRemainingMs = 0ul;
if (ms > 0u) {
// sleep for defined time
sleepRemainingMs = hwPowerDown(ms);
} else {
// sleep until ext interrupt triggered
hwPowerDown(PIT_SLEEP_FOREVER);
}
if (interruptWakeUp()) {
ret = static_cast<int8_t>(_wokeUpByInterrupt);
}
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
return ret;
}
int8_t hwSleep(const uint8_t interrupt, const uint8_t mode, uint32_t ms)
{
return hwSleep(interrupt, mode, INVALID_INTERRUPT_NUM, 0u, ms);
}
int8_t hwSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
const uint8_t mode2,
uint32_t ms)
{
// ATMega328P supports following modes to wake from sleep: LOW, CHANGE, RISING, FALLING
// Datasheet states only LOW can be used with INT0/1 to wake from sleep, which is incorrect.
// Ref: http://gammon.com.au/interrupts
// Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt()
// and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled!
cli();
// attach interrupts
_wakeUp1Interrupt = interrupt1;
_wakeUp2Interrupt = interrupt2;
// Attach external interrupt handlers, and clear any pending interrupt flag
// to prevent waking immediately again.
// Ref: https://forum.arduino.cc/index.php?topic=59217.0
if (interrupt1 != INVALID_INTERRUPT_NUM) {
clearPendingInterrupt(interrupt1);
attachInterrupt(interrupt1, wakeUp1, mode1);
}
if (interrupt2 != INVALID_INTERRUPT_NUM) {
clearPendingInterrupt(interrupt2);
attachInterrupt(interrupt2, wakeUp2, mode2);
}
sleepRemainingMs = 0ul;
if (ms > 0u) {
// sleep for defined time
sleepRemainingMs = hwPowerDown(ms);
} else {
// sleep until ext interrupt triggered
hwPowerDown(PIT_SLEEP_FOREVER);
}
// Assure any interrupts attached, will get detached when they did not occur.
if (interrupt1 != INVALID_INTERRUPT_NUM) {
detachInterrupt(interrupt1);
}
if (interrupt2 != INVALID_INTERRUPT_NUM) {
detachInterrupt(interrupt2);
}
// Return what woke the mcu.
// Default: no interrupt triggered, timer wake up
int8_t ret = MY_WAKE_UP_BY_TIMER;
if (interruptWakeUp()) {
ret = static_cast<int8_t>(_wokeUpByInterrupt);
}
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
return ret;
}
uint32_t hwGetSleepRemaining(void)
{
return sleepRemainingMs;
}
inline void hwRandomNumberInit(void)
{
// This function initializes the random number generator with a seed
// of 32 bits. This method is good enough to earn FIPS 140-2 conform
// random data. This should reach to generate 32 Bit for randomSeed().
uint32_t seed = 0;
uint32_t timeout = millis() + 20;
// Trigger floating effect of an unconnected pin
pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT_PULLUP);
pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT);
delay(10);
// Generate 32 bits of datas
for (uint8_t i=0; i<32; i++) {
const int pinValue = analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN);
// Wait until the analog value has changed
while ((pinValue == analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)) && (timeout>=millis())) {
seed ^= (millis() << i);
// Check of data generation is slow
if (timeout<=millis()) {
// Trigger pin again
pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT_PULLUP);
pinMode(MY_SIGNING_SOFT_RANDOMSEED_PIN, INPUT);
// Pause a short while
delay(seed % 10);
timeout = millis() + 20;
}
}
}
randomSeed(seed);
}
bool hwUniqueID(unique_id_t *uniqueID)
{
// padding
(void)memset(uniqueID, MY_HWID_PADDING_BYTE, sizeof(unique_id_t));
// no unique ID for non-PB AVR, use HW specifics for diversification
*((uint8_t *)uniqueID) = SIGNATURE_2;
*((uint8_t *)uniqueID + 1) = SIGNATURE_1;
*((uint8_t *)uniqueID + 2) = SIGNATURE_0;
*((uint8_t *)uniqueID + 3) = SIGROW.DEVICEID0;
*((uint8_t *)uniqueID + 4) = SIGROW.DEVICEID1;
*((uint8_t *)uniqueID + 5) = SIGROW.DEVICEID2;
// SIGROW.SERNUM[9:0].
for(uint8_t idx = 0; idx < 10; idx++) {
*((uint8_t *)uniqueID + 6 + idx) = *(&SIGROW.SERNUM0 + idx);
}
return true; // unique ID returned
}
uint16_t hwCPUVoltage(void)
{
analogReference(INTERNAL1V024);
for (uint8_t i = 0; i < 10; i++) {
analogRead(ADC_VDDDIV10);
}
uint16_t adc = analogRead(ADC_VDDDIV10);
uint16_t voltage = adc * (uint16_t) 10.24; // value in mV
return voltage; // value in mV
}
uint16_t hwCPUFrequency(void)
{
#ifdef F_CPU
return F_CPU / 100000UL;
#else
cli();
const uint8_t rtcPitCtrlA = RTC.PITCTRLA;
const uint8_t rtcPitIntCtrl = RTC.PITINTCTRL;
const uint8_t rtcPitPitIntFlags = RTC.PITINTFLAGS;
const uint8_t tcaEvCtrl = TCA0.SINGLE.EVCTRL;
const uint8_t tcaCtrlA = TCA0.SINGLE.CTRLA;
// setup timer1
TCA0.SINGLE.CNT = 0x0; /* Count: 0x0 */
TCA0.SINGLE.EVCTRL = 0 << TCA_SINGLE_CNTAEI_bp /* Count on Event Input A: disabled */
| 0 << TCA_SINGLE_CNTBEI_bp /* Count on Event Input B: disabled */
| TCA_SINGLE_EVACTA_CNT_POSEDGE_gc /* Count on positive edge event */
| TCA_SINGLE_EVACTB_UPDOWN_gc; /* Count on prescaled clock. Event controls count direction.
Up-count when event line is 0, down-count when event line
is 1. */
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc /* System Clock */
| 1 << TCA_SINGLE_ENABLE_bp /* Module Enable: enabled */
| 0 << TCA_SINGLE_RUNSTDBY_bp; /* Run Standby: disabled */
// set pit
while (RTC.PITSTATUS >
0) {} /* Wait for all register to be synchronized */
RTC.PITCTRLA = RTC_PERIOD_CYC16384_gc /* RTC Clock Cycles 16384 - 500ms */
| 1 << RTC_PITEN_bp; /* Enable: enabled */
RTC.PITINTCTRL = 1 << RTC_PI_bp; /* Periodic Interrupt: enabled */
// wait for pit to interrupt
while (bit_is_clear(RTC.PITINTFLAGS, RTC_PI_bp)) {};
TCA0.SINGLE.CTRLA = 0; /* Enable: disabled */
RTC.PITCTRLA &= ~(1 << RTC_PITEN_bp); /* Enable: disabled */
sei();
const uint16_t result = (TCA0.SINGLE.CNT * 2048UL) / 100000UL;
// Reset timers
RTC.PITCTRLA = rtcPitCtrlA;
RTC.PITINTCTRL = rtcPitIntCtrl;
RTC.PITINTFLAGS = rtcPitPitIntFlags;
TCA0.SINGLE.EVCTRL = tcaEvCtrl;
TCA0.SINGLE.CTRLA = tcaCtrlA;
// return frequency in 1/10MHz (accuracy +- 10%)
return result;
#endif
}
int8_t hwCPUTemperature(void)
{
analogReference(INTERNAL1V024);
uint16_t adc_reading = analogRead(ADC_TEMPERATURE);
int8_t sigrow_offset = SIGROW.TEMPSENSE1; // Read signed offset from signature row
uint8_t sigrow_gain = SIGROW.TEMPSENSE0; // Read unsigned gain/slope from signature row
uint32_t temp = adc_reading - sigrow_offset;
temp *= sigrow_gain; // Result might overflow 16-bit variable (10-bit + 8-bit)
temp += 0x80; // Add 256/2 to get correct integer rounding on division below
temp >>= 8; // Divide result by 256 to get processed temperature in Kelvin
uint16_t temperature_in_K = temp;
return temperature_in_K - 273.15; // value in Celsius
}
uint16_t hwFreeMem(void)
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

View File

@@ -0,0 +1,95 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2022 Sensnology AB
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyHwAVR_h
#define MyHwAVR_h
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/atomic.h>
#include <SPI.h>
// Fast IO driver
#include "drivers/DigitalWriteFast/digitalWriteFast.h"
// SOFTSPI
#ifdef MY_SOFTSPI
#include "hal/architecture/AVR/drivers/DigitalIO/DigitalIO.h"
#endif
#ifdef __cplusplus
#include <Arduino.h>
#endif
#define CRYPTO_LITTLE_ENDIAN
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE Serial
#endif
#ifndef MY_DEBUGDEVICE
#define MY_DEBUGDEVICE MY_SERIALDEVICE
#endif
// AVR temperature calibration reference: http://ww1.microchip.com/downloads/en/AppNotes/Atmel-8108-Calibration-of-the-AVRs-Internal-Temperature-Reference_ApplicationNote_AVR122.pdf
#ifndef MY_AVR_TEMPERATURE_OFFSET
#define MY_AVR_TEMPERATURE_OFFSET (324.31f)
#endif
#ifndef MY_AVR_TEMPERATURE_GAIN
#define MY_AVR_TEMPERATURE_GAIN (1.22f)
#endif
// Define these as macros to save valuable space
#define hwDigitalWrite(__pin, __value) digitalWriteFast(__pin, __value)
#define hwDigitalRead(__pin) digitalReadFast(__pin)
#define hwPinMode(__pin, __value) pinModeFast(__pin, __value)
void (*_beforeSleep)() ;
void (*_afterSleep)() ;
bool hwInit(void);
void pit_reset();
#define hwWatchdogReset() pit_reset()
#define hwReboot() wdt_enable(WDTO_15MS); while (1)
#define hwMillis() millis()
#define hwReadConfig(__pos) eeprom_read_byte((const uint8_t *)__pos)
#define hwWriteConfig(__pos, __val) eeprom_update_byte((uint8_t *)__pos, (uint8_t)__val)
#define hwReadConfigBlock(__buf, __pos, __length) eeprom_read_block((void *)__buf, (const void *)__pos, (uint32_t)__length)
#define hwWriteConfigBlock(__buf, __pos, __length) eeprom_update_block((const void *)__buf, (void *)__pos, (uint32_t)__length)
inline void hwRandomNumberInit(void);
#if defined(MY_SOFTSPI)
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, 0> hwSPI; //!< hwSPI
#else
#define hwSPI SPI //!< hwSPI
#endif
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#endif /* DOXYGEN */
#endif

View File

@@ -79,6 +79,7 @@ MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE_MS LITERAL1
MY_TRANSPORT_TIMEOUT_FAILURE_STATE_MS LITERAL1
MY_TRANSPORT_UPLINK_CHECK_DISABLED LITERAL1
MY_TRANSPORT_WAIT_READY_MS LITERAL1
MY_ROUTES_SIZE LITERAL1
# debug
MY_DEBUG LITERAL1