Remerge 0.16.x' into firmware21
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
/* Copyright 2017 Fred Sundvik
|
||||
*
|
||||
* 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 2 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
#include "samd51j18a.h"
|
||||
#include "md_bootloader.h"
|
||||
|
||||
// Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
|
||||
void bootloader_jump(void) {
|
||||
#ifdef KEYBOARD_massdrop_ctrl
|
||||
// CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
|
||||
uint8_t ver_ram_method[] = "v2.18Jun 22 2018 17:28:08"; // The version to match (NULL terminated by compiler)
|
||||
uint8_t *ver_check = ver_ram_method; // Pointer to version match string for traversal
|
||||
uint8_t *ver_rom = (uint8_t *)0x21A0; // Pointer to address in ROM where this specific bootloader version would exist
|
||||
|
||||
while (*ver_check && *ver_rom == *ver_check) { // While there are check version characters to match and bootloader's version matches check's version
|
||||
ver_check++; // Move check version pointer to next character
|
||||
ver_rom++; // Move ROM version pointer to next character
|
||||
}
|
||||
|
||||
if (!*ver_check) { // If check version pointer is NULL, all characters have matched
|
||||
*MAGIC_ADDR = BOOTLOADER_MAGIC; // Set magic number into RAM
|
||||
NVIC_SystemReset(); // Perform system reset
|
||||
while (1) {
|
||||
} // Won't get here
|
||||
}
|
||||
#endif
|
||||
|
||||
WDT->CTRLA.bit.ENABLE = 0;
|
||||
while (WDT->SYNCBUSY.bit.ENABLE) {
|
||||
}
|
||||
while (WDT->CTRLA.bit.ENABLE) {
|
||||
}
|
||||
WDT->CONFIG.bit.WINDOW = 0;
|
||||
WDT->CONFIG.bit.PER = 0;
|
||||
WDT->EWCTRL.bit.EWOFFSET = 0;
|
||||
WDT->CTRLA.bit.ENABLE = 1;
|
||||
while (WDT->SYNCBUSY.bit.ENABLE) {
|
||||
}
|
||||
while (!WDT->CTRLA.bit.ENABLE) {
|
||||
}
|
||||
while (1) {
|
||||
} // Wait on timeout
|
||||
}
|
||||
65
platforms/arm_atsam/bootloaders/md_boot.c
Normal file
65
platforms/arm_atsam/bootloaders/md_boot.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Copyright 2017 Fred Sundvik
|
||||
*
|
||||
* 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 2 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include "samd51j18a.h"
|
||||
|
||||
// WARNING: These are only for CTRL bootloader release "v2.18Jun 22 2018 17:28:08" for bootloader_jump support
|
||||
extern uint32_t _eram;
|
||||
#define BOOTLOADER_MAGIC 0x3B9ACA00
|
||||
#define MAGIC_ADDR (uint32_t *)((intptr_t)(&_eram) - 4)
|
||||
|
||||
// CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
|
||||
void bootloader_jump(void) {
|
||||
#ifdef KEYBOARD_massdrop_ctrl
|
||||
uint8_t ver_ram_method[] = "v2.18Jun 22 2018 17:28:08"; // The version to match (NULL terminated by compiler)
|
||||
uint8_t *ver_check = ver_ram_method; // Pointer to version match string for traversal
|
||||
uint8_t *ver_rom = (uint8_t *)0x21A0; // Pointer to address in ROM where this specific bootloader version would exist
|
||||
|
||||
while (*ver_check && *ver_rom == *ver_check) { // While there are check version characters to match and bootloader's version matches check's version
|
||||
ver_check++; // Move check version pointer to next character
|
||||
ver_rom++; // Move ROM version pointer to next character
|
||||
}
|
||||
|
||||
if (!*ver_check) { // If check version pointer is NULL, all characters have matched
|
||||
*MAGIC_ADDR = BOOTLOADER_MAGIC; // Set magic number into RAM
|
||||
NVIC_SystemReset(); // Perform system reset
|
||||
while (1)
|
||||
; // Won't get here
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
|
||||
WDT->CTRLA.bit.ENABLE = 0;
|
||||
|
||||
while (WDT->SYNCBUSY.bit.ENABLE)
|
||||
;
|
||||
while (WDT->CTRLA.bit.ENABLE)
|
||||
;
|
||||
|
||||
WDT->CONFIG.bit.WINDOW = 0;
|
||||
WDT->CONFIG.bit.PER = 0;
|
||||
WDT->EWCTRL.bit.EWOFFSET = 0;
|
||||
WDT->CTRLA.bit.ENABLE = 1;
|
||||
|
||||
while (WDT->SYNCBUSY.bit.ENABLE)
|
||||
;
|
||||
while (!WDT->CTRLA.bit.ENABLE)
|
||||
;
|
||||
while (1)
|
||||
; // Wait on timeout
|
||||
}
|
||||
@@ -18,11 +18,7 @@
|
||||
#include "samd51j18a.h"
|
||||
#include "core_cm4.h"
|
||||
#include "component/nvmctrl.h"
|
||||
|
||||
#ifndef EEPROM_SIZE
|
||||
# include "eeconfig.h"
|
||||
# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
|
||||
#endif
|
||||
#include "eeprom_samd.h"
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
|
||||
@@ -159,7 +155,9 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); }
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) {
|
||||
eeprom_write_byte(addr, value);
|
||||
}
|
||||
|
||||
void eeprom_update_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
8
platforms/arm_atsam/eeprom_samd.h
Normal file
8
platforms/arm_atsam/eeprom_samd.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2022 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#ifndef EEPROM_SIZE
|
||||
# include "eeconfig.h"
|
||||
# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
|
||||
#endif
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
typedef uint8_t pin_t;
|
||||
|
||||
#define SAMD_PORT(pin) ((pin & 0x20) >> 5)
|
||||
#define SAMD_PIN(pin) (pin & 0x1f)
|
||||
#define SAMD_PIN_MASK(pin) (1 << (pin & 0x1f))
|
||||
#define SAMD_PORT(pin) (((pin)&0x20) >> 5)
|
||||
#define SAMD_PIN(pin) ((pin)&0x1f)
|
||||
#define SAMD_PIN_MASK(pin) (1 << ((pin)&0x1f))
|
||||
|
||||
#define setPinInput(pin) \
|
||||
do { \
|
||||
@@ -48,12 +48,16 @@ typedef uint8_t pin_t;
|
||||
PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
|
||||
} while (0)
|
||||
|
||||
#define setPinOutput(pin) \
|
||||
#define setPinOutputPushPull(pin) \
|
||||
do { \
|
||||
PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \
|
||||
PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
|
||||
} while (0)
|
||||
|
||||
#define setPinOutputOpenDrain(pin) _Static_assert(0, "arm_atsam platform does not implement an open-drain output")
|
||||
|
||||
#define setPinOutput(pin) setPinOutputPushPull(pin)
|
||||
|
||||
#define writePinHigh(pin) \
|
||||
do { \
|
||||
PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
|
||||
|
||||
@@ -3,61 +3,18 @@
|
||||
#include "md_rgb_matrix.h"
|
||||
#include "suspend.h"
|
||||
|
||||
/** \brief Suspend idle
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_idle(uint8_t time) { /* Note: Not used anywhere currently */
|
||||
}
|
||||
|
||||
/** \brief Run user level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_power_down_user(void) {}
|
||||
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
|
||||
|
||||
/** \brief Suspend power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_power_down(void) {
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
I2C3733_Control_Set(0); // Disable LED driver
|
||||
I2C3733_Control_Set(0); // Disable LED driver
|
||||
#endif
|
||||
|
||||
suspend_power_down_kb();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void matrix_power_up(void) {}
|
||||
__attribute__((weak)) void matrix_power_down(void) {}
|
||||
bool suspend_wakeup_condition(void) {
|
||||
matrix_power_up();
|
||||
matrix_scan();
|
||||
matrix_power_down();
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
if (matrix_get_row(r)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief run user level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_wakeup_init_user(void) {}
|
||||
|
||||
/** \brief run keyboard level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
|
||||
|
||||
/** \brief run immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
|
||||
@@ -2,18 +2,34 @@
|
||||
#include "timer.h"
|
||||
#include "tmk_core/protocol/arm_atsam/clks.h"
|
||||
|
||||
void set_time(uint64_t tset) { ms_clk = tset; }
|
||||
void set_time(uint64_t tset) {
|
||||
ms_clk = tset;
|
||||
}
|
||||
|
||||
void timer_init(void) { timer_clear(); }
|
||||
void timer_init(void) {
|
||||
timer_clear();
|
||||
}
|
||||
|
||||
uint16_t timer_read(void) { return (uint16_t)ms_clk; }
|
||||
uint16_t timer_read(void) {
|
||||
return (uint16_t)ms_clk;
|
||||
}
|
||||
|
||||
uint32_t timer_read32(void) { return (uint32_t)ms_clk; }
|
||||
uint32_t timer_read32(void) {
|
||||
return (uint32_t)ms_clk;
|
||||
}
|
||||
|
||||
uint64_t timer_read64(void) { return ms_clk; }
|
||||
uint64_t timer_read64(void) {
|
||||
return ms_clk;
|
||||
}
|
||||
|
||||
uint16_t timer_elapsed(uint16_t tlast) { return TIMER_DIFF_16(timer_read(), tlast); }
|
||||
uint16_t timer_elapsed(uint16_t tlast) {
|
||||
return TIMER_DIFF_16(timer_read(), tlast);
|
||||
}
|
||||
|
||||
uint32_t timer_elapsed32(uint32_t tlast) { return TIMER_DIFF_32(timer_read32(), tlast); }
|
||||
uint32_t timer_elapsed32(uint32_t tlast) {
|
||||
return TIMER_DIFF_32(timer_read32(), tlast);
|
||||
}
|
||||
|
||||
void timer_clear(void) { set_time(0); }
|
||||
void timer_clear(void) {
|
||||
set_time(0);
|
||||
}
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <util/delay.h>
|
||||
#include "bootloader.h"
|
||||
#include <avr/boot.h>
|
||||
|
||||
#ifdef PROTOCOL_LUFA
|
||||
# include <LUFA/Drivers/USB/USB.h>
|
||||
#endif
|
||||
|
||||
/** \brief Bootloader Size in *bytes*
|
||||
*
|
||||
* AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet.
|
||||
* Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'.
|
||||
*
|
||||
* Size of Bootloaders in bytes:
|
||||
* Atmel DFU loader(ATmega32U4) 4096
|
||||
* Atmel DFU loader(AT90USB128) 8192
|
||||
* LUFA bootloader(ATmega32U4) 4096
|
||||
* Arduino Caterina(ATmega32U4) 4096
|
||||
* USBaspLoader(ATmega***) 2048
|
||||
* Teensy halfKay(ATmega32U4) 512
|
||||
* Teensy++ halfKay(AT90USB128) 1024
|
||||
*
|
||||
* AVR Boot section is located at the end of Flash memory like the followings.
|
||||
*
|
||||
* byte Atmel/LUFA(ATMega32u4) byte Atmel(AT90SUB128)
|
||||
* 0x0000 +---------------+ 0x00000 +---------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Application | | Application |
|
||||
* | | | |
|
||||
* = = = =
|
||||
* | | 32KB-4KB | | 128KB-8KB
|
||||
* 0x7000 +---------------+ 0x1E000 +---------------+
|
||||
* | Bootloader | 4KB | Bootloader | 8KB
|
||||
* 0x7FFF +---------------+ 0x1FFFF +---------------+
|
||||
*
|
||||
*
|
||||
* byte Teensy(ATMega32u4) byte Teensy++(AT90SUB128)
|
||||
* 0x0000 +---------------+ 0x00000 +---------------+
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | Application | | Application |
|
||||
* | | | |
|
||||
* = = = =
|
||||
* | | 32KB-512B | | 128KB-1KB
|
||||
* 0x7E00 +---------------+ 0x1FC00 +---------------+
|
||||
* | Bootloader | 512B | Bootloader | 1KB
|
||||
* 0x7FFF +---------------+ 0x1FFFF +---------------+
|
||||
*/
|
||||
#define FLASH_SIZE (FLASHEND + 1L)
|
||||
|
||||
#if !defined(BOOTLOADER_SIZE)
|
||||
uint16_t bootloader_start;
|
||||
#endif
|
||||
|
||||
// compatibility between ATMega8 and ATMega88
|
||||
#if !defined(MCUCSR)
|
||||
# if defined(MCUSR)
|
||||
# define MCUCSR MCUSR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** \brief Entering the Bootloader via Software
|
||||
*
|
||||
* http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
|
||||
*/
|
||||
#define BOOTLOADER_RESET_KEY 0xB007B007
|
||||
uint32_t reset_key __attribute__((section(".noinit,\"aw\",@nobits;")));
|
||||
|
||||
/** \brief initialize MCU status by watchdog reset
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
#if !defined(BOOTLOADER_SIZE)
|
||||
uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
|
||||
|
||||
if (high_fuse & ~(FUSE_BOOTSZ0 & FUSE_BOOTSZ1)) {
|
||||
bootloader_start = (FLASH_SIZE - 512) >> 1;
|
||||
} else if (high_fuse & ~(FUSE_BOOTSZ1)) {
|
||||
bootloader_start = (FLASH_SIZE - 1024) >> 1;
|
||||
} else if (high_fuse & ~(FUSE_BOOTSZ0)) {
|
||||
bootloader_start = (FLASH_SIZE - 2048) >> 1;
|
||||
} else {
|
||||
bootloader_start = (FLASH_SIZE - 4096) >> 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Something like this might work, but it compiled larger than the block above
|
||||
// bootloader_start = FLASH_SIZE - (256 << (~high_fuse & 0b110 >> 1));
|
||||
|
||||
#if defined(BOOTLOADER_HALFKAY)
|
||||
// http://www.pjrc.com/teensy/jump_to_bootloader.html
|
||||
cli();
|
||||
// disable watchdog, if enabled (it's not)
|
||||
// disable all peripherals
|
||||
// a shutdown call might make sense here
|
||||
UDCON = 1;
|
||||
USBCON = (1 << FRZCLK); // disable USB
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5);
|
||||
# if defined(__AVR_AT90USB162__) // Teensy 1.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
UCSR1B = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
asm volatile("jmp 0x3E00");
|
||||
# elif defined(__AVR_ATmega32U4__) // Teensy 2.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
ADCSRA = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
TIMSK3 = 0;
|
||||
TIMSK4 = 0;
|
||||
UCSR1B = 0;
|
||||
TWCR = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
DDRE = 0;
|
||||
DDRF = 0;
|
||||
TWCR = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
PORTE = 0;
|
||||
PORTF = 0;
|
||||
asm volatile("jmp 0x7E00");
|
||||
# elif defined(__AVR_AT90USB646__) // Teensy++ 1.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
ADCSRA = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
TIMSK2 = 0;
|
||||
TIMSK3 = 0;
|
||||
UCSR1B = 0;
|
||||
TWCR = 0;
|
||||
DDRA = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
DDRE = 0;
|
||||
DDRF = 0;
|
||||
PORTA = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
PORTE = 0;
|
||||
PORTF = 0;
|
||||
asm volatile("jmp 0xFC00");
|
||||
# elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
ADCSRA = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
TIMSK2 = 0;
|
||||
TIMSK3 = 0;
|
||||
UCSR1B = 0;
|
||||
TWCR = 0;
|
||||
DDRA = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
DDRE = 0;
|
||||
DDRF = 0;
|
||||
PORTA = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
PORTE = 0;
|
||||
PORTF = 0;
|
||||
asm volatile("jmp 0x1FC00");
|
||||
# endif
|
||||
|
||||
#elif defined(BOOTLOADER_CATERINA)
|
||||
// this block may be optional
|
||||
// TODO: figure it out
|
||||
|
||||
uint16_t *const bootKeyPtr = (uint16_t *)0x0800;
|
||||
|
||||
// Value used by Caterina bootloader use to determine whether to run the
|
||||
// sketch or the bootloader programmer.
|
||||
uint16_t bootKey = 0x7777;
|
||||
|
||||
*bootKeyPtr = bootKey;
|
||||
|
||||
// setup watchdog timeout
|
||||
wdt_enable(WDTO_60MS);
|
||||
|
||||
while (1) {
|
||||
} // wait for watchdog timer to trigger
|
||||
|
||||
#elif defined(BOOTLOADER_USBASP)
|
||||
// Taken with permission of Stephan Baerwolf from https://github.com/tinyusbboard/API/blob/master/apipage.c
|
||||
wdt_enable(WDTO_15MS);
|
||||
wdt_reset();
|
||||
asm volatile("cli \n\t"
|
||||
"ldi r29 , %[ramendhi] \n\t"
|
||||
"ldi r28 , %[ramendlo] \n\t"
|
||||
# if (FLASHEND > 131071)
|
||||
"ldi r18 , %[bootaddrhi] \n\t"
|
||||
"st Y+, r18 \n\t"
|
||||
# endif
|
||||
"ldi r18 , %[bootaddrme] \n\t"
|
||||
"st Y+, r18 \n\t"
|
||||
"ldi r18 , %[bootaddrlo] \n\t"
|
||||
"st Y+, r18 \n\t"
|
||||
"out %[mcucsrio], __zero_reg__ \n\t"
|
||||
"bootloader_startup_loop%=: \n\t"
|
||||
"rjmp bootloader_startup_loop%= \n\t"
|
||||
:
|
||||
: [mcucsrio] "I"(_SFR_IO_ADDR(MCUCSR)),
|
||||
# if (FLASHEND > 131071)
|
||||
[ramendhi] "M"(((RAMEND - 2) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 2) >> 0) & 0xff), [bootaddrhi] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 16) & 0xff),
|
||||
# else
|
||||
[ramendhi] "M"(((RAMEND - 1) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 1) >> 0) & 0xff),
|
||||
# endif
|
||||
[bootaddrme] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 8) & 0xff), [bootaddrlo] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 0) & 0xff));
|
||||
|
||||
#else // Assume remaining boards are DFU, even if the flag isn't set
|
||||
|
||||
# if !(defined(__AVR_ATmega32A__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATtiny85__)) // no USB - maybe BOOTLOADER_BOOTLOADHID instead though?
|
||||
UDCON = 1;
|
||||
USBCON = (1 << FRZCLK); // disable USB
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5); // 5 seems to work fine
|
||||
# endif
|
||||
|
||||
# ifdef BOOTLOADER_BOOTLOADHID
|
||||
// force bootloadHID to stay in bootloader mode, so that it waits
|
||||
// for a new firmware to be flashed
|
||||
eeprom_write_byte((uint8_t *)1, 0x00);
|
||||
# endif
|
||||
|
||||
// watchdog reset
|
||||
reset_key = BOOTLOADER_RESET_KEY;
|
||||
wdt_enable(WDTO_250MS);
|
||||
for (;;)
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* this runs before main() */
|
||||
void bootloader_jump_after_watchdog_reset(void) __attribute__((used, naked, section(".init3")));
|
||||
void bootloader_jump_after_watchdog_reset(void) {
|
||||
#ifndef BOOTLOADER_HALFKAY
|
||||
if ((MCUCSR & (1 << WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
|
||||
reset_key = 0;
|
||||
|
||||
// My custom USBasploader requires this to come up.
|
||||
MCUCSR = 0;
|
||||
|
||||
// Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
|
||||
MCUCSR &= ~(1 << WDRF);
|
||||
wdt_disable();
|
||||
|
||||
// This is compled into 'icall', address should be in word unit, not byte.
|
||||
# ifdef BOOTLOADER_SIZE
|
||||
((void (*)(void))((FLASH_SIZE - BOOTLOADER_SIZE) >> 1))();
|
||||
# else
|
||||
asm("ijmp" ::"z"(bootloader_start));
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
33
platforms/avr/bootloaders/bootloadhid.c
Normal file
33
platforms/avr/bootloaders/bootloadhid.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// force bootloadHID to stay in bootloader mode, so that it waits
|
||||
// for a new firmware to be flashed
|
||||
// NOTE: this byte is part of QMK's "magic number" - changing it causes the EEPROM to be re-initialized
|
||||
// thus every time the device is flashed the EEPROM will be wiped
|
||||
eeprom_write_byte((uint8_t *)1, 0x00);
|
||||
|
||||
// watchdog reset
|
||||
wdt_enable(WDTO_250MS);
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
39
platforms/avr/bootloaders/caterina.c
Normal file
39
platforms/avr/bootloaders/caterina.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <avr/wdt.h>
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// this block may be optional
|
||||
// TODO: figure it out
|
||||
|
||||
uint16_t *const bootKeyPtr = (uint16_t *)0x0800;
|
||||
|
||||
// Value used by Caterina bootloader use to determine whether to run the
|
||||
// sketch or the bootloader programmer.
|
||||
uint16_t bootKey = 0x7777;
|
||||
|
||||
*bootKeyPtr = bootKey;
|
||||
|
||||
// setup watchdog timeout
|
||||
wdt_enable(WDTO_60MS);
|
||||
|
||||
// wait for watchdog timer to trigger
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/* Copyright 2018-2020 Nick Brassel (@tzarc)
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* 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,
|
||||
@@ -14,10 +14,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here (page 175):
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
* This also requires a patch to chibios:
|
||||
* <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
#include "bootloader.h"
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {}
|
||||
52
platforms/avr/bootloaders/dfu.c
Normal file
52
platforms/avr/bootloaders/dfu.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <avr/wdt.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define FLASH_SIZE (FLASHEND + 1L)
|
||||
|
||||
/** \brief Entering the Bootloader via Software
|
||||
*
|
||||
* http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
|
||||
*/
|
||||
#define BOOTLOADER_RESET_KEY 0xB007B007
|
||||
uint32_t reset_key __attribute__((section(".noinit,\"aw\",@nobits;")));
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
UDCON = 1;
|
||||
USBCON = (1 << FRZCLK); // disable USB
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5); // 5 seems to work fine
|
||||
|
||||
// watchdog reset
|
||||
reset_key = BOOTLOADER_RESET_KEY;
|
||||
wdt_enable(WDTO_250MS);
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
/* this runs before main() */
|
||||
void bootloader_jump_after_watchdog_reset(void) __attribute__((used, naked, section(".init3")));
|
||||
void bootloader_jump_after_watchdog_reset(void) {
|
||||
if ((MCUSR & (1 << WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
|
||||
reset_key = 0;
|
||||
|
||||
((void (*)(void))((FLASH_SIZE - BOOTLOADER_SIZE) >> 1))();
|
||||
}
|
||||
}
|
||||
128
platforms/avr/bootloaders/halfkay.c
Normal file
128
platforms/avr/bootloaders/halfkay.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// http://www.pjrc.com/teensy/jump_to_bootloader.html
|
||||
|
||||
cli();
|
||||
// disable watchdog, if enabled (it's not)
|
||||
// disable all peripherals
|
||||
// a shutdown call might make sense here
|
||||
UDCON = 1;
|
||||
USBCON = (1 << FRZCLK); // disable USB
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5);
|
||||
|
||||
#if defined(__AVR_AT90USB162__) // Teensy 1.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
UCSR1B = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
asm volatile("jmp 0x3E00");
|
||||
#elif defined(__AVR_ATmega32U4__) // Teensy 2.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
ADCSRA = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
TIMSK3 = 0;
|
||||
TIMSK4 = 0;
|
||||
UCSR1B = 0;
|
||||
TWCR = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
DDRE = 0;
|
||||
DDRF = 0;
|
||||
TWCR = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
PORTE = 0;
|
||||
PORTF = 0;
|
||||
asm volatile("jmp 0x7E00");
|
||||
#elif defined(__AVR_AT90USB646__) // Teensy++ 1.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
ADCSRA = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
TIMSK2 = 0;
|
||||
TIMSK3 = 0;
|
||||
UCSR1B = 0;
|
||||
TWCR = 0;
|
||||
DDRA = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
DDRE = 0;
|
||||
DDRF = 0;
|
||||
PORTA = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
PORTE = 0;
|
||||
PORTF = 0;
|
||||
asm volatile("jmp 0xFC00");
|
||||
#elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0
|
||||
EIMSK = 0;
|
||||
PCICR = 0;
|
||||
SPCR = 0;
|
||||
ACSR = 0;
|
||||
EECR = 0;
|
||||
ADCSRA = 0;
|
||||
TIMSK0 = 0;
|
||||
TIMSK1 = 0;
|
||||
TIMSK2 = 0;
|
||||
TIMSK3 = 0;
|
||||
UCSR1B = 0;
|
||||
TWCR = 0;
|
||||
DDRA = 0;
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
DDRE = 0;
|
||||
DDRF = 0;
|
||||
PORTA = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
PORTE = 0;
|
||||
PORTF = 0;
|
||||
asm volatile("jmp 0x1FC00");
|
||||
#endif
|
||||
}
|
||||
56
platforms/avr/bootloaders/usbasploader.c
Normal file
56
platforms/avr/bootloaders/usbasploader.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <avr/wdt.h>
|
||||
|
||||
#define FLASH_SIZE (FLASHEND + 1L)
|
||||
|
||||
#if !defined(MCUCSR)
|
||||
# if defined(MCUSR)
|
||||
# define MCUCSR MCUSR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// Taken with permission of Stephan Baerwolf from https://github.com/tinyusbboard/API/blob/master/apipage.c
|
||||
|
||||
wdt_enable(WDTO_15MS);
|
||||
wdt_reset();
|
||||
asm volatile("cli \n\t"
|
||||
"ldi r29 , %[ramendhi] \n\t"
|
||||
"ldi r28 , %[ramendlo] \n\t"
|
||||
#if (FLASHEND > 131071)
|
||||
"ldi r18 , %[bootaddrhi] \n\t"
|
||||
"st Y+, r18 \n\t"
|
||||
#endif
|
||||
"ldi r18 , %[bootaddrme] \n\t"
|
||||
"st Y+, r18 \n\t"
|
||||
"ldi r18 , %[bootaddrlo] \n\t"
|
||||
"st Y+, r18 \n\t"
|
||||
"out %[mcucsrio], __zero_reg__ \n\t"
|
||||
"bootloader_startup_loop%=: \n\t"
|
||||
"rjmp bootloader_startup_loop%= \n\t"
|
||||
:
|
||||
: [mcucsrio] "I"(_SFR_IO_ADDR(MCUCSR)),
|
||||
#if (FLASHEND > 131071)
|
||||
[ramendhi] "M"(((RAMEND - 2) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 2) >> 0) & 0xff), [bootaddrhi] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 16) & 0xff),
|
||||
#else
|
||||
[ramendhi] "M"(((RAMEND - 1) >> 8) & 0xff), [ramendlo] "M"(((RAMEND - 1) >> 0) & 0xff),
|
||||
#endif
|
||||
[bootaddrme] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 8) & 0xff), [bootaddrlo] "M"((((FLASH_SIZE - BOOTLOADER_SIZE) >> 1) >> 0) & 0xff));
|
||||
}
|
||||
@@ -14,16 +14,17 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <stdint.h>
|
||||
#include "analog.h"
|
||||
|
||||
static uint8_t aref = ADC_REF_POWER;
|
||||
|
||||
void analogReference(uint8_t mode) { aref = mode & (_BV(REFS1) | _BV(REFS0)); }
|
||||
void analogReference(uint8_t mode) {
|
||||
aref = mode & (_BV(REFS1) | _BV(REFS0));
|
||||
}
|
||||
|
||||
int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); }
|
||||
int16_t analogReadPin(pin_t pin) {
|
||||
return adc_read(pinToMux(pin));
|
||||
}
|
||||
|
||||
uint8_t pinToMux(pin_t pin) {
|
||||
switch (pin) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -32,21 +32,21 @@ int16_t adc_read(uint8_t mux);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ADC_REF_EXTERNAL 0 // AREF, Internal Vref turned off
|
||||
#define ADC_REF_POWER _BV(REFS0) // AVCC with external capacitor on AREF pin
|
||||
#define ADC_REF_INTERNAL (_BV(REFS1) | _BV(REFS0)) // Internal 2.56V Voltage Reference with external capacitor on AREF pin (1.1V for 328P)
|
||||
#define ADC_REF_EXTERNAL 0 // AREF, Internal Vref turned off
|
||||
#define ADC_REF_POWER _BV(REFS0) // AVCC with external capacitor on AREF pin
|
||||
#define ADC_REF_INTERNAL (_BV(REFS1) | _BV(REFS0)) // Internal 2.56V Voltage Reference with external capacitor on AREF pin (1.1V for 328P)
|
||||
|
||||
// These prescaler values are for high speed mode, ADHSM = 1
|
||||
#if F_CPU == 16000000L || F_CPU == 12000000L
|
||||
# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64
|
||||
# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS1)) // /64
|
||||
#elif F_CPU == 8000000L
|
||||
# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32
|
||||
# define ADC_PRESCALER (_BV(ADPS2) | _BV(ADPS0)) // /32
|
||||
#elif F_CPU == 4000000L
|
||||
# define ADC_PRESCALER (_BV(ADPS2)) // /16
|
||||
# define ADC_PRESCALER (_BV(ADPS2)) // /16
|
||||
#elif F_CPU == 2000000L
|
||||
# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8
|
||||
# define ADC_PRESCALER (_BV(ADPS1) | _BV(ADPS0)) // /8
|
||||
#elif F_CPU == 1000000L
|
||||
# define ADC_PRESCALER _BV(ADPS1) // /4
|
||||
# define ADC_PRESCALER _BV(ADPS1) // /4
|
||||
#else
|
||||
# define ADC_PRESCALER _BV(ADPS0) // /2
|
||||
# define ADC_PRESCALER _BV(ADPS0) // /2
|
||||
#endif
|
||||
|
||||
@@ -152,7 +152,7 @@ extern uint8_t note_timbre;
|
||||
#ifdef AUDIO1_PIN_SET
|
||||
static float channel_1_frequency = 0.0f;
|
||||
void channel_1_set_frequency(float freq) {
|
||||
if (freq == 0.0f) // a pause/rest is a valid "note" with freq=0
|
||||
if (freq == 0.0f) // a pause/rest is a valid "note" with freq=0
|
||||
{
|
||||
// disable the output, but keep the pwm-ISR going (with the previous
|
||||
// frequency) so the audio-state keeps getting updated
|
||||
@@ -160,7 +160,7 @@ void channel_1_set_frequency(float freq) {
|
||||
AUDIO1_TCCRxA &= ~(_BV(AUDIO1_COMxy1) | _BV(AUDIO1_COMxy0));
|
||||
return;
|
||||
} else {
|
||||
AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); // enable output, PWM mode
|
||||
AUDIO1_TCCRxA |= _BV(AUDIO1_COMxy1); // enable output, PWM mode
|
||||
}
|
||||
|
||||
channel_1_frequency = freq;
|
||||
@@ -202,7 +202,9 @@ void channel_2_set_frequency(float freq) {
|
||||
AUDIO2_OCRxy = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre / 100);
|
||||
}
|
||||
|
||||
float channel_2_get_frequency(void) { return channel_2_frequency; }
|
||||
float channel_2_get_frequency(void) {
|
||||
return channel_2_frequency;
|
||||
}
|
||||
|
||||
void channel_2_start(void) {
|
||||
AUDIO2_TIMSKx |= _BV(AUDIO2_OCIExy);
|
||||
|
||||
@@ -10,14 +10,14 @@ static const unsigned char font[] PROGMEM = {
|
||||
0x30, 0x38, 0x3E, 0x38, 0x30, 0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00,
|
||||
0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78, 0x04, 0x03,
|
||||
0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C,
|
||||
0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
|
||||
0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
|
||||
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
|
||||
0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
|
||||
0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
|
||||
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
|
||||
};
|
||||
|
||||
@@ -262,7 +262,7 @@ static uint8_t lcd_waitbusy(void)
|
||||
delay(LCD_DELAY_BUSY_FLAG);
|
||||
|
||||
/* now read the address counter */
|
||||
return (lcd_read(0)); // return address counter
|
||||
return (lcd_read(0)); // return address counter
|
||||
|
||||
} /* lcd_waitbusy */
|
||||
|
||||
@@ -362,17 +362,23 @@ void lcd_gotoxy(uint8_t x, uint8_t y) {
|
||||
|
||||
/*************************************************************************
|
||||
*************************************************************************/
|
||||
int lcd_getxy(void) { return lcd_waitbusy(); }
|
||||
int lcd_getxy(void) {
|
||||
return lcd_waitbusy();
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Clear display and set cursor to home position
|
||||
*************************************************************************/
|
||||
void lcd_clrscr(void) { lcd_command(1 << LCD_CLR); }
|
||||
void lcd_clrscr(void) {
|
||||
lcd_command(1 << LCD_CLR);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Set cursor to home position
|
||||
*************************************************************************/
|
||||
void lcd_home(void) { lcd_command(1 << LCD_HOME); }
|
||||
void lcd_home(void) {
|
||||
lcd_command(1 << LCD_HOME);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Display character at current cursor position
|
||||
@@ -382,7 +388,7 @@ Returns: none
|
||||
void lcd_putc(char c) {
|
||||
uint8_t pos;
|
||||
|
||||
pos = lcd_waitbusy(); // read busy-flag and address counter
|
||||
pos = lcd_waitbusy(); // read busy-flag and address counter
|
||||
if (c == '\n') {
|
||||
lcd_newline(pos);
|
||||
} else {
|
||||
@@ -483,8 +489,8 @@ void lcd_init(uint8_t dispAttr) {
|
||||
delay(LCD_DELAY_BOOTUP); /* wait 16ms or more after power-on */
|
||||
|
||||
/* initial write to lcd is 8bit */
|
||||
LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4;
|
||||
LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4;
|
||||
LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN); // LCD_FUNCTION>>4;
|
||||
LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN); // LCD_FUNCTION_8BIT>>4;
|
||||
lcd_e_toggle();
|
||||
delay(LCD_DELAY_INIT); /* delay, busy flag can't be checked here */
|
||||
|
||||
@@ -497,7 +503,7 @@ void lcd_init(uint8_t dispAttr) {
|
||||
delay(LCD_DELAY_INIT_REP); /* delay, busy flag can't be checked here */
|
||||
|
||||
/* now configure for 4bit mode */
|
||||
LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4
|
||||
LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN); // LCD_FUNCTION_4BIT_1LINE>>4
|
||||
lcd_e_toggle();
|
||||
delay(LCD_DELAY_INIT_4BIT); /* some displays need this additional delay */
|
||||
|
||||
|
||||
@@ -25,12 +25,15 @@
|
||||
#include "wait.h"
|
||||
|
||||
#ifndef F_SCL
|
||||
# define F_SCL 400000UL // SCL frequency
|
||||
# define F_SCL 400000UL // SCL frequency
|
||||
#endif
|
||||
|
||||
#ifndef I2C_START_RETRY_COUNT
|
||||
# define I2C_START_RETRY_COUNT 20
|
||||
#endif // I2C_START_RETRY_COUNT
|
||||
#endif // I2C_START_RETRY_COUNT
|
||||
|
||||
#define I2C_ACTION_READ 0x01
|
||||
#define I2C_ACTION_WRITE 0x00
|
||||
|
||||
#define TWBR_val (((F_CPU / F_SCL) - 16) / 2)
|
||||
|
||||
@@ -95,7 +98,7 @@ static i2c_status_t i2c_start_impl(uint8_t address, uint16_t timeout) {
|
||||
i2c_status_t i2c_start(uint8_t address, uint16_t timeout) {
|
||||
// Retry i2c_start_impl a bunch times in case the remote side has interrupts disabled.
|
||||
uint16_t timeout_timer = timer_read();
|
||||
uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
|
||||
uint16_t time_slice = MAX(1, (timeout == (I2C_TIMEOUT_INFINITE)) ? 5 : (timeout / (I2C_START_RETRY_COUNT))); // if it's infinite, wait 1ms between attempts, otherwise split up the entire timeout into the number of retries
|
||||
i2c_status_t status;
|
||||
do {
|
||||
status = i2c_start_impl(address, time_slice);
|
||||
@@ -154,7 +157,7 @@ int16_t i2c_read_nack(uint16_t timeout) {
|
||||
}
|
||||
|
||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_status_t status = i2c_start(address | I2C_WRITE, timeout);
|
||||
i2c_status_t status = i2c_start(address | I2C_ACTION_WRITE, timeout);
|
||||
|
||||
for (uint16_t i = 0; i < length && status >= 0; i++) {
|
||||
status = i2c_write(data[i], timeout);
|
||||
@@ -166,7 +169,7 @@ i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length,
|
||||
}
|
||||
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_status_t status = i2c_start(address | I2C_READ, timeout);
|
||||
i2c_status_t status = i2c_start(address | I2C_ACTION_READ, timeout);
|
||||
|
||||
for (uint16_t i = 0; i < (length - 1) && status >= 0; i++) {
|
||||
status = i2c_read_ack(timeout);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
# include "transactions.h"
|
||||
|
||||
static volatile bool is_callback_executor = false;
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
|
||||
volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
|
||||
|
||||
@@ -57,7 +57,7 @@ ISR(TWI_vect) {
|
||||
slave_has_register_set = false;
|
||||
#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
is_callback_executor = false;
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
break;
|
||||
|
||||
case TW_SR_DATA_ACK:
|
||||
@@ -66,16 +66,16 @@ ISR(TWI_vect) {
|
||||
if (!slave_has_register_set) {
|
||||
buffer_address = TWDR;
|
||||
|
||||
if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack
|
||||
if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack
|
||||
ack = 0;
|
||||
buffer_address = 0;
|
||||
}
|
||||
slave_has_register_set = true; // address has been received now fill in buffer
|
||||
slave_has_register_set = true; // address has been received now fill in buffer
|
||||
|
||||
#if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
// Work out if we're attempting to execute a callback
|
||||
is_callback_executor = buffer_address == split_transaction_table[I2C_EXECUTE_CALLBACK].initiator2target_offset;
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
} else {
|
||||
i2c_slave_reg[buffer_address] = TWDR;
|
||||
buffer_address++;
|
||||
@@ -88,7 +88,7 @@ ISR(TWI_vect) {
|
||||
trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
|
||||
}
|
||||
}
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
#endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
# if defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
# include "transport.h"
|
||||
# define I2C_SLAVE_REG_COUNT sizeof(split_shared_memory_t)
|
||||
# else // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
# else // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
# define I2C_SLAVE_REG_COUNT 30
|
||||
# endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
# endif // defined(USE_I2C) && defined(SPLIT_COMMON_TRANSACTIONS)
|
||||
|
||||
#endif // I2C_SLAVE_REG_COUNT
|
||||
#endif // I2C_SLAVE_REG_COUNT
|
||||
|
||||
_Static_assert(I2C_SLAVE_REG_COUNT < 256, "I2C target registers must be single byte");
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ void clock_lo(void) {
|
||||
setPinOutput(PS2_CLOCK_PIN);
|
||||
}
|
||||
|
||||
void clock_hi(void) { setPinInputHigh(PS2_CLOCK_PIN); }
|
||||
void clock_hi(void) {
|
||||
setPinInputHigh(PS2_CLOCK_PIN);
|
||||
}
|
||||
|
||||
bool clock_in(void) {
|
||||
setPinInputHigh(PS2_CLOCK_PIN);
|
||||
@@ -42,7 +44,9 @@ void data_lo(void) {
|
||||
setPinOutput(PS2_DATA_PIN);
|
||||
}
|
||||
|
||||
void data_hi(void) { setPinInputHigh(PS2_DATA_PIN); }
|
||||
void data_hi(void) {
|
||||
setPinInputHigh(PS2_DATA_PIN);
|
||||
}
|
||||
|
||||
bool data_in(void) {
|
||||
setPinInputHigh(PS2_DATA_PIN);
|
||||
|
||||
@@ -76,7 +76,7 @@ static inline bool pbuf_has_data(void);
|
||||
static inline void pbuf_clear(void);
|
||||
|
||||
void ps2_host_init(void) {
|
||||
idle(); // without this many USART errors occur when cable is disconnected
|
||||
idle(); // without this many USART errors occur when cable is disconnected
|
||||
PS2_USART_INIT();
|
||||
PS2_USART_RX_INT_ON();
|
||||
// POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
|
||||
@@ -91,12 +91,12 @@ uint8_t ps2_host_send(uint8_t data) {
|
||||
|
||||
/* terminate a transmission if we have */
|
||||
inhibit();
|
||||
_delay_us(100); // [4]p.13
|
||||
_delay_us(100); // [4]p.13
|
||||
|
||||
/* 'Request to Send' and Start bit */
|
||||
data_lo();
|
||||
clock_hi();
|
||||
WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
|
||||
WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
|
||||
|
||||
/* Data bit[2-9] */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
@@ -165,7 +165,7 @@ uint8_t ps2_host_recv(void) {
|
||||
|
||||
ISR(PS2_USART_RX_VECT) {
|
||||
// TODO: request RESEND when error occurs?
|
||||
uint8_t error = PS2_USART_ERROR; // USART error should be read before data
|
||||
uint8_t error = PS2_USART_ERROR; // USART error should be read before data
|
||||
uint8_t data = PS2_USART_RX_DATA;
|
||||
if (!error) {
|
||||
pbuf_enqueue(data);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <util/delay.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "gpio.h"
|
||||
#include "serial.h"
|
||||
|
||||
#ifdef SOFT_SERIAL_PIN
|
||||
@@ -124,12 +125,6 @@
|
||||
# error invalid SOFT_SERIAL_PIN value
|
||||
# endif
|
||||
|
||||
# define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
# define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
# define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
# define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
|
||||
# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
|
||||
|
||||
# define ALWAYS_INLINE __attribute__((always_inline))
|
||||
# define NO_INLINE __attribute__((noinline))
|
||||
# define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
|
||||
@@ -166,59 +161,59 @@
|
||||
|
||||
# if SELECT_SOFT_SERIAL_SPEED == 0
|
||||
// Very High speed
|
||||
# define SERIAL_DELAY 4 // micro sec
|
||||
# define SERIAL_DELAY 4 // micro sec
|
||||
# if __GNUC__ < 6
|
||||
# define READ_WRITE_START_ADJUST 33 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# define READ_WRITE_START_ADJUST 33 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# else
|
||||
# define READ_WRITE_START_ADJUST 34 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# define READ_WRITE_START_ADJUST 34 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# endif
|
||||
# elif SELECT_SOFT_SERIAL_SPEED == 1
|
||||
// High speed
|
||||
# define SERIAL_DELAY 6 // micro sec
|
||||
# define SERIAL_DELAY 6 // micro sec
|
||||
# if __GNUC__ < 6
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# else
|
||||
# define READ_WRITE_START_ADJUST 33 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# define READ_WRITE_START_ADJUST 33 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# endif
|
||||
# elif SELECT_SOFT_SERIAL_SPEED == 2
|
||||
// Middle speed
|
||||
# define SERIAL_DELAY 12 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# define SERIAL_DELAY 12 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# if __GNUC__ < 6
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# else
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# endif
|
||||
# elif SELECT_SOFT_SERIAL_SPEED == 3
|
||||
// Low speed
|
||||
# define SERIAL_DELAY 24 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# define SERIAL_DELAY 24 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# if __GNUC__ < 6
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# else
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# endif
|
||||
# elif SELECT_SOFT_SERIAL_SPEED == 4
|
||||
// Very Low speed
|
||||
# define SERIAL_DELAY 36 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# define SERIAL_DELAY 36 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# if __GNUC__ < 6
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# else
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# endif
|
||||
# elif SELECT_SOFT_SERIAL_SPEED == 5
|
||||
// Ultra Low speed
|
||||
# define SERIAL_DELAY 48 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# define SERIAL_DELAY 48 // micro sec
|
||||
# define READ_WRITE_START_ADJUST 30 // cycles
|
||||
# if __GNUC__ < 6
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 3 // cycles
|
||||
# else
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# define READ_WRITE_WIDTH_ADJUST 7 // cycles
|
||||
# endif
|
||||
# else
|
||||
# error invalid SELECT_SOFT_SERIAL_SPEED value
|
||||
@@ -233,29 +228,45 @@
|
||||
# define SLAVE_INT_ACK_WIDTH 4
|
||||
|
||||
inline static void serial_delay(void) ALWAYS_INLINE;
|
||||
inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); }
|
||||
inline static void serial_delay(void) {
|
||||
_delay_us(SERIAL_DELAY);
|
||||
}
|
||||
|
||||
inline static void serial_delay_half1(void) ALWAYS_INLINE;
|
||||
inline static void serial_delay_half1(void) { _delay_us(SERIAL_DELAY_HALF1); }
|
||||
inline static void serial_delay_half1(void) {
|
||||
_delay_us(SERIAL_DELAY_HALF1);
|
||||
}
|
||||
|
||||
inline static void serial_delay_half2(void) ALWAYS_INLINE;
|
||||
inline static void serial_delay_half2(void) { _delay_us(SERIAL_DELAY_HALF2); }
|
||||
inline static void serial_delay_half2(void) {
|
||||
_delay_us(SERIAL_DELAY_HALF2);
|
||||
}
|
||||
|
||||
inline static void serial_output(void) ALWAYS_INLINE;
|
||||
inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_output(void) {
|
||||
setPinOutput(SOFT_SERIAL_PIN);
|
||||
}
|
||||
|
||||
// make the serial pin an input with pull-up resistor
|
||||
inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
|
||||
inline static void serial_input_with_pullup(void) { setPinInputHigh(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_input_with_pullup(void) {
|
||||
setPinInputHigh(SOFT_SERIAL_PIN);
|
||||
}
|
||||
|
||||
inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
|
||||
inline static uint8_t serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); }
|
||||
inline static uint8_t serial_read_pin(void) {
|
||||
return !!readPin(SOFT_SERIAL_PIN);
|
||||
}
|
||||
|
||||
inline static void serial_low(void) ALWAYS_INLINE;
|
||||
inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_low(void) {
|
||||
writePinLow(SOFT_SERIAL_PIN);
|
||||
}
|
||||
|
||||
inline static void serial_high(void) ALWAYS_INLINE;
|
||||
inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_high(void) {
|
||||
writePinHigh(SOFT_SERIAL_PIN);
|
||||
}
|
||||
|
||||
void soft_serial_initiator_init(void) {
|
||||
serial_output();
|
||||
@@ -296,7 +307,7 @@ static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
|
||||
|
||||
_delay_sub_us(READ_WRITE_START_ADJUST);
|
||||
for (i = 0, byte = 0, p = PARITY; i < bit; i++) {
|
||||
serial_delay_half1(); // read the middle of pulses
|
||||
serial_delay_half1(); // read the middle of pulses
|
||||
if (serial_read_pin()) {
|
||||
byte = (byte << 1) | 1;
|
||||
p ^= 1;
|
||||
@@ -308,7 +319,7 @@ static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
|
||||
serial_delay_half2();
|
||||
}
|
||||
/* recive parity bit */
|
||||
serial_delay_half1(); // read the middle of pulses
|
||||
serial_delay_half1(); // read the middle of pulses
|
||||
pb = serial_read_pin();
|
||||
_delay_sub_us(READ_WRITE_WIDTH_ADJUST);
|
||||
serial_delay_half2();
|
||||
@@ -340,7 +351,7 @@ void serial_write_chunk(uint8_t data, uint8_t bit) {
|
||||
}
|
||||
serial_delay();
|
||||
|
||||
serial_low(); // sync_send() / senc_recv() need raise edge
|
||||
serial_low(); // sync_send() / senc_recv() need raise edge
|
||||
}
|
||||
|
||||
static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
|
||||
@@ -366,19 +377,19 @@ static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
|
||||
}
|
||||
|
||||
inline static void change_sender2reciver(void) {
|
||||
sync_send(); // 0
|
||||
serial_delay_half1(); // 1
|
||||
serial_low(); // 2
|
||||
serial_input_with_pullup(); // 2
|
||||
serial_delay_half1(); // 3
|
||||
sync_send(); // 0
|
||||
serial_delay_half1(); // 1
|
||||
serial_low(); // 2
|
||||
serial_input_with_pullup(); // 2
|
||||
serial_delay_half1(); // 3
|
||||
}
|
||||
|
||||
inline static void change_reciver2sender(void) {
|
||||
sync_recv(); // 0
|
||||
serial_delay(); // 1
|
||||
serial_low(); // 3
|
||||
serial_output(); // 3
|
||||
serial_delay_half1(); // 4
|
||||
sync_recv(); // 0
|
||||
serial_delay(); // 1
|
||||
serial_low(); // 3
|
||||
serial_output(); // 3
|
||||
serial_delay_half1(); // 4
|
||||
}
|
||||
|
||||
static inline uint8_t nibble_bits_count(uint8_t bits) {
|
||||
@@ -401,11 +412,11 @@ ISR(SERIAL_PIN_INTERRUPT) {
|
||||
}
|
||||
serial_delay_half1();
|
||||
|
||||
serial_high(); // response step1 low->high
|
||||
serial_high(); // response step1 low->high
|
||||
serial_output();
|
||||
_delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH);
|
||||
split_transaction_desc_t *trans = &split_transaction_table[tid];
|
||||
serial_low(); // response step2 ack high->low
|
||||
serial_low(); // response step2 ack high->low
|
||||
|
||||
// If the transaction has a callback, we can execute it now
|
||||
if (trans->slave_callback) {
|
||||
@@ -419,34 +430,22 @@ ISR(SERIAL_PIN_INTERRUPT) {
|
||||
|
||||
// target recive phase
|
||||
if (trans->initiator2target_buffer_size > 0) {
|
||||
if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
|
||||
*trans->status = TRANSACTION_ACCEPTED;
|
||||
} else {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
}
|
||||
} else {
|
||||
*trans->status = TRANSACTION_ACCEPTED;
|
||||
serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size);
|
||||
}
|
||||
|
||||
sync_recv(); // weit initiator output to high
|
||||
sync_recv(); // weit initiator output to high
|
||||
}
|
||||
|
||||
/////////
|
||||
// start transaction by initiator
|
||||
//
|
||||
// int soft_serial_transaction(int sstd_index)
|
||||
// bool soft_serial_transaction(int sstd_index)
|
||||
//
|
||||
// Returns:
|
||||
// TRANSACTION_END
|
||||
// TRANSACTION_NO_RESPONSE
|
||||
// TRANSACTION_DATA_ERROR
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
int soft_serial_transaction(int sstd_index) {
|
||||
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
|
||||
bool soft_serial_transaction(int sstd_index) {
|
||||
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false;
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
|
||||
if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
|
||||
|
||||
cli();
|
||||
|
||||
// signal to the target that we want to start a transaction
|
||||
@@ -473,9 +472,8 @@ int soft_serial_transaction(int sstd_index) {
|
||||
// slave failed to pull the line low, assume not present
|
||||
serial_output();
|
||||
serial_high();
|
||||
*trans->status = TRANSACTION_NO_RESPONSE;
|
||||
sei();
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
return false;
|
||||
}
|
||||
_delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
|
||||
}
|
||||
@@ -486,9 +484,8 @@ int soft_serial_transaction(int sstd_index) {
|
||||
if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
|
||||
serial_output();
|
||||
serial_high();
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
sei();
|
||||
return TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,19 +500,8 @@ int soft_serial_transaction(int sstd_index) {
|
||||
// always, release the line when not in use
|
||||
sync_send();
|
||||
|
||||
*trans->status = TRANSACTION_END;
|
||||
sei();
|
||||
return TRANSACTION_END;
|
||||
}
|
||||
|
||||
int soft_serial_get_and_clean_status(int sstd_index) {
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
cli();
|
||||
int retval = *trans->status;
|
||||
*trans->status = 0;
|
||||
;
|
||||
sei();
|
||||
return retval;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ spi_status_t spi_write(uint8_t data) {
|
||||
}
|
||||
|
||||
spi_status_t spi_read() {
|
||||
SPDR = 0x00; // Dummy
|
||||
SPDR = 0x00; // Dummy
|
||||
|
||||
uint16_t timeout_timer = timer_read();
|
||||
while (!(SPSR & _BV(SPIF))) {
|
||||
|
||||
@@ -161,7 +161,7 @@ bool iota_gfx_init(void) {
|
||||
send_cmd1(DeActivateScroll);
|
||||
send_cmd1(DisplayOn);
|
||||
|
||||
send_cmd2(SetContrast, 0); // Dim
|
||||
send_cmd2(SetContrast, 0); // Dim
|
||||
|
||||
clear_display();
|
||||
|
||||
@@ -226,7 +226,9 @@ void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
|
||||
matrix_write_char_inner(matrix, c);
|
||||
}
|
||||
|
||||
void iota_gfx_write_char(uint8_t c) { matrix_write_char(&display, c); }
|
||||
void iota_gfx_write_char(uint8_t c) {
|
||||
matrix_write_char(&display, c);
|
||||
}
|
||||
|
||||
void matrix_write(struct CharacterMatrix *matrix, const char *data) {
|
||||
const char *end = data + strlen(data);
|
||||
@@ -236,7 +238,9 @@ void matrix_write(struct CharacterMatrix *matrix, const char *data) {
|
||||
}
|
||||
}
|
||||
|
||||
void iota_gfx_write(const char *data) { matrix_write(&display, data); }
|
||||
void iota_gfx_write(const char *data) {
|
||||
matrix_write(&display, data);
|
||||
}
|
||||
|
||||
void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
|
||||
while (true) {
|
||||
@@ -249,7 +253,9 @@ void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
|
||||
}
|
||||
}
|
||||
|
||||
void iota_gfx_write_P(const char *data) { matrix_write_P(&display, data); }
|
||||
void iota_gfx_write_P(const char *data) {
|
||||
matrix_write_P(&display, data);
|
||||
}
|
||||
|
||||
void matrix_clear(struct CharacterMatrix *matrix) {
|
||||
memset(matrix->display, ' ', sizeof(matrix->display));
|
||||
@@ -257,7 +263,9 @@ void matrix_clear(struct CharacterMatrix *matrix) {
|
||||
matrix->dirty = true;
|
||||
}
|
||||
|
||||
void iota_gfx_clear_screen(void) { matrix_clear(&display); }
|
||||
void iota_gfx_clear_screen(void) {
|
||||
matrix_clear(&display);
|
||||
}
|
||||
|
||||
void matrix_render(struct CharacterMatrix *matrix) {
|
||||
last_flush = timer_read();
|
||||
@@ -301,7 +309,9 @@ done:
|
||||
# endif
|
||||
}
|
||||
|
||||
void iota_gfx_flush(void) { matrix_render(&display); }
|
||||
void iota_gfx_flush(void) {
|
||||
matrix_render(&display);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void iota_gfx_task_user(void) {}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ void uart_write(uint8_t data) {
|
||||
// return immediately to avoid deadlock when interrupt is disabled(called from ISR)
|
||||
if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return;
|
||||
while (tx_buffer_tail == i)
|
||||
; // wait until space in buffer
|
||||
; // wait until space in buffer
|
||||
// cli();
|
||||
tx_buffer[i] = data;
|
||||
tx_buffer_head = i;
|
||||
@@ -121,7 +121,7 @@ uint8_t uart_read(void) {
|
||||
uint8_t data, i;
|
||||
|
||||
while (rx_buffer_head == rx_buffer_tail)
|
||||
; // wait for character
|
||||
; // wait for character
|
||||
i = rx_buffer_tail + 1;
|
||||
if (i >= RX_BUFFER_SIZE) i = 0;
|
||||
data = rx_buffer[i];
|
||||
|
||||
@@ -110,7 +110,7 @@ static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t
|
||||
|
||||
asm volatile(" ldi %0,8 \n\t"
|
||||
"loop%=: \n\t"
|
||||
" out %2,%3 \n\t" // '1' [01] '0' [01] - re
|
||||
" out %2,%3 \n\t" // '1' [01] '0' [01] - re
|
||||
#if (w1_nops & 1)
|
||||
w_nop1
|
||||
#endif
|
||||
@@ -126,9 +126,9 @@ static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t
|
||||
#if (w1_nops & 16)
|
||||
w_nop16
|
||||
#endif
|
||||
" sbrs %1,7 \n\t" // '1' [03] '0' [02]
|
||||
" out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
|
||||
" lsl %1 \n\t" // '1' [04] '0' [04]
|
||||
" sbrs %1,7 \n\t" // '1' [03] '0' [02]
|
||||
" out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
|
||||
" lsl %1 \n\t" // '1' [04] '0' [04]
|
||||
#if (w2_nops & 1)
|
||||
w_nop1
|
||||
#endif
|
||||
@@ -144,7 +144,7 @@ static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t
|
||||
#if (w2_nops & 16)
|
||||
w_nop16
|
||||
#endif
|
||||
" out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
|
||||
" out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
|
||||
#if (w3_nops & 1)
|
||||
w_nop1
|
||||
#endif
|
||||
@@ -161,8 +161,8 @@ static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t
|
||||
w_nop16
|
||||
#endif
|
||||
|
||||
" dec %0 \n\t" // '1' [+2] '0' [+2]
|
||||
" brne loop%=\n\t" // '1' [+3] '0' [+4]
|
||||
" dec %0 \n\t" // '1' [+2] '0' [+2]
|
||||
" brne loop%=\n\t" // '1' [+3] '0' [+4]
|
||||
: "=&d"(ctr)
|
||||
: "r"(curbyte), "I"(_SFR_IO_ADDR(PORTx_ADDRESS(RGB_DI_PIN))), "r"(maskhi), "r"(masklo));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
# define WS2812_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
void ws2812_init(void) { i2c_init(); }
|
||||
void ws2812_init(void) {
|
||||
i2c_init();
|
||||
}
|
||||
|
||||
// Setleds for standard RGB
|
||||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
|
||||
|
||||
@@ -25,7 +25,9 @@ typedef uint8_t pin_t;
|
||||
#define setPinInput(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
|
||||
#define setPinInputHigh(pin) (DDRx_ADDRESS(pin) &= ~_BV((pin)&0xF), PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
#define setPinInputLow(pin) _Static_assert(0, "AVR processors cannot implement an input as pull low")
|
||||
#define setPinOutput(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
#define setPinOutputPushPull(pin) (DDRx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
#define setPinOutputOpenDrain(pin) _Static_assert(0, "AVR platform does not implement an open-drain output")
|
||||
#define setPinOutput(pin) setPinOutputPushPull(pin)
|
||||
|
||||
#define writePinHigh(pin) (PORTx_ADDRESS(pin) |= _BV((pin)&0xF))
|
||||
#define writePinLow(pin) (PORTx_ADDRESS(pin) &= ~_BV((pin)&0xF))
|
||||
@@ -34,16 +36,3 @@ typedef uint8_t pin_t;
|
||||
#define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
|
||||
|
||||
#define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))
|
||||
|
||||
/* Operation of GPIO by port. */
|
||||
|
||||
typedef uint8_t port_data_t;
|
||||
|
||||
#define readPort(port) PINx_ADDRESS(port)
|
||||
|
||||
#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF))
|
||||
#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF))
|
||||
#define setPortBitOutput(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF))
|
||||
|
||||
#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF))
|
||||
#define writePortBitHigh(port, bit) (PORTx_ADDRESS(port) |= _BV((bit)&0xF))
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#define PORT_SHIFTER 4 // this may be 4 for all AVR chips
|
||||
#define PORT_SHIFTER 4 // this may be 4 for all AVR chips
|
||||
|
||||
// If you want to add more to this list, reference the PINx definitions in these header
|
||||
// files: https://github.com/vancegroup-mirrors/avr-libc/tree/master/avr-libc/include/avr
|
||||
|
||||
@@ -159,7 +159,7 @@ endif
|
||||
|
||||
bootloader:
|
||||
ifeq ($(strip $(QMK_BOOTLOADER_TYPE)),)
|
||||
$(error Please set BOOTLOADER to "qmk-dfu" or "qmk-hid" first!)
|
||||
$(call CATASTROPHIC_ERROR,Invalid BOOTLOADER,Please set BOOTLOADER to "qmk-dfu" or "qmk-hid" first!)
|
||||
else
|
||||
make -C lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/ clean
|
||||
$(QMK_BIN) generate-dfu-header --quiet --keyboard $(KEYBOARD) --output lib/lufa/Bootloaders/$(QMK_BOOTLOADER_TYPE)/Keyboard.h
|
||||
|
||||
@@ -17,4 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "xprintf.h"
|
||||
#include "sendchar.h"
|
||||
|
||||
void print_set_sendchar(sendchar_func_t func) { xdev_out(func); }
|
||||
void print_set_sendchar(sendchar_func_t func) {
|
||||
xdev_out(func);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#if SLEEP_LED_TIMER == 1
|
||||
# define TCCRxB TCCR1B
|
||||
# define TIMERx_COMPA_vect TIMER1_COMPA_vect
|
||||
# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
|
||||
# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
|
||||
# define TIMSKx TIMSK
|
||||
# else
|
||||
# define TIMSKx TIMSK1
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "matrix.h"
|
||||
#include "action.h"
|
||||
#include "suspend.h"
|
||||
#include "action.h"
|
||||
#include "timer.h"
|
||||
#include "led.h"
|
||||
#include "host.h"
|
||||
|
||||
#ifdef PROTOCOL_LUFA
|
||||
# include "lufa.h"
|
||||
@@ -16,19 +13,6 @@
|
||||
# include "vusb.h"
|
||||
#endif
|
||||
|
||||
/** \brief Suspend idle
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_idle(uint8_t time) {
|
||||
cli();
|
||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||
sleep_enable();
|
||||
sei();
|
||||
sleep_cpu();
|
||||
sleep_disable();
|
||||
}
|
||||
|
||||
// TODO: This needs some cleanup
|
||||
|
||||
#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
|
||||
@@ -91,6 +75,18 @@ static void power_down(uint8_t wdto) {
|
||||
// Disable watchdog after sleep
|
||||
wdt_disable();
|
||||
}
|
||||
|
||||
/* watchdog timeout */
|
||||
ISR(WDT_vect) {
|
||||
// compensate timer for sleep
|
||||
switch (wdt_timeout) {
|
||||
case WDTO_15MS:
|
||||
timer_count += 15 + 2; // WDTO_15MS + 2(from observation)
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** \brief Suspend power down
|
||||
@@ -115,18 +111,6 @@ void suspend_power_down(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((weak)) void matrix_power_up(void) {}
|
||||
__attribute__((weak)) void matrix_power_down(void) {}
|
||||
bool suspend_wakeup_condition(void) {
|
||||
matrix_power_up();
|
||||
matrix_scan();
|
||||
matrix_power_down();
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
if (matrix_get_row(r)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief run immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
@@ -137,16 +121,3 @@ void suspend_wakeup_init(void) {
|
||||
|
||||
suspend_wakeup_init_quantum();
|
||||
}
|
||||
|
||||
#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
|
||||
/* watchdog timeout */
|
||||
ISR(WDT_vect) {
|
||||
// compensate timer for sleep
|
||||
switch (wdt_timeout) {
|
||||
case WDTO_15MS:
|
||||
timer_count += 15 + 2; // WDTO_15MS + 2(from observation)
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -73,7 +73,9 @@ void timer_init(void) {
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
inline void timer_clear(void) {
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { timer_count = 0; }
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
timer_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief timer read
|
||||
@@ -83,7 +85,9 @@ inline void timer_clear(void) {
|
||||
inline uint16_t timer_read(void) {
|
||||
uint32_t t;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { t = timer_count; }
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
t = timer_count;
|
||||
}
|
||||
|
||||
return (t & 0xFFFF);
|
||||
}
|
||||
@@ -95,7 +99,9 @@ inline uint16_t timer_read(void) {
|
||||
inline uint32_t timer_read32(void) {
|
||||
uint32_t t;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { t = timer_count; }
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
t = timer_count;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -107,7 +113,9 @@ inline uint32_t timer_read32(void) {
|
||||
inline uint16_t timer_elapsed(uint16_t last) {
|
||||
uint32_t t;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { t = timer_count; }
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
t = timer_count;
|
||||
}
|
||||
|
||||
return TIMER_DIFF_16((t & 0xFFFF), last);
|
||||
}
|
||||
@@ -119,7 +127,9 @@ inline uint16_t timer_elapsed(uint16_t last) {
|
||||
inline uint32_t timer_elapsed32(uint32_t last) {
|
||||
uint32_t t;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { t = timer_count; }
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
t = timer_count;
|
||||
}
|
||||
|
||||
return TIMER_DIFF_32(t, last);
|
||||
}
|
||||
@@ -130,4 +140,6 @@ inline uint32_t timer_elapsed32(uint32_t last) {
|
||||
#else
|
||||
# define TIMER_INTERRUPT_VECTOR TIMER0_COMP_vect
|
||||
#endif
|
||||
ISR(TIMER_INTERRUPT_VECTOR, ISR_NOBLOCK) { timer_count++; }
|
||||
ISR(TIMER_INTERRUPT_VECTOR, ISR_NOBLOCK) {
|
||||
timer_count++;
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here:
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
@@ -1,5 +0,0 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here:
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
@@ -1,5 +0,0 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here:
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFFC400
|
||||
@@ -1,5 +0,0 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here (page 175):
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800
|
||||
@@ -1,5 +0,0 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here:
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800
|
||||
@@ -17,7 +17,7 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
|
||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
|
||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
|
||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
|
||||
#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# List of all the board related files.
|
||||
BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c
|
||||
|
||||
# Required include directories
|
||||
BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC
|
||||
|
||||
# Shared variables
|
||||
ALLCSRC += $(BOARDSRC)
|
||||
ALLINC += $(BOARDINC)
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2021 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
// Fixup equivalent usages within QMK as the base board definitions only go up to high
|
||||
#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH
|
||||
|
||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
|
||||
#endif
|
||||
267
platforms/chibios/boards/GENERIC_STM32_L432XC/configs/mcuconf.h
Normal file
267
platforms/chibios/boards/GENERIC_STM32_L432XC/configs/mcuconf.h
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32L4xx drivers configuration.
|
||||
* The following settings override the default settings present in
|
||||
* the various device driver implementation headers.
|
||||
* Note that the settings for each driver only have effect if the whole
|
||||
* driver is enabled in halconf.h.
|
||||
*
|
||||
* IRQ priorities:
|
||||
* 15...0 Lowest...Highest.
|
||||
*
|
||||
* DMA priorities:
|
||||
* 0...3 Lowest...Highest.
|
||||
*/
|
||||
|
||||
#ifndef MCUCONF_H
|
||||
#define MCUCONF_H
|
||||
|
||||
#define STM32L4xx_MCUCONF
|
||||
#define STM32L432_MCUCONF
|
||||
#define STM32L433_MCUCONF
|
||||
|
||||
/*
|
||||
* HAL driver system settings.
|
||||
*/
|
||||
#define STM32_NO_INIT FALSE
|
||||
#define STM32_VOS STM32_VOS_RANGE1
|
||||
#define STM32_PVD_ENABLE FALSE
|
||||
#define STM32_PLS STM32_PLS_LEV0
|
||||
#define STM32_HSI16_ENABLED TRUE
|
||||
#define STM32_HSI48_ENABLED TRUE
|
||||
#define STM32_LSI_ENABLED TRUE
|
||||
#define STM32_HSE_ENABLED FALSE
|
||||
#define STM32_LSE_ENABLED FALSE
|
||||
#define STM32_MSIPLL_ENABLED FALSE
|
||||
#define STM32_MSIRANGE STM32_MSIRANGE_4M
|
||||
#define STM32_MSISRANGE STM32_MSISRANGE_4M
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSI16
|
||||
#define STM32_PLLM_VALUE 1
|
||||
#define STM32_PLLN_VALUE 10
|
||||
#define STM32_PLLPDIV_VALUE 0
|
||||
#define STM32_PLLP_VALUE 7
|
||||
#define STM32_PLLQ_VALUE 2
|
||||
#define STM32_PLLR_VALUE 2
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV1
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV1
|
||||
#define STM32_STOPWUCK STM32_STOPWUCK_MSI
|
||||
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
|
||||
#define STM32_MCOPRE STM32_MCOPRE_DIV1
|
||||
#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK
|
||||
#define STM32_PLLSAI1N_VALUE 24
|
||||
#define STM32_PLLSAI1PDIV_VALUE 0
|
||||
#define STM32_PLLSAI1P_VALUE 7
|
||||
#define STM32_PLLSAI1Q_VALUE 2
|
||||
#define STM32_PLLSAI1R_VALUE 2
|
||||
|
||||
/*
|
||||
* Peripherals clock sources.
|
||||
*/
|
||||
#define STM32_USART1SEL STM32_USART1SEL_SYSCLK
|
||||
#define STM32_USART2SEL STM32_USART2SEL_SYSCLK
|
||||
#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK
|
||||
#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK
|
||||
#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK
|
||||
#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1
|
||||
#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1
|
||||
#define STM32_SAI1SEL STM32_SAI1SEL_OFF
|
||||
#define STM32_CLK48SEL STM32_CLK48SEL_HSI48
|
||||
#define STM32_ADCSEL STM32_ADCSEL_SYSCLK
|
||||
#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1
|
||||
#define STM32_RTCSEL STM32_RTCSEL_LSI
|
||||
|
||||
/*
|
||||
* IRQ system settings.
|
||||
*/
|
||||
#define STM32_IRQ_EXTI0_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI1_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI2_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI3_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI4_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI5_9_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI10_15_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI1635_38_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI18_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI19_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI20_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI21_22_PRIORITY 15
|
||||
|
||||
#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_CC_PRIORITY 7
|
||||
#define STM32_IRQ_TIM2_PRIORITY 7
|
||||
#define STM32_IRQ_TIM6_PRIORITY 7
|
||||
#define STM32_IRQ_TIM7_PRIORITY 7
|
||||
|
||||
#define STM32_IRQ_USART1_PRIORITY 12
|
||||
#define STM32_IRQ_USART2_PRIORITY 12
|
||||
#define STM32_IRQ_LPUART1_PRIORITY 12
|
||||
|
||||
/*
|
||||
* ADC driver system settings.
|
||||
*/
|
||||
#define STM32_ADC_COMPACT_SAMPLES FALSE
|
||||
#define STM32_ADC_USE_ADC1 FALSE
|
||||
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
|
||||
#define STM32_ADC_ADC1_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC12_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
|
||||
#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2
|
||||
|
||||
/*
|
||||
* CAN driver system settings.
|
||||
*/
|
||||
#define STM32_CAN_USE_CAN1 FALSE
|
||||
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
|
||||
|
||||
/*
|
||||
* DAC driver system settings.
|
||||
*/
|
||||
#define STM32_DAC_DUAL_MODE FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH1 FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH2 FALSE
|
||||
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
|
||||
#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
|
||||
|
||||
/*
|
||||
* GPT driver system settings.
|
||||
*/
|
||||
#define STM32_GPT_USE_TIM1 FALSE
|
||||
#define STM32_GPT_USE_TIM2 FALSE
|
||||
#define STM32_GPT_USE_TIM6 FALSE
|
||||
#define STM32_GPT_USE_TIM7 FALSE
|
||||
#define STM32_GPT_USE_TIM15 FALSE
|
||||
#define STM32_GPT_USE_TIM16 FALSE
|
||||
|
||||
/*
|
||||
* I2C driver system settings.
|
||||
*/
|
||||
#define STM32_I2C_USE_I2C1 FALSE
|
||||
#define STM32_I2C_USE_I2C3 FALSE
|
||||
#define STM32_I2C_BUSY_TIMEOUT 50
|
||||
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
|
||||
#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
|
||||
#define STM32_I2C_I2C1_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C3_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C1_DMA_PRIORITY 3
|
||||
#define STM32_I2C_I2C3_DMA_PRIORITY 3
|
||||
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ICU driver system settings.
|
||||
*/
|
||||
#define STM32_ICU_USE_TIM1 FALSE
|
||||
#define STM32_ICU_USE_TIM2 FALSE
|
||||
#define STM32_ICU_USE_TIM15 FALSE
|
||||
#define STM32_ICU_USE_TIM16 FALSE
|
||||
|
||||
/*
|
||||
* PWM driver system settings.
|
||||
*/
|
||||
#define STM32_PWM_USE_ADVANCED FALSE
|
||||
#define STM32_PWM_USE_TIM1 FALSE
|
||||
#define STM32_PWM_USE_TIM2 FALSE
|
||||
#define STM32_PWM_USE_TIM15 FALSE
|
||||
#define STM32_PWM_USE_TIM16 FALSE
|
||||
|
||||
/*
|
||||
* RTC driver system settings.
|
||||
*/
|
||||
#define STM32_RTC_PRESA_VALUE 32
|
||||
#define STM32_RTC_PRESS_VALUE 1024
|
||||
#define STM32_RTC_CR_INIT 0
|
||||
#define STM32_RTC_TAMPCR_INIT 0
|
||||
|
||||
/*
|
||||
* SERIAL driver system settings.
|
||||
*/
|
||||
#define STM32_SERIAL_USE_USART1 FALSE
|
||||
#define STM32_SERIAL_USE_USART2 FALSE
|
||||
#define STM32_SERIAL_USE_LPUART1 FALSE
|
||||
#define STM32_SERIAL_USART1_PRIORITY 12
|
||||
#define STM32_SERIAL_USART2_PRIORITY 12
|
||||
#define STM32_SERIAL_LPUART1_PRIORITY 12
|
||||
|
||||
/*
|
||||
* SPI driver system settings.
|
||||
*/
|
||||
#define STM32_SPI_USE_SPI1 FALSE
|
||||
#define STM32_SPI_USE_SPI3 FALSE
|
||||
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
|
||||
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
|
||||
#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
|
||||
#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
|
||||
#define STM32_SPI_SPI1_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI3_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ST driver system settings.
|
||||
*/
|
||||
#define STM32_ST_IRQ_PRIORITY 8
|
||||
#define STM32_ST_USE_TIMER 2
|
||||
|
||||
/*
|
||||
* TRNG driver system settings.
|
||||
*/
|
||||
#define STM32_TRNG_USE_RNG1 FALSE
|
||||
|
||||
/*
|
||||
* UART driver system settings.
|
||||
*/
|
||||
#define STM32_UART_USE_USART1 FALSE
|
||||
#define STM32_UART_USE_USART2 FALSE
|
||||
#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||
#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6)
|
||||
#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* USB driver system settings.
|
||||
*/
|
||||
#define STM32_USB_USE_USB1 TRUE
|
||||
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
|
||||
#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
|
||||
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
|
||||
|
||||
/*
|
||||
* WDG driver system settings.
|
||||
*/
|
||||
#define STM32_WDG_USE_IWDG FALSE
|
||||
|
||||
/*
|
||||
* WSPI driver system settings.
|
||||
*/
|
||||
#define STM32_WSPI_USE_QUADSPI1 FALSE
|
||||
#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||
#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1
|
||||
|
||||
#endif /* MCUCONF_H */
|
||||
@@ -17,7 +17,6 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
|
||||
#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/* Address for jumping to bootloader on WB32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here:
|
||||
* http://www.westberrytech.com/down/mcu/data/WB32F3G71xx_rm.pdf
|
||||
*/
|
||||
#ifndef WB32_BOOTLOADER_ADDRESS
|
||||
# undef STM32_BOOTLOADER_ADDRESS
|
||||
# define WB32_BOOTLOADER_ADDRESS 0x1FFFE000
|
||||
# define STM32_BOOTLOADER_ADDRESS WB32_BOOTLOADER_ADDRESS
|
||||
#else
|
||||
# undef STM32_BOOTLOADER_ADDRESS
|
||||
# define STM32_BOOTLOADER_ADDRESS WB32_BOOTLOADER_ADDRESS
|
||||
#endif
|
||||
@@ -1,7 +0,0 @@
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up here:
|
||||
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
|
||||
* This also requires a patch to chibios:
|
||||
* <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800
|
||||
@@ -1,145 +0,0 @@
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
#include "wait.h"
|
||||
|
||||
/* This code should be checked whether it runs correctly on platforms */
|
||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
|
||||
#define BOOTLOADER_MAGIC 0xDEADBEEF
|
||||
#define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
|
||||
|
||||
#ifndef STM32_BOOTLOADER_DUAL_BANK
|
||||
# define STM32_BOOTLOADER_DUAL_BANK FALSE
|
||||
#endif
|
||||
|
||||
#ifdef BOOTLOADER_TINYUF2
|
||||
|
||||
# define DBL_TAP_MAGIC 0xf01669ef // From tinyuf2's board_api.h
|
||||
|
||||
// defined by linker script
|
||||
extern uint32_t _board_dfu_dbl_tap[];
|
||||
# define DBL_TAP_REG _board_dfu_dbl_tap[0]
|
||||
|
||||
void bootloader_jump(void) {
|
||||
DBL_TAP_REG = DBL_TAP_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void enter_bootloader_mode_if_requested(void) { /* not needed, no two-stage reset */
|
||||
}
|
||||
|
||||
#elif STM32_BOOTLOADER_DUAL_BANK
|
||||
|
||||
// Need pin definitions
|
||||
# include "config_common.h"
|
||||
|
||||
# ifndef STM32_BOOTLOADER_DUAL_BANK_GPIO
|
||||
# error "No STM32_BOOTLOADER_DUAL_BANK_GPIO defined, don't know which pin to toggle"
|
||||
# endif
|
||||
|
||||
# ifndef STM32_BOOTLOADER_DUAL_BANK_POLARITY
|
||||
# define STM32_BOOTLOADER_DUAL_BANK_POLARITY 0
|
||||
# endif
|
||||
|
||||
# ifndef STM32_BOOTLOADER_DUAL_BANK_DELAY
|
||||
# define STM32_BOOTLOADER_DUAL_BANK_DELAY 100000
|
||||
# endif
|
||||
|
||||
extern uint32_t __ram0_end__;
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash
|
||||
// bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do
|
||||
// it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to
|
||||
// BOOT0's RC charging circuit, lets it charge the capacitor, and issue a system reset. See the QMK discord
|
||||
// #hardware channel pins for an example circuit.
|
||||
palSetPadMode(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_MODE_OUTPUT_PUSHPULL);
|
||||
# if STM32_BOOTLOADER_DUAL_BANK_POLARITY
|
||||
palSetPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
|
||||
# else
|
||||
palClearPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
|
||||
# endif
|
||||
|
||||
// Wait for a while for the capacitor to charge
|
||||
wait_ms(100);
|
||||
|
||||
// Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void enter_bootloader_mode_if_requested(void) {} // not needed at all, but if anybody attempts to invoke it....
|
||||
|
||||
#elif defined(STM32_BOOTLOADER_ADDRESS) // STM32_BOOTLOADER_DUAL_BANK
|
||||
|
||||
extern uint32_t __ram0_end__;
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
*MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void enter_bootloader_mode_if_requested(void) {
|
||||
unsigned long *check = MAGIC_ADDR;
|
||||
if (*check == BOOTLOADER_MAGIC) {
|
||||
*check = 0;
|
||||
__set_CONTROL(0);
|
||||
__set_MSP(*(__IO uint32_t *)STM32_BOOTLOADER_ADDRESS);
|
||||
__enable_irq();
|
||||
|
||||
typedef void (*BootJump_t)(void);
|
||||
BootJump_t boot_jump = *(BootJump_t *)(STM32_BOOTLOADER_ADDRESS + 4);
|
||||
boot_jump();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(GD32VF103)
|
||||
|
||||
# define DBGMCU_KEY_UNLOCK 0x4B5A6978
|
||||
# define DBGMCU_CMD_RESET 0x1
|
||||
|
||||
__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
|
||||
__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
/* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
|
||||
* register to generate a software reset request.
|
||||
* BUT instead two undocumented registers in the debug peripheral
|
||||
* that allow issueing a software reset. WHO would need the MSFRST
|
||||
* register anyway? Source:
|
||||
* https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
|
||||
*DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
|
||||
*DBGMCU_CMD = DBGMCU_CMD_RESET;
|
||||
}
|
||||
|
||||
void enter_bootloader_mode_if_requested(void) { /* Jumping to bootloader is not possible from user code. */
|
||||
}
|
||||
|
||||
#elif defined(KL2x) || defined(K20x) || defined(MK66F18) || defined(MIMXRT1062) // STM32_BOOTLOADER_DUAL_BANK // STM32_BOOTLOADER_ADDRESS
|
||||
/* Kinetis */
|
||||
|
||||
# if defined(BOOTLOADER_KIIBOHD)
|
||||
/* Kiibohd Bootloader (MCHCK and Infinity KB) */
|
||||
# define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
|
||||
const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
void *volatile vbat = (void *)VBAT;
|
||||
__builtin_memcpy(vbat, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
|
||||
// request reset
|
||||
SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
|
||||
}
|
||||
|
||||
# else /* defined(BOOTLOADER_KIIBOHD) */
|
||||
/* Default for Kinetis - expecting an ARM Teensy */
|
||||
# include "wait.h"
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
wait_ms(100);
|
||||
__BKPT(0);
|
||||
}
|
||||
# endif /* defined(BOOTLOADER_KIIBOHD) */
|
||||
|
||||
#else /* neither STM32 nor KINETIS */
|
||||
__attribute__((weak)) void bootloader_jump(void) {}
|
||||
#endif
|
||||
21
platforms/chibios/bootloaders/custom.c
Normal file
21
platforms/chibios/bootloaders/custom.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {}
|
||||
|
||||
__attribute__((weak)) void enter_bootloader_mode_if_requested(void) {}
|
||||
40
platforms/chibios/bootloaders/gd32v_dfu.c
Normal file
40
platforms/chibios/bootloaders/gd32v_dfu.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#define DBGMCU_KEY_UNLOCK 0x4B5A6978
|
||||
#define DBGMCU_CMD_RESET 0x1
|
||||
|
||||
__IO uint32_t *DBGMCU_KEY = (uint32_t *)DBGMCU_BASE + 0x0CU;
|
||||
__IO uint32_t *DBGMCU_CMD = (uint32_t *)DBGMCU_BASE + 0x08U;
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
/* The MTIMER unit of the GD32VF103 doesn't have the MSFRST
|
||||
* register to generate a software reset request.
|
||||
* BUT instead two undocumented registers in the debug peripheral
|
||||
* that allow issueing a software reset. WHO would need the MSFRST
|
||||
* register anyway? Source:
|
||||
* https://github.com/esmil/gd32vf103inator/blob/master/include/gd32vf103/dbg.h */
|
||||
*DBGMCU_KEY = DBGMCU_KEY_UNLOCK;
|
||||
*DBGMCU_CMD = DBGMCU_CMD_RESET;
|
||||
}
|
||||
|
||||
/* Jumping to bootloader is not possible from user code. */
|
||||
void enter_bootloader_mode_if_requested(void) {}
|
||||
25
platforms/chibios/bootloaders/halfkay.c
Normal file
25
platforms/chibios/bootloaders/halfkay.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
#include "wait.h"
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
wait_ms(100);
|
||||
__BKPT(0);
|
||||
}
|
||||
32
platforms/chibios/bootloaders/kiibohd.c
Normal file
32
platforms/chibios/bootloaders/kiibohd.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
/* Kiibohd Bootloader (MCHCK and Infinity KB) */
|
||||
#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
|
||||
|
||||
const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
void *volatile vbat = (void *)VBAT;
|
||||
__builtin_memcpy(vbat, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
|
||||
|
||||
// request reset
|
||||
SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
|
||||
}
|
||||
94
platforms/chibios/bootloaders/stm32_dfu.c
Normal file
94
platforms/chibios/bootloaders/stm32_dfu.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
#include "wait.h"
|
||||
|
||||
extern uint32_t __ram0_end__;
|
||||
|
||||
#ifndef STM32_BOOTLOADER_DUAL_BANK
|
||||
# define STM32_BOOTLOADER_DUAL_BANK FALSE
|
||||
#endif
|
||||
|
||||
#if STM32_BOOTLOADER_DUAL_BANK
|
||||
# include "config_common.h"
|
||||
|
||||
# ifndef STM32_BOOTLOADER_DUAL_BANK_GPIO
|
||||
# error "No STM32_BOOTLOADER_DUAL_BANK_GPIO defined, don't know which pin to toggle"
|
||||
# endif
|
||||
|
||||
# ifndef STM32_BOOTLOADER_DUAL_BANK_POLARITY
|
||||
# define STM32_BOOTLOADER_DUAL_BANK_POLARITY 0
|
||||
# endif
|
||||
|
||||
# ifndef STM32_BOOTLOADER_DUAL_BANK_DELAY
|
||||
# define STM32_BOOTLOADER_DUAL_BANK_DELAY 100000
|
||||
# endif
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
// For STM32 MCUs with dual-bank flash, and we're incapable of jumping to the bootloader. The first valid flash
|
||||
// bank is executed unconditionally after a reset, so it doesn't enter DFU unless BOOT0 is high. Instead, we do
|
||||
// it with hardware...in this case, we pull a GPIO high/low depending on the configuration, connects 3.3V to
|
||||
// BOOT0's RC charging circuit, lets it charge the capacitor, and issue a system reset. See the QMK discord
|
||||
// #hardware channel pins for an example circuit.
|
||||
palSetPadMode(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_MODE_OUTPUT_PUSHPULL);
|
||||
# if STM32_BOOTLOADER_DUAL_BANK_POLARITY
|
||||
palSetPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
|
||||
# else
|
||||
palClearPad(PAL_PORT(STM32_BOOTLOADER_DUAL_BANK_GPIO), PAL_PAD(STM32_BOOTLOADER_DUAL_BANK_GPIO));
|
||||
# endif
|
||||
|
||||
// Wait for a while for the capacitor to charge
|
||||
wait_ms(100);
|
||||
|
||||
// Issue a system reset to get the ROM bootloader to execute, with BOOT0 high
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
// not needed at all, but if anybody attempts to invoke it....
|
||||
void enter_bootloader_mode_if_requested(void) {}
|
||||
|
||||
#else
|
||||
|
||||
/* This code should be checked whether it runs correctly on platforms */
|
||||
# define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
|
||||
# define BOOTLOADER_MAGIC 0xDEADBEEF
|
||||
# define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
*MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void enter_bootloader_mode_if_requested(void) {
|
||||
unsigned long *check = MAGIC_ADDR;
|
||||
if (*check == BOOTLOADER_MAGIC) {
|
||||
*check = 0;
|
||||
__set_CONTROL(0);
|
||||
__set_MSP(*(__IO uint32_t *)STM32_BOOTLOADER_ADDRESS);
|
||||
__enable_irq();
|
||||
|
||||
typedef void (*BootJump_t)(void);
|
||||
BootJump_t boot_jump = *(BootJump_t *)(STM32_BOOTLOADER_ADDRESS + 4);
|
||||
boot_jump();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
23
platforms/chibios/bootloaders/stm32duino.c
Normal file
23
platforms/chibios/bootloaders/stm32duino.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
34
platforms/chibios/bootloaders/tinyuf2.c
Normal file
34
platforms/chibios/bootloaders/tinyuf2.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bootloader.h"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
// From tinyuf2's board_api.h
|
||||
#define DBL_TAP_MAGIC 0xF01669EF
|
||||
|
||||
// defined by linker script
|
||||
extern uint32_t _board_dfu_dbl_tap[];
|
||||
#define DBL_TAP_REG _board_dfu_dbl_tap[0]
|
||||
|
||||
__attribute__((weak)) void bootloader_jump(void) {
|
||||
DBL_TAP_REG = DBL_TAP_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/* not needed, no two-stage reset */
|
||||
void enter_bootloader_mode_if_requested(void) {}
|
||||
@@ -16,7 +16,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef USB_VBUS_PIN
|
||||
# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
|
||||
# define SPLIT_USB_DETECT // Force this on when dedicated pin is not used
|
||||
#endif
|
||||
|
||||
// STM32 compatibility
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
# if defined(K20x) || defined(KL2x)
|
||||
# define USE_I2CV1
|
||||
# define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed
|
||||
# define USE_I2CV1_CONTRIB // for some reason a bunch of ChibiOS-Contrib boards only have clock_speed
|
||||
# define USE_GPIOV1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "analog.h"
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
@@ -101,9 +100,9 @@
|
||||
|
||||
// Options are 12, 10, 8, and 6 bit.
|
||||
#ifndef ADC_RESOLUTION
|
||||
# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4
|
||||
# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4
|
||||
# define ADC_RESOLUTION ADC_CFGR_RES_10BITS
|
||||
# else // ADCv1, ADCv5, or the bodge for ADCv2 above
|
||||
# else // ADCv1, ADCv5, or the bodge for ADCv2 above
|
||||
# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT
|
||||
# endif
|
||||
#endif
|
||||
@@ -123,7 +122,7 @@ static ADCConversionGroup adcConversionGroup = {
|
||||
.smpr = ADC_SAMPLING_RATE,
|
||||
#elif defined(USE_ADCV2)
|
||||
# if !defined(STM32F1XX) && !defined(GD32VF103)
|
||||
.cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
|
||||
.cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
|
||||
# endif
|
||||
.smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE),
|
||||
.smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE),
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -28,7 +28,9 @@ typedef struct {
|
||||
uint8_t adc;
|
||||
} adc_mux;
|
||||
#define TO_MUX(i, a) \
|
||||
(adc_mux) { i, a }
|
||||
(adc_mux) { \
|
||||
i, a \
|
||||
}
|
||||
|
||||
int16_t analogReadPin(pin_t pin);
|
||||
int16_t analogReadPinAdc(pin_t pin, uint8_t adc);
|
||||
|
||||
@@ -52,19 +52,19 @@ static const dacsample_t dac_buffer_sine[AUDIO_DAC_BUFFER_SIZE] = {
|
||||
// 256 values, max 4095
|
||||
0x0, 0x1, 0x2, 0x6, 0xa, 0xf, 0x16, 0x1e, 0x27, 0x32, 0x3d, 0x4a, 0x58, 0x67, 0x78, 0x89, 0x9c, 0xb0, 0xc5, 0xdb, 0xf2, 0x10a, 0x123, 0x13e, 0x159, 0x175, 0x193, 0x1b1, 0x1d1, 0x1f1, 0x212, 0x235, 0x258, 0x27c, 0x2a0, 0x2c6, 0x2ed, 0x314, 0x33c, 0x365, 0x38e, 0x3b8, 0x3e3, 0x40e, 0x43a, 0x467, 0x494, 0x4c2, 0x4f0, 0x51f, 0x54e, 0x57d, 0x5ad, 0x5dd, 0x60e, 0x63f, 0x670, 0x6a1, 0x6d3, 0x705, 0x737, 0x769, 0x79b, 0x7cd, 0x800, 0x832, 0x864, 0x896, 0x8c8, 0x8fa, 0x92c, 0x95e, 0x98f, 0x9c0, 0x9f1, 0xa22, 0xa52, 0xa82, 0xab1, 0xae0, 0xb0f, 0xb3d, 0xb6b, 0xb98, 0xbc5, 0xbf1, 0xc1c, 0xc47, 0xc71, 0xc9a, 0xcc3, 0xceb, 0xd12, 0xd39, 0xd5f, 0xd83, 0xda7, 0xdca, 0xded, 0xe0e, 0xe2e, 0xe4e, 0xe6c, 0xe8a, 0xea6, 0xec1, 0xedc, 0xef5, 0xf0d, 0xf24, 0xf3a, 0xf4f, 0xf63, 0xf76, 0xf87, 0xf98, 0xfa7, 0xfb5, 0xfc2, 0xfcd, 0xfd8, 0xfe1, 0xfe9, 0xff0, 0xff5, 0xff9, 0xffd, 0xffe,
|
||||
0xfff, 0xffe, 0xffd, 0xff9, 0xff5, 0xff0, 0xfe9, 0xfe1, 0xfd8, 0xfcd, 0xfc2, 0xfb5, 0xfa7, 0xf98, 0xf87, 0xf76, 0xf63, 0xf4f, 0xf3a, 0xf24, 0xf0d, 0xef5, 0xedc, 0xec1, 0xea6, 0xe8a, 0xe6c, 0xe4e, 0xe2e, 0xe0e, 0xded, 0xdca, 0xda7, 0xd83, 0xd5f, 0xd39, 0xd12, 0xceb, 0xcc3, 0xc9a, 0xc71, 0xc47, 0xc1c, 0xbf1, 0xbc5, 0xb98, 0xb6b, 0xb3d, 0xb0f, 0xae0, 0xab1, 0xa82, 0xa52, 0xa22, 0x9f1, 0x9c0, 0x98f, 0x95e, 0x92c, 0x8fa, 0x8c8, 0x896, 0x864, 0x832, 0x800, 0x7cd, 0x79b, 0x769, 0x737, 0x705, 0x6d3, 0x6a1, 0x670, 0x63f, 0x60e, 0x5dd, 0x5ad, 0x57d, 0x54e, 0x51f, 0x4f0, 0x4c2, 0x494, 0x467, 0x43a, 0x40e, 0x3e3, 0x3b8, 0x38e, 0x365, 0x33c, 0x314, 0x2ed, 0x2c6, 0x2a0, 0x27c, 0x258, 0x235, 0x212, 0x1f1, 0x1d1, 0x1b1, 0x193, 0x175, 0x159, 0x13e, 0x123, 0x10a, 0xf2, 0xdb, 0xc5, 0xb0, 0x9c, 0x89, 0x78, 0x67, 0x58, 0x4a, 0x3d, 0x32, 0x27, 0x1e, 0x16, 0xf, 0xa, 0x6, 0x2, 0x1};
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SINE
|
||||
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
|
||||
static const dacsample_t dac_buffer_triangle[AUDIO_DAC_BUFFER_SIZE] = {
|
||||
// 256 values, max 4095
|
||||
0x0, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1a0, 0x1c0, 0x1e0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4a0, 0x4c0, 0x4e0, 0x500, 0x520, 0x540, 0x560, 0x580, 0x5a0, 0x5c0, 0x5e0, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6a0, 0x6c0, 0x6e0, 0x700, 0x720, 0x740, 0x760, 0x780, 0x7a0, 0x7c0, 0x7e0, 0x800, 0x81f, 0x83f, 0x85f, 0x87f, 0x89f, 0x8bf, 0x8df, 0x8ff, 0x91f, 0x93f, 0x95f, 0x97f, 0x99f, 0x9bf, 0x9df, 0x9ff, 0xa1f, 0xa3f, 0xa5f, 0xa7f, 0xa9f, 0xabf, 0xadf, 0xaff, 0xb1f, 0xb3f, 0xb5f, 0xb7f, 0xb9f, 0xbbf, 0xbdf, 0xbff, 0xc1f, 0xc3f, 0xc5f, 0xc7f, 0xc9f, 0xcbf, 0xcdf, 0xcff, 0xd1f, 0xd3f, 0xd5f, 0xd7f, 0xd9f, 0xdbf, 0xddf, 0xdff, 0xe1f, 0xe3f, 0xe5f, 0xe7f, 0xe9f, 0xebf, 0xedf, 0xeff, 0xf1f, 0xf3f, 0xf5f, 0xf7f, 0xf9f, 0xfbf, 0xfdf,
|
||||
0xfff, 0xfdf, 0xfbf, 0xf9f, 0xf7f, 0xf5f, 0xf3f, 0xf1f, 0xeff, 0xedf, 0xebf, 0xe9f, 0xe7f, 0xe5f, 0xe3f, 0xe1f, 0xdff, 0xddf, 0xdbf, 0xd9f, 0xd7f, 0xd5f, 0xd3f, 0xd1f, 0xcff, 0xcdf, 0xcbf, 0xc9f, 0xc7f, 0xc5f, 0xc3f, 0xc1f, 0xbff, 0xbdf, 0xbbf, 0xb9f, 0xb7f, 0xb5f, 0xb3f, 0xb1f, 0xaff, 0xadf, 0xabf, 0xa9f, 0xa7f, 0xa5f, 0xa3f, 0xa1f, 0x9ff, 0x9df, 0x9bf, 0x99f, 0x97f, 0x95f, 0x93f, 0x91f, 0x8ff, 0x8df, 0x8bf, 0x89f, 0x87f, 0x85f, 0x83f, 0x81f, 0x800, 0x7e0, 0x7c0, 0x7a0, 0x780, 0x760, 0x740, 0x720, 0x700, 0x6e0, 0x6c0, 0x6a0, 0x680, 0x660, 0x640, 0x620, 0x600, 0x5e0, 0x5c0, 0x5a0, 0x580, 0x560, 0x540, 0x520, 0x500, 0x4e0, 0x4c0, 0x4a0, 0x480, 0x460, 0x440, 0x420, 0x400, 0x3e0, 0x3c0, 0x3a0, 0x380, 0x360, 0x340, 0x320, 0x300, 0x2e0, 0x2c0, 0x2a0, 0x280, 0x260, 0x240, 0x220, 0x200, 0x1e0, 0x1c0, 0x1a0, 0x180, 0x160, 0x140, 0x120, 0x100, 0xe0, 0xc0, 0xa0, 0x80, 0x60, 0x40, 0x20};
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRIANGLE
|
||||
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
|
||||
static const dacsample_t dac_buffer_square[AUDIO_DAC_BUFFER_SIZE] = {
|
||||
[0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, // first and
|
||||
[AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half
|
||||
[0 ... AUDIO_DAC_BUFFER_SIZE / 2 - 1] = 0, // first and
|
||||
[AUDIO_DAC_BUFFER_SIZE / 2 ... AUDIO_DAC_BUFFER_SIZE - 1] = AUDIO_DAC_SAMPLE_MAX, // second half
|
||||
};
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_SQUARE
|
||||
/*
|
||||
// four steps: 0, 1/3, 2/3 and 1
|
||||
static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = {
|
||||
@@ -77,7 +77,7 @@ static const dacsample_t dac_buffer_staircase[AUDIO_DAC_BUFFER_SIZE] = {
|
||||
#ifdef AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
|
||||
static const dacsample_t dac_buffer_trapezoid[AUDIO_DAC_BUFFER_SIZE] = {0x0, 0x1f, 0x7f, 0xdf, 0x13f, 0x19f, 0x1ff, 0x25f, 0x2bf, 0x31f, 0x37f, 0x3df, 0x43f, 0x49f, 0x4ff, 0x55f, 0x5bf, 0x61f, 0x67f, 0x6df, 0x73f, 0x79f, 0x7ff, 0x85f, 0x8bf, 0x91f, 0x97f, 0x9df, 0xa3f, 0xa9f, 0xaff, 0xb5f, 0xbbf, 0xc1f, 0xc7f, 0xcdf, 0xd3f, 0xd9f, 0xdff, 0xe5f, 0xebf, 0xf1f, 0xf7f, 0xfdf, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
|
||||
0xfff, 0xfdf, 0xf7f, 0xf1f, 0xebf, 0xe5f, 0xdff, 0xd9f, 0xd3f, 0xcdf, 0xc7f, 0xc1f, 0xbbf, 0xb5f, 0xaff, 0xa9f, 0xa3f, 0x9df, 0x97f, 0x91f, 0x8bf, 0x85f, 0x7ff, 0x79f, 0x73f, 0x6df, 0x67f, 0x61f, 0x5bf, 0x55f, 0x4ff, 0x49f, 0x43f, 0x3df, 0x37f, 0x31f, 0x2bf, 0x25f, 0x1ff, 0x19f, 0x13f, 0xdf, 0x7f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
|
||||
#endif // AUDIO_DAC_SAMPLE_WAVEFORM_TRAPEZOID
|
||||
|
||||
static dacsample_t dac_buffer_empty[AUDIO_DAC_BUFFER_SIZE] = {AUDIO_DAC_OFF_VALUE};
|
||||
|
||||
@@ -98,7 +98,7 @@ typedef enum {
|
||||
OUTPUT_REACHED_ZERO_BEFORE_OFF,
|
||||
OUTPUT_OFF,
|
||||
OUTPUT_OFF_1,
|
||||
OUTPUT_OFF_2, // trailing off: giving the DAC two more conversion cycles until the AUDIO_DAC_OFF_VALUE reaches the output, then turn the timer off, which leaves the output at that level
|
||||
OUTPUT_OFF_2, // trailing off: giving the DAC two more conversion cycles until the AUDIO_DAC_OFF_VALUE reaches the output, then turn the timer off, which leaves the output at that level
|
||||
number_of_output_states
|
||||
} output_states_t;
|
||||
output_states_t state = OUTPUT_OFF_2;
|
||||
@@ -171,7 +171,7 @@ static void dac_end(DACDriver *dacp) {
|
||||
|
||||
// work on the other half of the buffer
|
||||
if (dacIsBufferComplete(dacp)) {
|
||||
sample_p += AUDIO_DAC_BUFFER_SIZE / 2; // 'half_index'
|
||||
sample_p += AUDIO_DAC_BUFFER_SIZE / 2; // 'half_index'
|
||||
}
|
||||
|
||||
for (uint8_t s = 0; s < AUDIO_DAC_BUFFER_SIZE / 2; s++) {
|
||||
@@ -196,8 +196,8 @@ static void dac_end(DACDriver *dacp) {
|
||||
* * *
|
||||
* =====*=*================================================= 0x0
|
||||
*/
|
||||
if (((sample_p[s] + (AUDIO_DAC_SAMPLE_MAX / 100)) > AUDIO_DAC_OFF_VALUE) && // value approaches from below
|
||||
(sample_p[s] < (AUDIO_DAC_OFF_VALUE + (AUDIO_DAC_SAMPLE_MAX / 100))) // or above
|
||||
if (((sample_p[s] + (AUDIO_DAC_SAMPLE_MAX / 100)) > AUDIO_DAC_OFF_VALUE) && // value approaches from below
|
||||
(sample_p[s] < (AUDIO_DAC_OFF_VALUE + (AUDIO_DAC_SAMPLE_MAX / 100))) // or above
|
||||
) {
|
||||
if ((OUTPUT_SHOULD_START == state) && (active_tones_snapshot_length > 0)) {
|
||||
state = OUTPUT_RUN_NORMALLY;
|
||||
@@ -220,7 +220,7 @@ static void dac_end(DACDriver *dacp) {
|
||||
// -> saves cpu cycles (?)
|
||||
for (uint8_t i = 0; i < active_tones; i++) {
|
||||
float freq = audio_get_processed_frequency(i);
|
||||
if (freq > 0) { // disregard 'rest' notes, with valid frequency 0.0f; which would only lower the resulting waveform volume during the additive synthesis step
|
||||
if (freq > 0) { // disregard 'rest' notes, with valid frequency 0.0f; which would only lower the resulting waveform volume during the additive synthesis step
|
||||
active_tones_snapshot[active_tones_snapshot_length++] = freq;
|
||||
}
|
||||
}
|
||||
@@ -321,7 +321,9 @@ void audio_driver_initialize() {
|
||||
gptStart(&GPTD6, &gpt6cfg1);
|
||||
}
|
||||
|
||||
void audio_driver_stop(void) { state = OUTPUT_SHOULD_STOP; }
|
||||
void audio_driver_stop(void) {
|
||||
state = OUTPUT_SHOULD_STOP;
|
||||
}
|
||||
|
||||
void audio_driver_start(void) {
|
||||
gptStartContinuous(&GPTD6, 2U);
|
||||
|
||||
@@ -115,13 +115,15 @@ void channel_1_set_frequency(float freq) {
|
||||
channel_1_frequency = freq;
|
||||
|
||||
channel_1_stop();
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
return;
|
||||
|
||||
gpt6cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE;
|
||||
channel_1_start();
|
||||
}
|
||||
float channel_1_get_frequency(void) { return channel_1_frequency; }
|
||||
float channel_1_get_frequency(void) {
|
||||
return channel_1_frequency;
|
||||
}
|
||||
|
||||
void channel_2_start(void) {
|
||||
gptStart(&GPTD7, &gpt7cfg1);
|
||||
@@ -140,13 +142,15 @@ void channel_2_set_frequency(float freq) {
|
||||
channel_2_frequency = freq;
|
||||
|
||||
channel_2_stop();
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
return;
|
||||
|
||||
gpt7cfg1.frequency = 2 * freq * AUDIO_DAC_BUFFER_SIZE;
|
||||
channel_2_start();
|
||||
}
|
||||
float channel_2_get_frequency(void) { return channel_2_frequency; }
|
||||
float channel_2_get_frequency(void) {
|
||||
return channel_2_frequency;
|
||||
}
|
||||
|
||||
static void gpt_audio_state_cb(GPTDriver *gptp) {
|
||||
if (audio_update_state()) {
|
||||
@@ -155,8 +159,8 @@ static void gpt_audio_state_cb(GPTDriver *gptp) {
|
||||
channel_1_set_frequency(audio_get_processed_frequency(0));
|
||||
channel_2_set_frequency(audio_get_processed_frequency(0));
|
||||
|
||||
#else // two separate audio outputs/speakers
|
||||
// primary speaker on A4, optional secondary on A5
|
||||
#else // two separate audio outputs/speakers
|
||||
// primary speaker on A4, optional secondary on A5
|
||||
if (AUDIO_PIN == A4) {
|
||||
channel_1_set_frequency(audio_get_processed_frequency(0));
|
||||
if (AUDIO_PIN_ALT == A5) {
|
||||
|
||||
@@ -72,7 +72,7 @@ static float channel_1_frequency = 0.0f;
|
||||
void channel_1_set_frequency(float freq) {
|
||||
channel_1_frequency = freq;
|
||||
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
return;
|
||||
|
||||
pwmcnt_t period = (pwmCFG.frequency / freq);
|
||||
@@ -82,14 +82,18 @@ void channel_1_set_frequency(float freq) {
|
||||
PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100));
|
||||
}
|
||||
|
||||
float channel_1_get_frequency(void) { return channel_1_frequency; }
|
||||
float channel_1_get_frequency(void) {
|
||||
return channel_1_frequency;
|
||||
}
|
||||
|
||||
void channel_1_start(void) {
|
||||
pwmStop(&AUDIO_PWM_DRIVER);
|
||||
pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
|
||||
}
|
||||
|
||||
void channel_1_stop(void) { pwmStop(&AUDIO_PWM_DRIVER); }
|
||||
void channel_1_stop(void) {
|
||||
pwmStop(&AUDIO_PWM_DRIVER);
|
||||
}
|
||||
|
||||
static void gpt_callback(GPTDriver *gptp);
|
||||
GPTConfig gptCFG = {
|
||||
@@ -108,9 +112,9 @@ void audio_driver_initialize(void) {
|
||||
pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
|
||||
|
||||
// connect the AUDIO_PIN to the PWM hardware
|
||||
#if defined(USE_GPIOV1) // STM32F103C8
|
||||
#if defined(USE_GPIOV1) // STM32F103C8
|
||||
palSetLineMode(AUDIO_PIN, PAL_MODE_ALTERNATE_PUSHPULL);
|
||||
#else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command)
|
||||
#else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command)
|
||||
palSetLineMode(AUDIO_PIN, PAL_MODE_ALTERNATE(AUDIO_PWM_PAL_MODE));
|
||||
#endif
|
||||
|
||||
@@ -135,10 +139,10 @@ void audio_driver_stop(void) {
|
||||
* and updates the pwm to output that frequency
|
||||
*/
|
||||
static void gpt_callback(GPTDriver *gptp) {
|
||||
float freq; // TODO: freq_alt
|
||||
float freq; // TODO: freq_alt
|
||||
|
||||
if (audio_update_state()) {
|
||||
freq = audio_get_processed_frequency(0); // freq_alt would be index=1
|
||||
freq = audio_get_processed_frequency(0); // freq_alt would be index=1
|
||||
channel_1_set_frequency(freq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ static float channel_1_frequency = 0.0f;
|
||||
void channel_1_set_frequency(float freq) {
|
||||
channel_1_frequency = freq;
|
||||
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
if (freq <= 0.0) // a pause/rest has freq=0
|
||||
return;
|
||||
|
||||
pwmcnt_t period = (pwmCFG.frequency / freq);
|
||||
@@ -68,7 +68,9 @@ void channel_1_set_frequency(float freq) {
|
||||
PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100));
|
||||
}
|
||||
|
||||
float channel_1_get_frequency(void) { return channel_1_frequency; }
|
||||
float channel_1_get_frequency(void) {
|
||||
return channel_1_frequency;
|
||||
}
|
||||
|
||||
void channel_1_start(void) {
|
||||
pwmStop(&AUDIO_PWM_DRIVER);
|
||||
@@ -81,10 +83,10 @@ void channel_1_start(void) {
|
||||
void channel_1_stop(void) {
|
||||
pwmStop(&AUDIO_PWM_DRIVER);
|
||||
|
||||
palClearLine(AUDIO_PIN); // leave the line low, after last note was played
|
||||
palClearLine(AUDIO_PIN); // leave the line low, after last note was played
|
||||
|
||||
#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
|
||||
palClearLine(AUDIO_PIN_ALT); // leave the line low, after last note was played
|
||||
palClearLine(AUDIO_PIN_ALT); // leave the line low, after last note was played
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -100,7 +102,7 @@ static void pwm_audio_period_callback(PWMDriver *pwmp) {
|
||||
static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp) {
|
||||
(void)pwmp;
|
||||
if (channel_1_frequency > 0) {
|
||||
palSetLine(AUDIO_PIN); // generate a PWM signal on any pin, not necessarily the one connected to the timer
|
||||
palSetLine(AUDIO_PIN); // generate a PWM signal on any pin, not necessarily the one connected to the timer
|
||||
#if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
|
||||
palClearLine(AUDIO_PIN_ALT);
|
||||
#endif
|
||||
@@ -131,7 +133,7 @@ void audio_driver_initialize(void) {
|
||||
palClearLine(AUDIO_PIN_ALT);
|
||||
#endif
|
||||
|
||||
pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); // enable pwm callbacks
|
||||
pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER); // enable pwm callbacks
|
||||
pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1);
|
||||
|
||||
gptStart(&AUDIO_STATE_TIMER, &gptCFG);
|
||||
@@ -155,10 +157,10 @@ void audio_driver_stop(void) {
|
||||
* and updates the pwm to output that frequency
|
||||
*/
|
||||
static void gpt_callback(GPTDriver *gptp) {
|
||||
float freq; // TODO: freq_alt
|
||||
float freq; // TODO: freq_alt
|
||||
|
||||
if (audio_update_state()) {
|
||||
freq = audio_get_processed_frequency(0); // freq_alt would be index=1
|
||||
freq = audio_get_processed_frequency(0); // freq_alt would be index=1
|
||||
channel_1_set_frequency(freq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# define STM32_ONBOARD_EEPROM_SIZE 1024
|
||||
# else
|
||||
# include "eeconfig.h"
|
||||
# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing
|
||||
# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -27,8 +27,67 @@
|
||||
#include "quantum.h"
|
||||
#include "i2c_master.h"
|
||||
#include <string.h>
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#ifndef I2C1_SCL_PIN
|
||||
# define I2C1_SCL_PIN B6
|
||||
#endif
|
||||
#ifndef I2C1_SDA_PIN
|
||||
# define I2C1_SDA_PIN B7
|
||||
#endif
|
||||
|
||||
#ifdef USE_I2CV1
|
||||
# ifndef I2C1_OPMODE
|
||||
# define I2C1_OPMODE OPMODE_I2C
|
||||
# endif
|
||||
# ifndef I2C1_CLOCK_SPEED
|
||||
# define I2C1_CLOCK_SPEED 100000 /* 400000 */
|
||||
# endif
|
||||
# ifndef I2C1_DUTY_CYCLE
|
||||
# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */
|
||||
# endif
|
||||
#else
|
||||
// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||
# ifndef I2C1_TIMINGR_PRESC
|
||||
# define I2C1_TIMINGR_PRESC 0U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLDEL
|
||||
# define I2C1_TIMINGR_SCLDEL 7U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SDADEL
|
||||
# define I2C1_TIMINGR_SDADEL 0U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLH
|
||||
# define I2C1_TIMINGR_SCLH 38U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLL
|
||||
# define I2C1_TIMINGR_SCLL 129U
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef I2C_DRIVER
|
||||
# define I2C_DRIVER I2CD1
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPIOV1
|
||||
# ifndef I2C1_SCL_PAL_MODE
|
||||
# define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
|
||||
# endif
|
||||
# ifndef I2C1_SDA_PAL_MODE
|
||||
# define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
|
||||
# endif
|
||||
#else
|
||||
// The default PAL alternate modes are used to signal that the pins are used for I2C
|
||||
# ifndef I2C1_SCL_PAL_MODE
|
||||
# define I2C1_SCL_PAL_MODE 4
|
||||
# endif
|
||||
# ifndef I2C1_SDA_PAL_MODE
|
||||
# define I2C1_SDA_PAL_MODE 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static uint8_t i2c_address;
|
||||
|
||||
static const I2CConfig i2cconfig = {
|
||||
@@ -144,4 +203,6 @@ i2c_status_t i2c_readReg16(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uin
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
void i2c_stop(void) { i2cStop(&I2C_DRIVER); }
|
||||
void i2c_stop(void) {
|
||||
i2cStop(&I2C_DRIVER);
|
||||
}
|
||||
|
||||
@@ -24,66 +24,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#ifndef I2C1_SCL_PIN
|
||||
# define I2C1_SCL_PIN B6
|
||||
#endif
|
||||
#ifndef I2C1_SDA_PIN
|
||||
# define I2C1_SDA_PIN B7
|
||||
#endif
|
||||
|
||||
#ifdef USE_I2CV1
|
||||
# ifndef I2C1_OPMODE
|
||||
# define I2C1_OPMODE OPMODE_I2C
|
||||
# endif
|
||||
# ifndef I2C1_CLOCK_SPEED
|
||||
# define I2C1_CLOCK_SPEED 100000 /* 400000 */
|
||||
# endif
|
||||
# ifndef I2C1_DUTY_CYCLE
|
||||
# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */
|
||||
# endif
|
||||
#else
|
||||
// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||
# ifndef I2C1_TIMINGR_PRESC
|
||||
# define I2C1_TIMINGR_PRESC 0U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLDEL
|
||||
# define I2C1_TIMINGR_SCLDEL 7U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SDADEL
|
||||
# define I2C1_TIMINGR_SDADEL 0U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLH
|
||||
# define I2C1_TIMINGR_SCLH 38U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLL
|
||||
# define I2C1_TIMINGR_SCLL 129U
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef I2C_DRIVER
|
||||
# define I2C_DRIVER I2CD1
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPIOV1
|
||||
# ifndef I2C1_SCL_PAL_MODE
|
||||
# define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
|
||||
# endif
|
||||
# ifndef I2C1_SDA_PAL_MODE
|
||||
# define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
|
||||
# endif
|
||||
#else
|
||||
// The default PAL alternate modes are used to signal that the pins are used for I2C
|
||||
# ifndef I2C1_SCL_PAL_MODE
|
||||
# define I2C1_SCL_PAL_MODE 4
|
||||
# endif
|
||||
# ifndef I2C1_SDA_PAL_MODE
|
||||
# define I2C1_SDA_PAL_MODE 4
|
||||
# endif
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int16_t i2c_status_t;
|
||||
|
||||
|
||||
@@ -50,14 +50,30 @@
|
||||
# error invalid SELECT_SOFT_SERIAL_SPEED value
|
||||
#endif
|
||||
|
||||
inline static void serial_delay(void) { wait_us(SERIAL_DELAY); }
|
||||
inline static void serial_delay_half(void) { wait_us(SERIAL_DELAY / 2); }
|
||||
inline static void serial_delay_blip(void) { wait_us(1); }
|
||||
inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_input(void) { setPinInputHigh(SOFT_SERIAL_PIN); }
|
||||
inline static bool serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_delay(void) {
|
||||
wait_us(SERIAL_DELAY);
|
||||
}
|
||||
inline static void serial_delay_half(void) {
|
||||
wait_us(SERIAL_DELAY / 2);
|
||||
}
|
||||
inline static void serial_delay_blip(void) {
|
||||
wait_us(1);
|
||||
}
|
||||
inline static void serial_output(void) {
|
||||
setPinOutput(SOFT_SERIAL_PIN);
|
||||
}
|
||||
inline static void serial_input(void) {
|
||||
setPinInputHigh(SOFT_SERIAL_PIN);
|
||||
}
|
||||
inline static bool serial_read_pin(void) {
|
||||
return !!readPin(SOFT_SERIAL_PIN);
|
||||
}
|
||||
inline static void serial_low(void) {
|
||||
writePinLow(SOFT_SERIAL_PIN);
|
||||
}
|
||||
inline static void serial_high(void) {
|
||||
writePinHigh(SOFT_SERIAL_PIN);
|
||||
}
|
||||
|
||||
void interrupt_handler(void *arg);
|
||||
|
||||
@@ -155,7 +171,8 @@ void interrupt_handler(void *arg) {
|
||||
checksum_computed += split_trans_initiator2target_buffer(trans)[i];
|
||||
}
|
||||
checksum_computed ^= 7;
|
||||
uint8_t checksum_received = serial_read_byte();
|
||||
|
||||
serial_read_byte();
|
||||
sync_send();
|
||||
|
||||
// wait for the sync to finish sending
|
||||
@@ -179,8 +196,6 @@ void interrupt_handler(void *arg) {
|
||||
// wait for the sync to finish sending
|
||||
serial_delay();
|
||||
|
||||
*trans->status = (checksum_computed == checksum_received) ? TRANSACTION_ACCEPTED : TRANSACTION_DATA_ERROR;
|
||||
|
||||
// end transaction
|
||||
serial_input();
|
||||
|
||||
@@ -193,17 +208,12 @@ void interrupt_handler(void *arg) {
|
||||
/////////
|
||||
// start transaction by initiator
|
||||
//
|
||||
// int soft_serial_transaction(int sstd_index)
|
||||
// bool soft_serial_transaction(int sstd_index)
|
||||
//
|
||||
// Returns:
|
||||
// TRANSACTION_END
|
||||
// TRANSACTION_NO_RESPONSE
|
||||
// TRANSACTION_DATA_ERROR
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
int soft_serial_transaction(int sstd_index) {
|
||||
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
|
||||
bool soft_serial_transaction(int sstd_index) {
|
||||
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false;
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
|
||||
|
||||
// TODO: remove extra delay between transactions
|
||||
serial_delay();
|
||||
@@ -226,14 +236,14 @@ int soft_serial_transaction(int sstd_index) {
|
||||
// slave failed to pull the line low, assume not present
|
||||
dprintf("serial::NO_RESPONSE\n");
|
||||
chSysUnlock();
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the slave is present syncronize with it
|
||||
|
||||
uint8_t checksum = 0;
|
||||
// send data to the slave
|
||||
serial_write_byte(sstd_index); // first chunk is transaction id
|
||||
serial_write_byte(sstd_index); // first chunk is transaction id
|
||||
sync_recv();
|
||||
|
||||
for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
|
||||
@@ -245,7 +255,7 @@ int soft_serial_transaction(int sstd_index) {
|
||||
sync_recv();
|
||||
|
||||
serial_delay();
|
||||
serial_delay(); // read mid pulses
|
||||
serial_delay(); // read mid pulses
|
||||
|
||||
// receive data from the slave
|
||||
uint8_t checksum_computed = 0;
|
||||
@@ -266,7 +276,7 @@ int soft_serial_transaction(int sstd_index) {
|
||||
serial_high();
|
||||
|
||||
chSysUnlock();
|
||||
return TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
// always, release the line when not in use
|
||||
@@ -274,5 +284,5 @@ int soft_serial_transaction(int sstd_index) {
|
||||
serial_output();
|
||||
|
||||
chSysUnlock();
|
||||
return TRANSACTION_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ static SerialDriver* serial_driver = &SERIAL_USART_DRIVER;
|
||||
static inline bool react_to_transactions(void);
|
||||
static inline bool __attribute__((nonnull)) receive(uint8_t* destination, const size_t size);
|
||||
static inline bool __attribute__((nonnull)) send(const uint8_t* source, const size_t size);
|
||||
static inline int initiate_transaction(uint8_t sstd_index);
|
||||
static inline bool initiate_transaction(uint8_t sstd_index);
|
||||
static inline void usart_clear(void);
|
||||
|
||||
/**
|
||||
@@ -206,14 +206,12 @@ static inline bool react_to_transactions(void) {
|
||||
to signal that the slave is ready to receive possible transaction buffers */
|
||||
sstd_index ^= HANDSHAKE_MAGIC;
|
||||
if (!send(&sstd_index, sizeof(sstd_index))) {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Receive transaction buffer from the master. If this transaction requires it.*/
|
||||
if (trans->initiator2target_buffer_size) {
|
||||
if (!receive(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -226,12 +224,10 @@ static inline bool react_to_transactions(void) {
|
||||
/* Send transaction buffer to the master. If this transaction requires it. */
|
||||
if (trans->target2initiator_buffer_size) {
|
||||
if (!send(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*trans->status = TRANSACTION_ACCEPTED;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -242,7 +238,7 @@ void soft_serial_initiator_init(void) {
|
||||
usart_master_init(&serial_driver);
|
||||
|
||||
#if defined(MCU_STM32) && defined(SERIAL_USART_PIN_SWAP)
|
||||
serial_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins
|
||||
serial_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins
|
||||
#endif
|
||||
|
||||
sdStart(serial_driver, &serial_config);
|
||||
@@ -252,11 +248,9 @@ void soft_serial_initiator_init(void) {
|
||||
* @brief Start transaction from the master half to the slave half.
|
||||
*
|
||||
* @param index Transaction Table index of the transaction to start.
|
||||
* @return int TRANSACTION_NO_RESPONSE in case of Timeout.
|
||||
* TRANSACTION_TYPE_ERROR in case of invalid transaction index.
|
||||
* TRANSACTION_END in case of success.
|
||||
* @return bool Indicates success of transaction.
|
||||
*/
|
||||
int soft_serial_transaction(int index) {
|
||||
bool soft_serial_transaction(int index) {
|
||||
/* Clear the receive queue, to start with a clean slate.
|
||||
* Parts of failed transactions or spurious bytes could still be in it. */
|
||||
usart_clear();
|
||||
@@ -266,25 +260,19 @@ int soft_serial_transaction(int index) {
|
||||
/**
|
||||
* @brief Initiate transaction to slave half.
|
||||
*/
|
||||
static inline int initiate_transaction(uint8_t sstd_index) {
|
||||
static inline bool initiate_transaction(uint8_t sstd_index) {
|
||||
/* Sanity check that we are actually starting a valid transaction. */
|
||||
if (sstd_index >= NUM_TOTAL_TRANSACTIONS) {
|
||||
dprintln("USART: Illegal transaction Id.");
|
||||
return TRANSACTION_TYPE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
|
||||
|
||||
/* Transaction is not registered. Abort. */
|
||||
if (!trans->status) {
|
||||
dprintln("USART: Transaction not registered.");
|
||||
return TRANSACTION_TYPE_ERROR;
|
||||
}
|
||||
|
||||
/* Send transaction table index to the slave, which doubles as basic handshake token. */
|
||||
if (!send(&sstd_index, sizeof(sstd_index))) {
|
||||
dprintln("USART: Send Handshake failed.");
|
||||
return TRANSACTION_TYPE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t sstd_index_shake = 0xFF;
|
||||
@@ -295,14 +283,14 @@ static inline int initiate_transaction(uint8_t sstd_index) {
|
||||
*/
|
||||
if (!receive(&sstd_index_shake, sizeof(sstd_index_shake)) || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
|
||||
dprintln("USART: Handshake failed.");
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Send transaction buffer to the slave. If this transaction requires it. */
|
||||
if (trans->initiator2target_buffer_size) {
|
||||
if (!send(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
|
||||
dprintln("USART: Send failed.");
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,9 +298,9 @@ static inline int initiate_transaction(uint8_t sstd_index) {
|
||||
if (trans->target2initiator_buffer_size) {
|
||||
if (!receive(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
|
||||
dprintln("USART: Receive failed.");
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return TRANSACTION_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -50,15 +50,15 @@
|
||||
#endif
|
||||
|
||||
#if !defined(USART_CR1_M0)
|
||||
# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
|
||||
# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_CR1)
|
||||
# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
|
||||
# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_CR2)
|
||||
# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
|
||||
# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_CR3)
|
||||
|
||||
@@ -115,7 +115,7 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
|
||||
|
||||
#elif defined(HT32)
|
||||
spiConfig.cr0 = SPI_CR0_SELOEN;
|
||||
spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode
|
||||
spiConfig.cr1 = SPI_CR1_MODE | 8; // 8 bits and in master mode
|
||||
|
||||
if (lsbFirst) {
|
||||
spiConfig.cr1 |= SPI_CR1_FIRSTBIT;
|
||||
|
||||
@@ -43,7 +43,9 @@ void uart_init(uint32_t baud) {
|
||||
}
|
||||
}
|
||||
|
||||
void uart_write(uint8_t data) { sdPut(&SERIAL_DRIVER, c); }
|
||||
void uart_write(uint8_t data) {
|
||||
sdPut(&SERIAL_DRIVER, data);
|
||||
}
|
||||
|
||||
uint8_t uart_read(void) {
|
||||
msg_t res = sdGet(&SERIAL_DRIVER);
|
||||
@@ -51,8 +53,14 @@ uint8_t uart_read(void) {
|
||||
return (uint8_t)res;
|
||||
}
|
||||
|
||||
void uart_transmit(const uint8_t *data, uint16_t length) { sdWrite(&SERIAL_DRIVER, data, length); }
|
||||
void uart_transmit(const uint8_t *data, uint16_t length) {
|
||||
sdWrite(&SERIAL_DRIVER, data, length);
|
||||
}
|
||||
|
||||
void uart_receive(uint8_t *data, uint16_t length) { sdRead(&SERIAL_DRIVER, data, length); }
|
||||
void uart_receive(uint8_t *data, uint16_t length) {
|
||||
sdRead(&SERIAL_DRIVER, data, length);
|
||||
}
|
||||
|
||||
bool uart_available(void) { return !sdGetWouldBlock(&SERIAL_DRIVER); }
|
||||
bool uart_available(void) {
|
||||
return !sdGetWouldBlock(&SERIAL_DRIVER);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#ifndef USBPD_UCPD1_CFG1
|
||||
# define USBPD_UCPD1_CFG1 (UCPD_CFG1_PSC_UCPDCLK_0 | UCPD_CFG1_TRANSWIN_3 | UCPD_CFG1_IFRGAP_4 | UCPD_CFG1_HBITCLKDIV_4)
|
||||
#endif // USBPD_UCPD1_CFG1
|
||||
#endif // USBPD_UCPD1_CFG1
|
||||
|
||||
// Initialises the USBPD subsystem
|
||||
__attribute__((weak)) void usbpd_init(void) {
|
||||
@@ -64,7 +64,7 @@ __attribute__((weak)) usbpd_allowance_t usbpd_get_allowance(void) {
|
||||
switch (vstate_max) {
|
||||
case 0:
|
||||
case 1:
|
||||
return USBPD_500MA; // Note that this is 500mA (i.e. max USB 2.0), not 900mA, as we're not using USB 3.1 as a sink device.
|
||||
return USBPD_500MA; // Note that this is 500mA (i.e. max USB 2.0), not 900mA, as we're not using USB 3.1 as a sink device.
|
||||
case 2:
|
||||
return USBPD_1500MA;
|
||||
case 3:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# define NOP_FUDGE 0.4
|
||||
# else
|
||||
# error("NOP_FUDGE configuration required")
|
||||
# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
|
||||
# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
|
||||
// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
|
||||
#ifndef WS2812_RES
|
||||
# define WS2812_RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
|
||||
# define WS2812_RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
|
||||
#endif
|
||||
|
||||
#define NUMBER_NOPS 6
|
||||
#define CYCLES_PER_SEC (CPU_CLOCK / NUMBER_NOPS * NOP_FUDGE)
|
||||
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
|
||||
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
|
||||
#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
|
||||
#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
|
||||
|
||||
@@ -67,7 +67,9 @@ void sendByte(uint8_t byte) {
|
||||
}
|
||||
}
|
||||
|
||||
void ws2812_init(void) { palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); }
|
||||
void ws2812_init(void) {
|
||||
palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE);
|
||||
}
|
||||
|
||||
// Setleds for standard RGB
|
||||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
|
||||
|
||||
@@ -11,19 +11,19 @@
|
||||
#endif
|
||||
|
||||
#ifndef WS2812_PWM_DRIVER
|
||||
# define WS2812_PWM_DRIVER PWMD2 // TIMx
|
||||
# define WS2812_PWM_DRIVER PWMD2 // TIMx
|
||||
#endif
|
||||
#ifndef WS2812_PWM_CHANNEL
|
||||
# define WS2812_PWM_CHANNEL 2 // Channel
|
||||
# define WS2812_PWM_CHANNEL 2 // Channel
|
||||
#endif
|
||||
#ifndef WS2812_PWM_PAL_MODE
|
||||
# define WS2812_PWM_PAL_MODE 2 // DI Pin's alternate function value
|
||||
# define WS2812_PWM_PAL_MODE 2 // DI Pin's alternate function value
|
||||
#endif
|
||||
#ifndef WS2812_DMA_STREAM
|
||||
# define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA Stream for TIMx_UP
|
||||
# define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA Stream for TIMx_UP
|
||||
#endif
|
||||
#ifndef WS2812_DMA_CHANNEL
|
||||
# define WS2812_DMA_CHANNEL 2 // DMA Channel for TIMx_UP
|
||||
# define WS2812_DMA_CHANNEL 2 // DMA Channel for TIMx_UP
|
||||
#endif
|
||||
#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && !defined(WS2812_DMAMUX_ID)
|
||||
# error "please consult your MCU's datasheet and specify in your config.h: #define WS2812_DMAMUX_ID STM32_DMAMUX1_TIM?_UP"
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
#ifndef WS2812_PWM_TARGET_PERIOD
|
||||
//# define WS2812_PWM_TARGET_PERIOD 800000 // Original code is 800k...?
|
||||
# define WS2812_PWM_TARGET_PERIOD 80000 // TODO: work out why 10x less on f303/f4x1
|
||||
# define WS2812_PWM_TARGET_PERIOD 80000 // TODO: work out why 10x less on f303/f4x1
|
||||
#endif
|
||||
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
@@ -259,8 +259,10 @@ write/read to/from the other buffer).
|
||||
void ws2812_init(void) {
|
||||
// Initialize led frame buffer
|
||||
uint32_t i;
|
||||
for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle
|
||||
for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero
|
||||
for (i = 0; i < WS2812_COLOR_BIT_N; i++)
|
||||
ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle
|
||||
for (i = 0; i < WS2812_RESET_BIT_N; i++)
|
||||
ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero
|
||||
|
||||
palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE);
|
||||
|
||||
@@ -268,22 +270,22 @@ void ws2812_init(void) {
|
||||
//#pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config
|
||||
static const PWMConfig ws2812_pwm_config = {
|
||||
.frequency = WS2812_PWM_FREQUENCY,
|
||||
.period = WS2812_PWM_PERIOD, // Mit dieser Periode wird UDE-Event erzeugt und ein neuer Wert (Länge WS2812_BIT_N) vom DMA ins CCR geschrieben
|
||||
.period = WS2812_PWM_PERIOD, // Mit dieser Periode wird UDE-Event erzeugt und ein neuer Wert (Länge WS2812_BIT_N) vom DMA ins CCR geschrieben
|
||||
.callback = NULL,
|
||||
.channels =
|
||||
{
|
||||
[0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled
|
||||
[WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about
|
||||
[0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled
|
||||
[WS2812_PWM_CHANNEL - 1] = {.mode = WS2812_PWM_OUTPUT_MODE, .callback = NULL}, // Turn on the channel we care about
|
||||
},
|
||||
.cr2 = 0,
|
||||
.dier = TIM_DIER_UDE, // DMA on update event for next period
|
||||
.dier = TIM_DIER_UDE, // DMA on update event for next period
|
||||
};
|
||||
//#pragma GCC diagnostic pop // Restore command-line warning options
|
||||
|
||||
// Configure DMA
|
||||
// dmaInit(); // Joe added this
|
||||
dmaStreamAlloc(WS2812_DMA_STREAM - STM32_DMA_STREAM(0), 10, NULL, NULL);
|
||||
dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
|
||||
dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_PWM_CHANNEL - 1])); // Ziel ist der An-Zeit im Cap-Comp-Register
|
||||
dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer);
|
||||
dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N);
|
||||
dmaStreamSetMode(WS2812_DMA_STREAM, STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3));
|
||||
@@ -302,7 +304,7 @@ void ws2812_init(void) {
|
||||
// ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer,
|
||||
// disable counting, enable the channel, and then make whatever configuration changes we need.
|
||||
pwmStart(&WS2812_PWM_DRIVER, &ws2812_pwm_config);
|
||||
pwmEnableChannel(&WS2812_PWM_DRIVER, WS2812_PWM_CHANNEL - 1, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in
|
||||
pwmEnableChannel(&WS2812_PWM_DRIVER, WS2812_PWM_CHANNEL - 1, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in
|
||||
}
|
||||
|
||||
void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) {
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_0)
|
||||
#elif WS2812_SPI_DIVISOR == 8
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1)
|
||||
#elif WS2812_SPI_DIVISOR == 16 // same as default
|
||||
#elif WS2812_SPI_DIVISOR == 16 // same as default
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0)
|
||||
#elif WS2812_SPI_DIVISOR == 32
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2)
|
||||
@@ -53,14 +53,14 @@
|
||||
#elif WS2812_SPI_DIVISOR == 256
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
|
||||
#else
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0) // default
|
||||
# define WS2812_SPI_DIVISOR_CR1_BR_X (SPI_CR1_BR_1 | SPI_CR1_BR_0) // default
|
||||
#endif
|
||||
|
||||
// Use SPI circular buffer
|
||||
#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER
|
||||
# define WS2812_SPI_BUFFER_MODE 1 // circular buffer
|
||||
# define WS2812_SPI_BUFFER_MODE 1 // circular buffer
|
||||
#else
|
||||
# define WS2812_SPI_BUFFER_MODE 0 // normal buffer
|
||||
# define WS2812_SPI_BUFFER_MODE 0 // normal buffer
|
||||
#endif
|
||||
|
||||
#if defined(USE_GPIOV1)
|
||||
@@ -104,20 +104,30 @@ static void set_led_color_rgb(LED_TYPE color, int pos) {
|
||||
uint8_t* tx_start = &txbuf[PREAMBLE_SIZE];
|
||||
|
||||
#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j);
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j);
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.g, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.r, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j);
|
||||
#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.r, j);
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.r, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.b, j);
|
||||
#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.b, j);
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + j] = get_protocol_eq(color.b, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j);
|
||||
#endif
|
||||
#ifdef RGBW
|
||||
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 4 + j] = get_protocol_eq(color.w, j);
|
||||
for (int j = 0; j < 4; j++)
|
||||
tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 4 + j] = get_protocol_eq(color.w, j);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -126,7 +136,7 @@ void ws2812_init(void) {
|
||||
|
||||
#ifdef WS2812_SPI_SCK_PIN
|
||||
palSetLineMode(WS2812_SPI_SCK_PIN, WS2812_SCK_OUTPUT_MODE);
|
||||
#endif // WS2812_SPI_SCK_PIN
|
||||
#endif // WS2812_SPI_SCK_PIN
|
||||
|
||||
// TODO: more dynamic baudrate
|
||||
static const SPIConfig spicfg = {WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN), WS2812_SPI_DIVISOR_CR1_BR_X};
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
defined(RGB_BACKLIGHT_U80_A) || \
|
||||
defined(RGB_BACKLIGHT_DAWN60) || \
|
||||
defined(RGB_BACKLIGHT_PORTICO) || \
|
||||
defined(RGB_BACKLIGHT_PORTICO75) || \
|
||||
defined(RGB_BACKLIGHT_WT60_B) || \
|
||||
defined(RGB_BACKLIGHT_WT60_BX) || \
|
||||
defined(RGB_BACKLIGHT_WT60_C) || \
|
||||
@@ -89,6 +90,9 @@ LED_TYPE g_ws2812_leds[WS2812_LED_TOTAL];
|
||||
#elif defined(RGB_BACKLIGHT_NK87)
|
||||
#include "drivers/led/issi/is31fl3733.h"
|
||||
#define BACKLIGHT_LED_COUNT 128
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
#include "drivers/led/issi/is31fl3741.h"
|
||||
#define BACKLIGHT_LED_COUNT 98
|
||||
#else
|
||||
#include "drivers/led/issi/is31fl3731.h"
|
||||
#if defined(RGB_BACKLIGHT_U80_A)
|
||||
@@ -701,6 +705,135 @@ const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
|
||||
{ 1, C9_16, C7_15, C6_15 },
|
||||
{ 1, C8_16, C7_16, C6_16 }
|
||||
};
|
||||
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
// This is a 7-bit address, that gets left-shifted and bit 0
|
||||
// set to 0 for write, 1 for read (as per I2C protocol)
|
||||
#define ISSI_ADDR_1 0x30
|
||||
#define ISSI_ADDR_2
|
||||
|
||||
const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
|
||||
/* Refer to IS31 manual for these locations
|
||||
* driver
|
||||
* | R location
|
||||
* | | G location
|
||||
* | | | B location
|
||||
* | | | | */
|
||||
{0, CS18_SW1, CS17_SW1, CS16_SW1},
|
||||
{0, CS18_SW2, CS17_SW2, CS16_SW2},
|
||||
{0, CS18_SW3, CS17_SW3, CS16_SW3},
|
||||
{0, CS18_SW4, CS17_SW4, CS16_SW4},
|
||||
{0, CS18_SW5, CS17_SW5, CS16_SW5},
|
||||
{0, CS18_SW6, CS17_SW6, CS16_SW6},
|
||||
{0, CS18_SW7, CS17_SW7, CS16_SW7},
|
||||
{0, CS18_SW8, CS17_SW8, CS16_SW8},
|
||||
{0, CS18_SW9, CS17_SW9, CS16_SW9},
|
||||
|
||||
{0, CS21_SW1, CS20_SW1, CS19_SW1},
|
||||
{0, CS21_SW2, CS20_SW2, CS19_SW2},
|
||||
{0, CS21_SW3, CS20_SW3, CS19_SW3},
|
||||
{0, CS21_SW4, CS20_SW4, CS19_SW4},
|
||||
{0, CS21_SW5, CS20_SW5, CS19_SW5},
|
||||
{0, CS21_SW6, CS20_SW6, CS19_SW6}, //Encoder, NO_LED
|
||||
|
||||
{0, CS15_SW1, CS14_SW1, CS13_SW1},
|
||||
{0, CS15_SW2, CS14_SW2, CS13_SW2},
|
||||
{0, CS15_SW3, CS14_SW3, CS13_SW3},
|
||||
{0, CS15_SW4, CS14_SW4, CS13_SW4},
|
||||
{0, CS15_SW5, CS14_SW5, CS13_SW5},
|
||||
{0, CS15_SW6, CS14_SW6, CS13_SW6},
|
||||
{0, CS15_SW7, CS14_SW7, CS13_SW7},
|
||||
{0, CS15_SW8, CS14_SW8, CS13_SW8},
|
||||
{0, CS15_SW9, CS14_SW9, CS13_SW9},
|
||||
|
||||
{0, CS24_SW1, CS23_SW1, CS22_SW1},
|
||||
{0, CS24_SW2, CS23_SW2, CS22_SW2},
|
||||
{0, CS24_SW3, CS23_SW3, CS22_SW3},
|
||||
{0, CS24_SW4, CS23_SW4, CS22_SW4},
|
||||
{0, CS24_SW5, CS23_SW5, CS22_SW5},
|
||||
{0, CS24_SW6, CS23_SW6, CS22_SW6},
|
||||
|
||||
{0, CS12_SW1, CS11_SW1, CS10_SW1},
|
||||
{0, CS12_SW2, CS11_SW2, CS10_SW2},
|
||||
{0, CS12_SW3, CS11_SW3, CS10_SW3},
|
||||
{0, CS12_SW4, CS11_SW4, CS10_SW4},
|
||||
{0, CS12_SW5, CS11_SW5, CS10_SW5},
|
||||
{0, CS12_SW6, CS11_SW6, CS10_SW6},
|
||||
{0, CS12_SW7, CS11_SW7, CS10_SW7},
|
||||
{0, CS12_SW8, CS11_SW8, CS10_SW8},
|
||||
{0, CS12_SW9, CS11_SW9, CS10_SW9},
|
||||
|
||||
{0, CS27_SW1, CS26_SW1, CS25_SW1},
|
||||
{0, CS27_SW2, CS26_SW2, CS25_SW2},
|
||||
{0, CS27_SW3, CS26_SW3, CS25_SW3},
|
||||
{0, CS27_SW4, CS26_SW4, CS25_SW4},
|
||||
{0, CS27_SW5, CS26_SW5, CS25_SW5},
|
||||
{0, CS27_SW6, CS26_SW6, CS25_SW6},
|
||||
|
||||
{0, CS9_SW1, CS8_SW1, CS7_SW1},
|
||||
{0, CS9_SW2, CS8_SW2, CS7_SW2},
|
||||
{0, CS9_SW3, CS8_SW3, CS7_SW3},
|
||||
{0, CS9_SW4, CS8_SW4, CS7_SW4},
|
||||
{0, CS9_SW5, CS8_SW5, CS7_SW5},
|
||||
{0, CS9_SW6, CS8_SW6, CS7_SW6},
|
||||
{0, CS9_SW7, CS8_SW7, CS7_SW7},
|
||||
{0, CS9_SW8, CS8_SW8, CS7_SW8},
|
||||
{0, CS9_SW9, CS8_SW9, CS7_SW9},
|
||||
|
||||
{0, CS30_SW1, CS29_SW1, CS28_SW1},
|
||||
{0, CS30_SW2, CS29_SW2, CS28_SW2},
|
||||
{0, CS30_SW3, CS29_SW3, CS28_SW3},
|
||||
{0, CS30_SW4, CS29_SW4, CS28_SW4},
|
||||
|
||||
{0, CS6_SW1, CS5_SW1, CS4_SW1},
|
||||
{0, CS6_SW2, CS5_SW2, CS4_SW2},
|
||||
{0, CS6_SW3, CS5_SW3, CS4_SW3},
|
||||
{0, CS6_SW4, CS5_SW4, CS4_SW4},
|
||||
{0, CS6_SW5, CS5_SW5, CS4_SW5},
|
||||
{0, CS6_SW6, CS5_SW6, CS4_SW6},
|
||||
{0, CS6_SW7, CS5_SW7, CS4_SW7},
|
||||
{0, CS6_SW8, CS5_SW8, CS4_SW8},
|
||||
{0, CS6_SW9, CS5_SW9, CS4_SW9},
|
||||
|
||||
{0, CS33_SW1, CS32_SW1, CS31_SW1},
|
||||
{0, CS33_SW2, CS32_SW2, CS31_SW2},
|
||||
{0, CS33_SW3, CS32_SW3, CS31_SW3},
|
||||
{0, CS33_SW4, CS32_SW4, CS31_SW4},
|
||||
|
||||
{0, CS3_SW1, CS2_SW1, CS1_SW1},
|
||||
{0, CS3_SW2, CS2_SW2, CS1_SW2},
|
||||
{0, CS3_SW3, CS2_SW3, CS1_SW3},
|
||||
{0, CS3_SW6, CS2_SW6, CS1_SW6},
|
||||
{0, CS3_SW8, CS2_SW8, CS1_SW8},
|
||||
{0, CS3_SW9, CS2_SW9, CS1_SW9},
|
||||
|
||||
{0, CS36_SW1, CS35_SW1, CS34_SW1},
|
||||
{0, CS36_SW2, CS35_SW2, CS34_SW2},
|
||||
{0, CS36_SW3, CS35_SW3, CS34_SW3},
|
||||
|
||||
/*UNDERGLOW*/
|
||||
{0, CS39_SW1, CS38_SW1, CS37_SW1},
|
||||
{0, CS39_SW2, CS38_SW2, CS37_SW2},
|
||||
{0, CS39_SW3, CS38_SW3, CS37_SW3},
|
||||
{0, CS39_SW4, CS38_SW4, CS37_SW4},
|
||||
{0, CS39_SW5, CS38_SW5, CS37_SW5},
|
||||
{0, CS39_SW6, CS38_SW6, CS37_SW6},
|
||||
{0, CS39_SW7, CS38_SW7, CS37_SW7},
|
||||
{0, CS39_SW8, CS38_SW8, CS37_SW8},
|
||||
{0, CS39_SW9, CS38_SW9, CS37_SW9},
|
||||
|
||||
{0, CS36_SW4, CS35_SW4, CS34_SW4},
|
||||
{0, CS36_SW5, CS35_SW5, CS34_SW5},
|
||||
{0, CS36_SW6, CS35_SW6, CS34_SW6},
|
||||
{0, CS36_SW7, CS35_SW7, CS34_SW7},
|
||||
{0, CS36_SW8, CS35_SW8, CS34_SW8},
|
||||
{0, CS36_SW9, CS35_SW9, CS34_SW9},
|
||||
|
||||
{0, CS33_SW5, CS32_SW5, CS31_SW5},
|
||||
{0, CS33_SW6, CS32_SW6, CS31_SW6},
|
||||
{0, CS33_SW7, CS32_SW7, CS31_SW7}
|
||||
};
|
||||
|
||||
#elif defined(RGB_BACKLIGHT_M6_B)
|
||||
// Driver has fixed mapping of index to the red, green and blue LEDs
|
||||
#elif defined(RGB_BACKLIGHT_M10_C)
|
||||
@@ -865,7 +998,7 @@ const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
|
||||
{112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,60}, {24,64},
|
||||
{108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
|
||||
// LD0..LD1762
|
||||
|
||||
|
||||
{124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
|
||||
{116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {208,64}, {255,255}
|
||||
};
|
||||
@@ -1260,6 +1393,25 @@ const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
|
||||
{ 121, 215 }, { 119, 164 }, { 117, 134 }, { 114, 104 }, { 109, 76 }, { 98, 50 }, { 71, 34 }, { 37, 41 }, { 22, 65 }, { 15, 93 }, { 11, 122 }, { 8, 162 }, { 7, 205 }, { 6, 233 },
|
||||
{ 116, 236 }, { 113, 199 }, { 110, 164 }, { 82, 74 }, { 27, 106 }, { 20, 138 }, { 15, 183 }, { 13, 212 }, { 11, 240 }
|
||||
};
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
|
||||
{ 0, 0 }, { 18, 0 }, { 33, 0 }, { 48, 0 }, { 62, 0 }, { 81, 0 }, { 96, 0 }, { 110, 0 }, { 125, 0 }, { 143, 0 }, { 158, 0 }, { 173, 0 }, { 187, 0 }, { 205, 0 }, { 224, 0 },
|
||||
{ 0, 15 }, { 15, 15 }, { 29, 15 }, { 44, 15 }, { 59, 15 }, { 74, 15 }, { 88, 15 }, { 103, 15 }, { 118, 15 }, { 132, 15 }, { 147, 15 }, { 162, 15 }, { 176, 15 }, { 198, 15 }, { 224, 15 },
|
||||
{ 4, 26 }, { 22, 26 }, { 37, 26 }, { 51, 26 }, { 66, 26 }, { 81, 26 }, { 96, 26 }, { 110, 26 }, { 125, 26 }, { 140, 26 }, { 154, 26 }, { 169, 26 }, { 183, 26 }, { 202, 26 }, { 224, 26 },
|
||||
{ 5, 38 }, { 25, 38 }, { 40, 38 }, { 54, 38 }, { 69, 38 }, { 84, 38 }, { 98, 38 }, { 113, 38 }, { 128, 38 }, { 143, 38 }, { 157, 38 }, { 172, 38 }, { 197, 38 },
|
||||
{ 9, 49 }, { 33, 49 }, { 48, 49 }, { 62, 49 }, { 77, 49 }, { 92, 49 }, { 107, 49 }, { 121, 49 }, { 136, 49 }, { 151, 49 }, { 165, 49 }, { 186, 49 }, { 209, 49 },
|
||||
{ 2, 61 }, { 20, 61 }, { 39, 61 }, { 94, 61 }, { 151, 61 }, { 173, 61 }, { 195, 64 }, { 209, 64 }, { 224, 64 },
|
||||
{ 2, 0 }, { 46, 0 }, { 90, 0 }, { 134, 0 }, { 178, 0 }, { 222, 0 }, { 224, 2 }, { 224, 32 }, { 224, 62 }, { 2, 64 }, { 46, 64 }, { 90, 64 }, { 134, 64 }, { 178, 64 }, { 222, 64 }, { 0, 2 }, { 0, 32 }, { 0, 62 }
|
||||
};
|
||||
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
|
||||
{ 138, 240 }, { 140, 205 }, { 143, 176 }, { 146, 147 }, { 150, 122 }, { 159, 92 }, { 172, 74 }, { 188, 66 }, { 206, 71 }, { 222, 92 }, { 229, 115 }, { 234, 142 }, { 238, 168 }, { 241, 203 }, { 243, 240 },
|
||||
{ 133, 233 }, { 134, 203 }, { 135, 175 }, { 137, 144 }, { 140, 115 }, { 144, 86 }, { 152, 61 }, { 171, 40 }, { 204, 37 }, { 226, 54 }, { 236, 80 }, { 241, 109 }, { 244, 136 }, { 246, 181 }, { 248, 233 },
|
||||
{ 129, 223 }, { 130, 186 }, { 130, 155 }, { 131, 126 }, { 132, 96 }, { 135, 65 }, { 142, 35 }, { 177, 13 }, { 237, 30 }, { 245, 59 }, { 248, 87 }, { 250, 118 }, { 251, 147 }, { 251, 186 }, { 252, 231 },
|
||||
{ 125, 221 }, { 124, 180 }, { 124, 149 }, { 123, 120 }, { 121, 89 }, { 118, 59 }, { 111, 31 }, { 57, 13 }, { 15, 35 }, { 8, 65 }, { 5, 94 }, { 4, 124 }, { 3, 176 },
|
||||
{ 120, 215 }, { 118, 166 }, { 117, 136 }, { 114, 109 }, { 109, 80 }, { 99, 54 }, { 75, 37 }, { 44, 40 }, { 25, 61 }, { 17, 88 }, { 13, 115 }, { 9, 156 }, { 7, 203 },
|
||||
{ 117, 234 }, { 115, 199 }, { 112, 162 }, { 86, 70 }, { 26, 100 }, { 18, 139 }, { 15, 183 }, { 13, 210 }, { 11, 240 },
|
||||
{ 138, 236 }, { 145, 151 }, { 166, 80 }, { 215, 80 }, { 236, 151 }, { 243, 236 }, { 243, 239 }, { 0, 231 }, { 11, 239 }, { 116, 236 }, { 109, 151 }, { 88, 80 }, { 39, 80 }, { 18, 151 }, { 11, 236 }, { 138, 239 }, { 127, 231 }, { 116, 239 }
|
||||
};
|
||||
#elif defined(RGB_BACKLIGHT_M50_A)
|
||||
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
|
||||
// LA0..LA17
|
||||
@@ -1303,7 +1455,7 @@ void map_led_to_point( uint8_t index, Point *point )
|
||||
point->y = pgm_read_byte(addr+1);
|
||||
|
||||
#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_M10_C) || defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65) || defined(RGB_BACKLIGHT_PORTICO) || \
|
||||
defined(RGB_BACKLIGHT_NK87) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_NEBULA12) || defined(RGB_BACKLIGHT_KW_MEGA)
|
||||
defined(RGB_BACKLIGHT_PORTICO75) || defined(RGB_BACKLIGHT_NK87) || defined(RGB_BACKLIGHT_NEBULA68) || defined(RGB_BACKLIGHT_NEBULA12) || defined(RGB_BACKLIGHT_KW_MEGA)
|
||||
return;
|
||||
#endif
|
||||
|
||||
@@ -1586,6 +1738,15 @@ const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
|
||||
{ 44, 255, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 },
|
||||
{ 58, 59, 60, 255, 255, 255, 61, 255, 255, 255, 62, 63, 64, 65, 66 }
|
||||
};
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
|
||||
{ 0, 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, 255, 255 },
|
||||
{ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 255, 255 },
|
||||
{ 71, 72, 73, 255, 255, 74, 255, 255, 255, 75, 76, 77, 78, 79, 255 }
|
||||
};
|
||||
#elif defined(RGB_BACKLIGHT_M50_A)
|
||||
// LA15, LA14, LA13, LA12, LA11, LA10, LA9, LB1, LB2, LB3, LB4, LB5, LB6
|
||||
// LA16, LA6, LA5, LA4, LA3, LA2, LA1, LB9, LB10, LB11, LB12, LB13, LB14
|
||||
@@ -1612,6 +1773,9 @@ void backlight_update_pwm_buffers(void)
|
||||
{
|
||||
#if defined(RGB_BACKLIGHT_M6_B)
|
||||
IS31FL3218_update_pwm_buffers();
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
IS31FL3741_update_pwm_buffers( ISSI_ADDR_1, 0 );
|
||||
IS31FL3741_update_led_control_registers( ISSI_ADDR_1, 0 );
|
||||
#elif defined(RGB_BACKLIGHT_M10_C)
|
||||
IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, 0 );
|
||||
IS31FL3731_update_led_control_registers( ISSI_ADDR_1, 0 );
|
||||
@@ -1660,6 +1824,8 @@ void backlight_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
|
||||
IS31FL3733_set_color( index, red, green, blue );
|
||||
#elif defined (RGB_BACKLIGHT_PORTICO)
|
||||
IS31FL3731_set_color( index, red, green, blue );
|
||||
#elif defined (RGB_BACKLIGHT_PORTICO75)
|
||||
IS31FL3741_set_color( index, red, green, blue );
|
||||
#elif defined(RGB_BACKLIGHT_NK87)
|
||||
// This is done to avoid indicator LEDs being set
|
||||
if (( index != 63+64-1 ) && ( index != 48+64-1 )) {
|
||||
@@ -1693,6 +1859,11 @@ void backlight_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
|
||||
for (int i = 0; i < BACKLIGHT_LED_COUNT; i++) {
|
||||
IS31FL3731_set_color(i, red, green, blue);
|
||||
}
|
||||
#elif defined (RGB_BACKLIGHT_PORTICO75)
|
||||
// This is done to avoid indicator LEDs being set
|
||||
for (int i = 0; i < BACKLIGHT_LED_COUNT; i++) {
|
||||
IS31FL3741_set_color(i, red, green, blue);
|
||||
}
|
||||
#elif defined(RGB_BACKLIGHT_NK87)
|
||||
// This is done to avoid indicator LEDs being set
|
||||
for (int i = 0; i < BACKLIGHT_LED_COUNT; i++) {
|
||||
@@ -1933,6 +2104,15 @@ void backlight_effect_alphas_mods(void)
|
||||
{
|
||||
is_alpha = ( column < 16 ) && (( g_config.alphas_mods[row-1] & (1<<column) ) == 0);
|
||||
}
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
if ( row == 0 )
|
||||
{
|
||||
is_alpha = ( ( 0b11100000111100001 & (1<<column) ) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_alpha = ( column < 16 ) && (( g_config.alphas_mods[row-1] & (1<<column) ) == 0);
|
||||
}
|
||||
#else
|
||||
is_alpha = ( g_config.alphas_mods[row] & (1<<column) ) == 0;
|
||||
#endif
|
||||
@@ -2824,6 +3004,15 @@ void backlight_init_drivers(void)
|
||||
// This actually updates the LED drivers
|
||||
IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
|
||||
IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
|
||||
#elif defined(RGB_BACKLIGHT_PORTICO75)
|
||||
IS31FL3741_init( ISSI_ADDR_1 );
|
||||
bool enabled = true;
|
||||
for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
|
||||
{
|
||||
IS31FL3741_set_led_control_register( index, enabled, enabled, enabled );
|
||||
}
|
||||
// This actually updates the LED drivers
|
||||
IS31FL3741_update_led_control_registers( ISSI_ADDR_1, 0 );
|
||||
#elif defined(RGB_BACKLIGHT_KW_MEGA)
|
||||
IS31FL3733_init( ISSI_ADDR_1, 0 );
|
||||
IS31FL3733_init( ISSI_ADDR_2, 0 );
|
||||
|
||||
@@ -133,10 +133,6 @@
|
||||
*/
|
||||
|
||||
#include "eeprom_stm32_defs.h"
|
||||
#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) || !defined(FEE_MCU_FLASH_SIZE) || !defined(FEE_PAGE_BASE_ADDRESS)
|
||||
# error "not implemented."
|
||||
#endif
|
||||
|
||||
/* These bits are used for optimizing encoding of bytes, 0 and 1 */
|
||||
#define FEE_WORD_ENCODING 0x8000
|
||||
#define FEE_VALUE_NEXT 0x6000
|
||||
@@ -144,69 +140,11 @@
|
||||
#define FEE_VALUE_ENCODED 0x2000
|
||||
#define FEE_BYTE_RANGE 0x80
|
||||
|
||||
/* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */
|
||||
#define FEE_ADDRESS_MAX_SIZE 0x4000
|
||||
|
||||
/* Flash word value after erase */
|
||||
#define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
|
||||
|
||||
/* Size of combined compacted eeprom and write log pages */
|
||||
#define FEE_DENSITY_MAX_SIZE (FEE_PAGE_COUNT * FEE_PAGE_SIZE)
|
||||
|
||||
#ifndef FEE_MCU_FLASH_SIZE_IGNORE_CHECK /* *TODO: Get rid of this check */
|
||||
# if FEE_DENSITY_MAX_SIZE > (FEE_MCU_FLASH_SIZE * 1024)
|
||||
# pragma message STR(FEE_DENSITY_MAX_SIZE) " > " STR(FEE_MCU_FLASH_SIZE * 1024)
|
||||
# error emulated eeprom: FEE_DENSITY_MAX_SIZE is greater than available flash size
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Size of emulated eeprom */
|
||||
#ifdef FEE_DENSITY_BYTES
|
||||
# if (FEE_DENSITY_BYTES > FEE_DENSITY_MAX_SIZE)
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES exceeds FEE_DENSITY_MAX_SIZE
|
||||
# endif
|
||||
# if (FEE_DENSITY_BYTES == FEE_DENSITY_MAX_SIZE)
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " == " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# warning emulated eeprom: FEE_DENSITY_BYTES leaves no room for a write log. This will greatly increase the flash wear rate!
|
||||
# endif
|
||||
# if FEE_DENSITY_BYTES > FEE_ADDRESS_MAX_SIZE
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_ADDRESS_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES is greater than FEE_ADDRESS_MAX_SIZE allows
|
||||
# endif
|
||||
# if ((FEE_DENSITY_BYTES) % 2) == 1
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES must be even
|
||||
# endif
|
||||
#else
|
||||
/* Default to half of allocated space used for emulated eeprom, half for write log */
|
||||
# define FEE_DENSITY_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE / 2)
|
||||
#endif
|
||||
|
||||
/* Size of write log */
|
||||
#ifdef FEE_WRITE_LOG_BYTES
|
||||
# if ((FEE_DENSITY_BYTES + FEE_WRITE_LOG_BYTES) > FEE_DENSITY_MAX_SIZE)
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " + " STR(FEE_WRITE_LOG_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES exceeds remaining FEE_DENSITY_MAX_SIZE
|
||||
# endif
|
||||
# if ((FEE_WRITE_LOG_BYTES) % 2) == 1
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES must be even
|
||||
# endif
|
||||
#else
|
||||
/* Default to use all remaining space */
|
||||
# define FEE_WRITE_LOG_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE - FEE_DENSITY_BYTES)
|
||||
#endif
|
||||
|
||||
/* Start of the emulated eeprom compacted flash area */
|
||||
#define FEE_COMPACTED_BASE_ADDRESS FEE_PAGE_BASE_ADDRESS
|
||||
/* End of the emulated eeprom compacted flash area */
|
||||
#define FEE_COMPACTED_LAST_ADDRESS (FEE_COMPACTED_BASE_ADDRESS + FEE_DENSITY_BYTES)
|
||||
/* Start of the emulated eeprom write log */
|
||||
#define FEE_WRITE_LOG_BASE_ADDRESS FEE_COMPACTED_LAST_ADDRESS
|
||||
/* End of the emulated eeprom write log */
|
||||
#define FEE_WRITE_LOG_LAST_ADDRESS (FEE_WRITE_LOG_BASE_ADDRESS + FEE_WRITE_LOG_BYTES)
|
||||
|
||||
#if defined(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) && (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= FEE_DENSITY_BYTES)
|
||||
# error emulated eeprom: DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is greater than the FEE_DENSITY_BYTES available
|
||||
#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) || !defined(FEE_MCU_FLASH_SIZE) || !defined(FEE_PAGE_BASE_ADDRESS)
|
||||
# error "not implemented."
|
||||
#endif
|
||||
|
||||
/* In-memory contents of emulated eeprom for faster access */
|
||||
@@ -622,9 +560,13 @@ uint16_t EEPROM_ReadDataWord(uint16_t Address) {
|
||||
/*****************************************************************************
|
||||
* Bind to eeprom_driver.c
|
||||
*******************************************************************************/
|
||||
void eeprom_driver_init(void) { EEPROM_Init(); }
|
||||
void eeprom_driver_init(void) {
|
||||
EEPROM_Init();
|
||||
}
|
||||
|
||||
void eeprom_driver_erase(void) { EEPROM_Erase(); }
|
||||
void eeprom_driver_erase(void) {
|
||||
EEPROM_Erase();
|
||||
}
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, size_t len) {
|
||||
const uint8_t *src = (const uint8_t *)addr;
|
||||
|
||||
@@ -20,41 +20,41 @@
|
||||
#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT)
|
||||
# if defined(STM32F103xB) || defined(STM32F042x6) || defined(GD32VF103C8) || defined(GD32VF103CB)
|
||||
# ifndef FEE_PAGE_SIZE
|
||||
# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte
|
||||
# define FEE_PAGE_SIZE 0x400 // Page size = 1KByte
|
||||
# endif
|
||||
# ifndef FEE_PAGE_COUNT
|
||||
# define FEE_PAGE_COUNT 2 // How many pages are used
|
||||
# define FEE_PAGE_COUNT 2 // How many pages are used
|
||||
# endif
|
||||
# elif defined(STM32F103xE) || defined(STM32F303xC) || defined(STM32F072xB) || defined(STM32F070xB)
|
||||
# ifndef FEE_PAGE_SIZE
|
||||
# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte
|
||||
# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte
|
||||
# endif
|
||||
# ifndef FEE_PAGE_COUNT
|
||||
# define FEE_PAGE_COUNT 4 // How many pages are used
|
||||
# define FEE_PAGE_COUNT 4 // How many pages are used
|
||||
# endif
|
||||
# elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE)
|
||||
# ifndef FEE_PAGE_SIZE
|
||||
# define FEE_PAGE_SIZE 0x4000 // Page size = 16KByte
|
||||
# define FEE_PAGE_SIZE 0x4000 // Page size = 16KByte
|
||||
# endif
|
||||
# ifndef FEE_PAGE_COUNT
|
||||
# define FEE_PAGE_COUNT 1 // How many pages are used
|
||||
# define FEE_PAGE_COUNT 1 // How many pages are used
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(FEE_MCU_FLASH_SIZE)
|
||||
# if defined(STM32F042x6)
|
||||
# define FEE_MCU_FLASH_SIZE 32 // Size in Kb
|
||||
# define FEE_MCU_FLASH_SIZE 32 // Size in Kb
|
||||
# elif defined(GD32VF103C8)
|
||||
# define FEE_MCU_FLASH_SIZE 64 // Size in Kb
|
||||
# define FEE_MCU_FLASH_SIZE 64 // Size in Kb
|
||||
# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(GD32VF103CB)
|
||||
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
|
||||
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
|
||||
# elif defined(STM32F303xC) || defined(STM32F401xC)
|
||||
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
|
||||
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
|
||||
# elif defined(STM32F103xE) || defined(STM32F401xE) || defined(STM32F411xE)
|
||||
# define FEE_MCU_FLASH_SIZE 512 // Size in Kb
|
||||
# define FEE_MCU_FLASH_SIZE 512 // Size in Kb
|
||||
# elif defined(STM32F405xG)
|
||||
# define FEE_MCU_FLASH_SIZE 1024 // Size in Kb
|
||||
# define FEE_MCU_FLASH_SIZE 1024 // Size in Kb
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
#if !defined(FEE_PAGE_BASE_ADDRESS)
|
||||
# if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xG) || defined(STM32F411xE)
|
||||
# ifndef FEE_PAGE_BASE_ADDRESS
|
||||
# define FEE_PAGE_BASE_ADDRESS 0x08004000 // bodge to force 2nd 16k page
|
||||
# define FEE_PAGE_BASE_ADDRESS 0x08004000 // bodge to force 2nd 16k page
|
||||
# endif
|
||||
# else
|
||||
# ifndef FEE_FLASH_BASE
|
||||
@@ -72,3 +72,65 @@
|
||||
# define FEE_PAGE_BASE_ADDRESS ((uintptr_t)(FEE_FLASH_BASE) + FEE_MCU_FLASH_SIZE * 1024 - (FEE_PAGE_COUNT * FEE_PAGE_SIZE))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Addressable range 16KByte: 0 <-> (0x1FFF << 1) */
|
||||
#define FEE_ADDRESS_MAX_SIZE 0x4000
|
||||
|
||||
/* Size of combined compacted eeprom and write log pages */
|
||||
#define FEE_DENSITY_MAX_SIZE (FEE_PAGE_COUNT * FEE_PAGE_SIZE)
|
||||
|
||||
#ifndef FEE_MCU_FLASH_SIZE_IGNORE_CHECK /* *TODO: Get rid of this check */
|
||||
# if FEE_DENSITY_MAX_SIZE > (FEE_MCU_FLASH_SIZE * 1024)
|
||||
# pragma message STR(FEE_DENSITY_MAX_SIZE) " > " STR(FEE_MCU_FLASH_SIZE * 1024)
|
||||
# error emulated eeprom: FEE_DENSITY_MAX_SIZE is greater than available flash size
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Size of emulated eeprom */
|
||||
#ifdef FEE_DENSITY_BYTES
|
||||
# if (FEE_DENSITY_BYTES > FEE_DENSITY_MAX_SIZE)
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES exceeds FEE_DENSITY_MAX_SIZE
|
||||
# endif
|
||||
# if (FEE_DENSITY_BYTES == FEE_DENSITY_MAX_SIZE)
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " == " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# warning emulated eeprom: FEE_DENSITY_BYTES leaves no room for a write log. This will greatly increase the flash wear rate!
|
||||
# endif
|
||||
# if FEE_DENSITY_BYTES > FEE_ADDRESS_MAX_SIZE
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_ADDRESS_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES is greater than FEE_ADDRESS_MAX_SIZE allows
|
||||
# endif
|
||||
# if ((FEE_DENSITY_BYTES) % 2) == 1
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES must be even
|
||||
# endif
|
||||
#else
|
||||
/* Default to half of allocated space used for emulated eeprom, half for write log */
|
||||
# define FEE_DENSITY_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE / 2)
|
||||
#endif
|
||||
|
||||
/* Size of write log */
|
||||
#ifdef FEE_WRITE_LOG_BYTES
|
||||
# if ((FEE_DENSITY_BYTES + FEE_WRITE_LOG_BYTES) > FEE_DENSITY_MAX_SIZE)
|
||||
# pragma message STR(FEE_DENSITY_BYTES) " + " STR(FEE_WRITE_LOG_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES exceeds remaining FEE_DENSITY_MAX_SIZE
|
||||
# endif
|
||||
# if ((FEE_WRITE_LOG_BYTES) % 2) == 1
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES must be even
|
||||
# endif
|
||||
#else
|
||||
/* Default to use all remaining space */
|
||||
# define FEE_WRITE_LOG_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE - FEE_DENSITY_BYTES)
|
||||
#endif
|
||||
|
||||
/* Start of the emulated eeprom compacted flash area */
|
||||
#define FEE_COMPACTED_BASE_ADDRESS FEE_PAGE_BASE_ADDRESS
|
||||
/* End of the emulated eeprom compacted flash area */
|
||||
#define FEE_COMPACTED_LAST_ADDRESS (FEE_COMPACTED_BASE_ADDRESS + FEE_DENSITY_BYTES)
|
||||
/* Start of the emulated eeprom write log */
|
||||
#define FEE_WRITE_LOG_BASE_ADDRESS FEE_COMPACTED_LAST_ADDRESS
|
||||
/* End of the emulated eeprom write log */
|
||||
#define FEE_WRITE_LOG_LAST_ADDRESS (FEE_WRITE_LOG_BASE_ADDRESS + FEE_WRITE_LOG_BYTES)
|
||||
|
||||
#if defined(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) && (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= FEE_DENSITY_BYTES)
|
||||
# error emulated eeprom: DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is greater than the FEE_DENSITY_BYTES available
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#include "eeprom_teensy.h"
|
||||
#include "eeconfig.h"
|
||||
|
||||
/*************************************/
|
||||
@@ -39,140 +40,9 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define SMC_PMSTAT_RUN ((uint8_t)0x01)
|
||||
#define SMC_PMSTAT_HSRUN ((uint8_t)0x80)
|
||||
|
||||
#define F_CPU KINETIS_SYSCLK_FREQUENCY
|
||||
|
||||
static inline int kinetis_hsrun_disable(void) {
|
||||
#if defined(MK66F18)
|
||||
if (SMC->PMSTAT == SMC_PMSTAT_HSRUN) {
|
||||
// First, reduce the CPU clock speed, but do not change
|
||||
// the peripheral speed (F_BUS). Serial1 & Serial2 baud
|
||||
// rates will be impacted, but most other peripherals
|
||||
// will continue functioning at the same speed.
|
||||
# if F_CPU == 256000000 && F_BUS == 64000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // TODO: TEST
|
||||
# elif F_CPU == 256000000 && F_BUS == 128000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // TODO: TEST
|
||||
# elif F_CPU == 240000000 && F_BUS == 60000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
|
||||
# elif F_CPU == 240000000 && F_BUS == 80000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
|
||||
# elif F_CPU == 240000000 && F_BUS == 120000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
|
||||
# elif F_CPU == 216000000 && F_BUS == 54000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
|
||||
# elif F_CPU == 216000000 && F_BUS == 72000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
|
||||
# elif F_CPU == 216000000 && F_BUS == 108000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
|
||||
# elif F_CPU == 192000000 && F_BUS == 48000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
|
||||
# elif F_CPU == 192000000 && F_BUS == 64000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
|
||||
# elif F_CPU == 192000000 && F_BUS == 96000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
|
||||
# elif F_CPU == 180000000 && F_BUS == 60000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
|
||||
# elif F_CPU == 180000000 && F_BUS == 90000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
|
||||
# elif F_CPU == 168000000 && F_BUS == 56000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
|
||||
# elif F_CPU == 144000000 && F_BUS == 48000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
|
||||
# elif F_CPU == 144000000 && F_BUS == 72000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 5); // ok
|
||||
# elif F_CPU == 120000000 && F_BUS == 60000000
|
||||
SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) |
|
||||
# if defined(MK66F18)
|
||||
SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) |
|
||||
# endif
|
||||
SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1);
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
// Then turn off HSRUN mode
|
||||
SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(0);
|
||||
while (SMC->PMSTAT == SMC_PMSTAT_HSRUN)
|
||||
; // wait
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kinetis_hsrun_enable(void) {
|
||||
#if defined(MK66F18)
|
||||
if (SMC->PMSTAT == SMC_PMSTAT_RUN) {
|
||||
// Turn HSRUN mode on
|
||||
SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(3);
|
||||
while (SMC->PMSTAT != SMC_PMSTAT_HSRUN) {
|
||||
;
|
||||
} // wait
|
||||
// Then configure clock for full speed
|
||||
# if F_CPU == 256000000 && F_BUS == 64000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
|
||||
# elif F_CPU == 256000000 && F_BUS == 128000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
|
||||
# elif F_CPU == 240000000 && F_BUS == 60000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
|
||||
# elif F_CPU == 240000000 && F_BUS == 80000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
|
||||
# elif F_CPU == 240000000 && F_BUS == 120000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
|
||||
# elif F_CPU == 216000000 && F_BUS == 54000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
|
||||
# elif F_CPU == 216000000 && F_BUS == 72000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
|
||||
# elif F_CPU == 216000000 && F_BUS == 108000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
|
||||
# elif F_CPU == 192000000 && F_BUS == 48000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 6);
|
||||
# elif F_CPU == 192000000 && F_BUS == 64000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
|
||||
# elif F_CPU == 192000000 && F_BUS == 96000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
|
||||
# elif F_CPU == 180000000 && F_BUS == 60000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
|
||||
# elif F_CPU == 180000000 && F_BUS == 90000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
|
||||
# elif F_CPU == 168000000 && F_BUS == 56000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 5);
|
||||
# elif F_CPU == 144000000 && F_BUS == 48000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 4);
|
||||
# elif F_CPU == 144000000 && F_BUS == 72000000
|
||||
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 4);
|
||||
# elif F_CPU == 120000000 && F_BUS == 60000000
|
||||
SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1 - 1) | SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2 - 1) |
|
||||
# if defined(MK66F18)
|
||||
SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3 - 1) |
|
||||
# endif
|
||||
SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4 - 1);
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(K20x) || defined(MK66F18) /* chip selection */
|
||||
#if defined(K20x) /* chip selection */
|
||||
/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
|
||||
|
||||
// The EEPROM is really RAM with a hardware-based backup system to
|
||||
// flash memory. Selecting a smaller size EEPROM allows more wear
|
||||
// leveling, for higher write endurance. If you edit this file,
|
||||
// set this to the smallest size your application can use. Also,
|
||||
// due to Freescale's implementation, writing 16 or 32 bit words
|
||||
// (aligned to 2 or 4 byte boundaries) has twice the endurance
|
||||
// compared to writing 8 bit bytes.
|
||||
//
|
||||
# ifndef EEPROM_SIZE
|
||||
# define EEPROM_SIZE 32
|
||||
# endif
|
||||
|
||||
/*
|
||||
^^^ Here be dragons:
|
||||
NXP AppNote AN4282 section 3.1 states that partitioning must only be done once.
|
||||
@@ -188,34 +58,22 @@ static inline int kinetis_hsrun_enable(void) {
|
||||
//
|
||||
# define HANDLE_UNALIGNED_WRITES
|
||||
|
||||
# if defined(K20x)
|
||||
# define EEPROM_MAX 2048
|
||||
# define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data
|
||||
# define EEESPLIT 0x30 // must be 0x30 on these chips
|
||||
# elif defined(MK66F18)
|
||||
# define EEPROM_MAX 4096
|
||||
# define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data
|
||||
# define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
|
||||
# endif
|
||||
|
||||
// Minimum EEPROM Endurance
|
||||
// ------------------------
|
||||
# if (EEPROM_SIZE == 4096)
|
||||
# define EEESIZE 0x02
|
||||
# elif (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
|
||||
# define EEESIZE 0x03
|
||||
# elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
|
||||
# define EEESIZE 0x04
|
||||
# elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
|
||||
# define EEESIZE 0x05
|
||||
# elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
|
||||
# define EEESIZE 0x06
|
||||
# elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
|
||||
# define EEESIZE 0x07
|
||||
# elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
|
||||
# define EEESIZE 0x08
|
||||
# elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
|
||||
# define EEESIZE 0x09
|
||||
# if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
|
||||
# define EEESIZE 0x33
|
||||
# elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
|
||||
# define EEESIZE 0x34
|
||||
# elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
|
||||
# define EEESIZE 0x35
|
||||
# elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
|
||||
# define EEESIZE 0x36
|
||||
# elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
|
||||
# define EEESIZE 0x37
|
||||
# elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
|
||||
# define EEESIZE 0x38
|
||||
# elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
|
||||
# define EEESIZE 0x39
|
||||
# endif
|
||||
|
||||
/** \brief eeprom initialization
|
||||
@@ -228,34 +86,28 @@ void eeprom_initialize(void) {
|
||||
uint8_t status;
|
||||
|
||||
if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
|
||||
// FlexRAM is configured as traditional RAM
|
||||
// We need to reconfigure for EEPROM usage
|
||||
kinetis_hsrun_disable();
|
||||
FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
|
||||
FTFL->FCCOB3 = 0;
|
||||
FTFL->FCCOB4 = EEESPLIT | EEESIZE;
|
||||
FTFL->FCCOB5 = EEPARTITION;
|
||||
FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
|
||||
FTFL->FCCOB4 = EEESIZE; // EEPROM Size
|
||||
FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
|
||||
__disable_irq();
|
||||
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
|
||||
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
|
||||
__enable_irq();
|
||||
kinetis_hsrun_enable();
|
||||
status = FTFL->FSTAT;
|
||||
if (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)) {
|
||||
FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL));
|
||||
return; // error
|
||||
return; // error
|
||||
}
|
||||
}
|
||||
// wait for eeprom to become ready (is this really necessary?)
|
||||
while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
|
||||
if (++count > 200000) break;
|
||||
if (++count > 20000) break;
|
||||
}
|
||||
}
|
||||
|
||||
# define FlexRAM ((volatile uint8_t *)0x14000000)
|
||||
# define FlexRAM ((uint8_t *)0x14000000)
|
||||
|
||||
/** \brief eeprom read byte
|
||||
*
|
||||
@@ -310,7 +162,9 @@ void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
int eeprom_is_ready(void) { return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0; }
|
||||
int eeprom_is_ready(void) {
|
||||
return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
|
||||
}
|
||||
|
||||
/** \brief flexram wait
|
||||
*
|
||||
@@ -332,12 +186,8 @@ void eeprom_write_byte(uint8_t *addr, uint8_t value) {
|
||||
if (offset >= EEPROM_SIZE) return;
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
if (FlexRAM[offset] != value) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
FlexRAM[offset] = value;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,30 +204,18 @@ void eeprom_write_word(uint16_t *addr, uint16_t value) {
|
||||
if ((offset & 1) == 0) {
|
||||
# endif
|
||||
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint16_t *)(&FlexRAM[offset]) = value;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
# ifdef HANDLE_UNALIGNED_WRITES
|
||||
} else {
|
||||
if (FlexRAM[offset] != value) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
FlexRAM[offset] = value;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
if (FlexRAM[offset + 1] != (value >> 8)) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
FlexRAM[offset + 1] = value >> 8;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
}
|
||||
# endif
|
||||
@@ -397,57 +235,33 @@ void eeprom_write_dword(uint32_t *addr, uint32_t value) {
|
||||
case 0:
|
||||
# endif
|
||||
if (*(uint32_t *)(&FlexRAM[offset]) != value) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint32_t *)(&FlexRAM[offset]) = value;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
return;
|
||||
# ifdef HANDLE_UNALIGNED_WRITES
|
||||
case 2:
|
||||
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint16_t *)(&FlexRAM[offset]) = value;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
return;
|
||||
default:
|
||||
if (FlexRAM[offset] != value) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
FlexRAM[offset] = value;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
if (FlexRAM[offset + 3] != (value >> 24)) {
|
||||
kinetis_hsrun_disable();
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
FlexRAM[offset + 3] = value >> 24;
|
||||
flexram_wait();
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
}
|
||||
# endif
|
||||
@@ -465,7 +279,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
|
||||
if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
|
||||
if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
|
||||
kinetis_hsrun_disable();
|
||||
while (len > 0) {
|
||||
uint32_t lsb = offset & 3;
|
||||
if (lsb == 0 && len >= 4) {
|
||||
@@ -476,8 +289,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
val32 |= (*src++ << 16);
|
||||
val32 |= (*src++ << 24);
|
||||
if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint32_t *)(&FlexRAM[offset]) = val32;
|
||||
flexram_wait();
|
||||
}
|
||||
@@ -489,8 +300,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
val16 = *src++;
|
||||
val16 |= (*src++ << 8);
|
||||
if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
*(uint16_t *)(&FlexRAM[offset]) = val16;
|
||||
flexram_wait();
|
||||
}
|
||||
@@ -500,8 +309,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
// write 8 bits
|
||||
uint8_t val8 = *src++;
|
||||
if (FlexRAM[offset] != val8) {
|
||||
uint8_t stat = FTFL->FSTAT & 0x70;
|
||||
if (stat) FTFL->FSTAT = stat;
|
||||
FlexRAM[offset] = val8;
|
||||
flexram_wait();
|
||||
}
|
||||
@@ -509,7 +316,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
kinetis_hsrun_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -535,8 +341,6 @@ void do_flash_cmd(volatile uint8_t *fstat)
|
||||
extern uint32_t __eeprom_workarea_start__;
|
||||
extern uint32_t __eeprom_workarea_end__;
|
||||
|
||||
# define EEPROM_SIZE 128
|
||||
|
||||
static uint32_t flashend = 0;
|
||||
|
||||
void eeprom_initialize(void) {
|
||||
@@ -684,7 +488,9 @@ void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
int eeprom_is_ready(void) { return 1; }
|
||||
int eeprom_is_ready(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void eeprom_write_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
@@ -709,68 +515,13 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
|
||||
}
|
||||
|
||||
#else
|
||||
// No EEPROM supported, so emulate it
|
||||
|
||||
# ifndef EEPROM_SIZE
|
||||
# include "eeconfig.h"
|
||||
# define EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO
|
||||
# endif
|
||||
__attribute__((aligned(4))) static uint8_t buffer[EEPROM_SIZE];
|
||||
|
||||
uint8_t eeprom_read_byte(const uint8_t *addr) {
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
return buffer[offset];
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint8_t *addr, uint8_t value) {
|
||||
uint32_t offset = (uint32_t)addr;
|
||||
buffer[offset] = value;
|
||||
}
|
||||
|
||||
uint16_t eeprom_read_word(const uint16_t *addr) {
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8);
|
||||
}
|
||||
|
||||
uint32_t eeprom_read_dword(const uint32_t *addr) {
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24);
|
||||
}
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, size_t len) {
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
uint8_t * dest = (uint8_t *)buf;
|
||||
while (len--) {
|
||||
*dest++ = eeprom_read_byte(p++);
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p, value >> 8);
|
||||
}
|
||||
|
||||
void eeprom_write_dword(uint32_t *addr, uint32_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
eeprom_write_byte(p++, value);
|
||||
eeprom_write_byte(p++, value >> 8);
|
||||
eeprom_write_byte(p++, value >> 16);
|
||||
eeprom_write_byte(p, value >> 24);
|
||||
}
|
||||
|
||||
void eeprom_write_block(const void *buf, void *addr, size_t len) {
|
||||
uint8_t * p = (uint8_t *)addr;
|
||||
const uint8_t *src = (const uint8_t *)buf;
|
||||
while (len--) {
|
||||
eeprom_write_byte(p++, *src++);
|
||||
}
|
||||
}
|
||||
|
||||
# error Unsupported Teensy EEPROM.
|
||||
#endif /* chip selection */
|
||||
// The update functions just calls write for now, but could probably be optimized
|
||||
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); }
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) {
|
||||
eeprom_write_byte(addr, value);
|
||||
}
|
||||
|
||||
void eeprom_update_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
|
||||
25
platforms/chibios/eeprom_teensy.h
Executable file
25
platforms/chibios/eeprom_teensy.h
Executable file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2022 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#if defined(K20x)
|
||||
/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
|
||||
// The EEPROM is really RAM with a hardware-based backup system to
|
||||
// flash memory. Selecting a smaller size EEPROM allows more wear
|
||||
// leveling, for higher write endurance. If you edit this file,
|
||||
// set this to the smallest size your application can use. Also,
|
||||
// due to Freescale's implementation, writing 16 or 32 bit words
|
||||
// (aligned to 2 or 4 byte boundaries) has twice the endurance
|
||||
// compared to writing 8 bit bytes.
|
||||
//
|
||||
# ifndef EEPROM_SIZE
|
||||
# define EEPROM_SIZE 32
|
||||
# endif
|
||||
#elif defined(KL2x) /* Teensy LC (emulated) */
|
||||
# define EEPROM_SIZE 128
|
||||
#else
|
||||
# error Unsupported Teensy EEPROM.
|
||||
#endif
|
||||
@@ -97,10 +97,10 @@
|
||||
/* Serial USART redefines. */
|
||||
#if HAL_USE_SERIAL
|
||||
# if !defined(SERIAL_USART_CR1)
|
||||
# define SERIAL_USART_CR1 (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL) // parity enable, odd parity, 9 bit length
|
||||
# define SERIAL_USART_CR1 (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL) // parity enable, odd parity, 9 bit length
|
||||
# endif
|
||||
# if !defined(SERIAL_USART_CR2)
|
||||
# define SERIAL_USART_CR2 (USART_CTL1_STB_1) // 2 stop bits
|
||||
# define SERIAL_USART_CR2 (USART_CTL1_STB_1) // 2 stop bits
|
||||
# endif
|
||||
# if !defined(SERIAL_USART_CR3)
|
||||
# define SERIAL_USART_CR3 0x0
|
||||
|
||||
@@ -22,10 +22,12 @@ typedef ioline_t pin_t;
|
||||
|
||||
/* Operation of GPIO by pin. */
|
||||
|
||||
#define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT)
|
||||
#define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)
|
||||
#define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)
|
||||
#define setPinOutput(pin) palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)
|
||||
#define setPinInput(pin) palSetLineMode((pin), PAL_MODE_INPUT)
|
||||
#define setPinInputHigh(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLUP)
|
||||
#define setPinInputLow(pin) palSetLineMode((pin), PAL_MODE_INPUT_PULLDOWN)
|
||||
#define setPinOutputPushPull(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_PUSHPULL)
|
||||
#define setPinOutputOpenDrain(pin) palSetLineMode((pin), PAL_MODE_OUTPUT_OPENDRAIN)
|
||||
#define setPinOutput(pin) setPinOutputPushPull(pin)
|
||||
|
||||
#define writePinHigh(pin) palSetLine(pin)
|
||||
#define writePinLow(pin) palClearLine(pin)
|
||||
@@ -34,17 +36,3 @@ typedef ioline_t pin_t;
|
||||
#define readPin(pin) palReadLine(pin)
|
||||
|
||||
#define togglePin(pin) palToggleLine(pin)
|
||||
|
||||
/* Operation of GPIO by port. */
|
||||
|
||||
typedef uint16_t port_data_t;
|
||||
|
||||
#define readPort(pin) palReadPort(PAL_PORT(pin))
|
||||
|
||||
#define setPortBitInput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT)
|
||||
#define setPortBitInputHigh(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLUP)
|
||||
#define setPortBitInputLow(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_INPUT_PULLDOWN)
|
||||
#define setPortBitOutput(pin, bit) palSetPadMode(PAL_PORT(pin), bit, PAL_MODE_OUTPUT_PUSHPULL)
|
||||
|
||||
#define writePortBitLow(pin, bit) palClearLine(PAL_LINE(PAL_PORT(pin), bit))
|
||||
#define writePortBitHigh(pin, bit) palSetLine(PAL_LINE(PAL_PORT(pin), bit))
|
||||
|
||||
@@ -344,7 +344,7 @@ ifeq ($(strip $(MCU)), risc-v)
|
||||
ifneq ($(shell which riscv64-unknown-elf-gcc 2>/dev/null),)
|
||||
TOOLCHAIN = riscv64-unknown-elf-
|
||||
else
|
||||
$(error "No RISC-V toolchain found. Can't find riscv32-unknown-elf-gcc or riscv64-unknown-elf-gcc found in your systems PATH variable. Please install a valid toolchain and make it accessible!")
|
||||
$(call CATASTROPHIC_ERROR,Missing toolchain,No RISC-V toolchain found. Can't find riscv32-unknown-elf-gcc or riscv64-unknown-elf-gcc found in your systems PATH variable. Please install a valid toolchain and make it accessible!)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -93,7 +93,7 @@ void sleep_led_init(void) {
|
||||
/* Reset LPTMR settings */
|
||||
LPTMR0->CSR = 0;
|
||||
/* Set the compare value */
|
||||
LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
|
||||
LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
|
||||
|
||||
/* Set up clock source and prescaler */
|
||||
/* Software PWM
|
||||
@@ -118,11 +118,11 @@ void sleep_led_init(void) {
|
||||
/* === OPTION 2 === */
|
||||
# if 1
|
||||
// nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
|
||||
MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
|
||||
# if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
|
||||
MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
|
||||
# if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
|
||||
MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
|
||||
# endif /* KL27 */
|
||||
MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
|
||||
# endif /* KL27 */
|
||||
MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
|
||||
// to work in stop mode, also MCG_C1_IREFSTEN
|
||||
// Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
|
||||
// => approx F=61, R=256, duration = 4
|
||||
@@ -140,7 +140,7 @@ void sleep_led_init(void) {
|
||||
/* === END OPTIONS === */
|
||||
|
||||
/* Interrupt on TCF set (compare flag) */
|
||||
nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
|
||||
nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
|
||||
LPTMR0->CSR |= LPTMRx_CSR_TIE;
|
||||
}
|
||||
|
||||
@@ -169,21 +169,33 @@ static void gptTimerCallback(GPTDriver *gptp) {
|
||||
static const GPTConfig gptcfg = {1000000, gptTimerCallback, 0, 0};
|
||||
|
||||
/* Initialise the timer */
|
||||
void sleep_led_init(void) { gptStart(&SLEEP_LED_GPT_DRIVER, &gptcfg); }
|
||||
void sleep_led_init(void) {
|
||||
gptStart(&SLEEP_LED_GPT_DRIVER, &gptcfg);
|
||||
}
|
||||
|
||||
void sleep_led_enable(void) { gptStartContinuous(&SLEEP_LED_GPT_DRIVER, gptcfg.frequency / 0xFFFF); }
|
||||
void sleep_led_enable(void) {
|
||||
gptStartContinuous(&SLEEP_LED_GPT_DRIVER, gptcfg.frequency / 0xFFFF);
|
||||
}
|
||||
|
||||
void sleep_led_disable(void) { gptStopTimer(&SLEEP_LED_GPT_DRIVER); }
|
||||
void sleep_led_disable(void) {
|
||||
gptStopTimer(&SLEEP_LED_GPT_DRIVER);
|
||||
}
|
||||
|
||||
void sleep_led_toggle(void) { (SLEEP_LED_GPT_DRIVER.state == GPT_READY) ? sleep_led_enable() : sleep_led_disable(); }
|
||||
void sleep_led_toggle(void) {
|
||||
(SLEEP_LED_GPT_DRIVER.state == GPT_READY) ? sleep_led_enable() : sleep_led_disable();
|
||||
}
|
||||
|
||||
#else /* platform selection: not on familiar chips */
|
||||
|
||||
void sleep_led_init(void) {}
|
||||
|
||||
void sleep_led_enable(void) { led_set(1 << USB_LED_CAPS_LOCK); }
|
||||
void sleep_led_enable(void) {
|
||||
led_set(1 << USB_LED_CAPS_LOCK);
|
||||
}
|
||||
|
||||
void sleep_led_disable(void) { led_set(0); }
|
||||
void sleep_led_disable(void) {
|
||||
led_set(0);
|
||||
}
|
||||
|
||||
void sleep_led_toggle(void) {
|
||||
// not implemented
|
||||
|
||||
@@ -13,15 +13,6 @@
|
||||
#include "led.h"
|
||||
#include "wait.h"
|
||||
|
||||
/** \brief suspend idle
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void suspend_idle(uint8_t time) {
|
||||
// TODO: this is not used anywhere - what units is 'time' in?
|
||||
wait_ms(time);
|
||||
}
|
||||
|
||||
/** \brief suspend power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
@@ -34,34 +25,6 @@ void suspend_power_down(void) {
|
||||
wait_ms(17);
|
||||
}
|
||||
|
||||
/** \brief suspend wakeup condition
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void matrix_power_up(void) {}
|
||||
__attribute__((weak)) void matrix_power_down(void) {}
|
||||
bool suspend_wakeup_condition(void) {
|
||||
matrix_power_up();
|
||||
matrix_scan();
|
||||
matrix_power_down();
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
if (matrix_get_row(r)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \brief run user level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_wakeup_init_user(void) {}
|
||||
|
||||
/** \brief run keyboard level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
|
||||
|
||||
/** \brief suspend wakeup condition
|
||||
*
|
||||
* run immediately after wakeup
|
||||
|
||||
@@ -87,9 +87,13 @@ __attribute__((weak, used)) int _kill(int pid, int sig) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak, used)) pid_t _getpid(void) { return 1; }
|
||||
__attribute__((weak, used)) pid_t _getpid(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((weak, used)) void _fini(void) { return; }
|
||||
__attribute__((weak, used)) void _fini(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((weak, used, noreturn)) void _exit(int i) {
|
||||
while (1)
|
||||
|
||||
@@ -2,46 +2,106 @@
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
static uint32_t reset_point = 0;
|
||||
static uint32_t ticks_offset = 0;
|
||||
static uint32_t last_ticks = 0;
|
||||
static uint32_t ms_offset = 0;
|
||||
#if CH_CFG_ST_RESOLUTION < 32
|
||||
static uint32_t last_systime = 0;
|
||||
static uint32_t overflow = 0;
|
||||
#endif
|
||||
|
||||
void timer_init(void) { timer_clear(); }
|
||||
|
||||
void timer_clear(void) {
|
||||
reset_point = (uint32_t)chVTGetSystemTime();
|
||||
#if CH_CFG_ST_RESOLUTION < 32
|
||||
last_systime = reset_point;
|
||||
overflow = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t timer_read(void) { return (uint16_t)timer_read32(); }
|
||||
|
||||
uint32_t timer_read32(void) {
|
||||
uint32_t systime = (uint32_t)chVTGetSystemTime();
|
||||
// Get the current system time in ticks as a 32-bit number.
|
||||
// This function must be called from within a system lock zone (so that it can safely use and update the static data).
|
||||
static inline uint32_t get_system_time_ticks(void) {
|
||||
uint32_t systime = (uint32_t)chVTGetSystemTimeX();
|
||||
|
||||
#if CH_CFG_ST_RESOLUTION < 32
|
||||
// If/when we need to support 64-bit chips, this may need to be modified to match the native bit-ness of the MCU.
|
||||
// At this point, the only SysTick resolution allowed other than 32 is 16 bit.
|
||||
// In the 16-bit case, at:
|
||||
// If the real system timer resolution is less than 32 bits, provide the missing bits by checking for the counter
|
||||
// overflow. For this to work, this function must be called at least once for every overflow of the system timer.
|
||||
// In the 16-bit case, the corresponding times are:
|
||||
// - CH_CFG_ST_FREQUENCY = 100000, overflow will occur every ~0.65 seconds
|
||||
// - CH_CFG_ST_FREQUENCY = 10000, overflow will occur every ~6.5 seconds
|
||||
// - CH_CFG_ST_FREQUENCY = 1000, overflow will occur every ~65 seconds
|
||||
// With this implementation, as long as we ensure a timer read happens at least once during the overflow period, timing should be accurate.
|
||||
if (systime < last_systime) {
|
||||
overflow += ((uint32_t)1) << CH_CFG_ST_RESOLUTION;
|
||||
}
|
||||
|
||||
last_systime = systime;
|
||||
return (uint32_t)TIME_I2MS(systime - reset_point + overflow);
|
||||
#else
|
||||
return (uint32_t)TIME_I2MS(systime - reset_point);
|
||||
systime += overflow;
|
||||
#endif
|
||||
|
||||
return systime;
|
||||
}
|
||||
|
||||
#if CH_CFG_ST_RESOLUTION < 32
|
||||
static virtual_timer_t update_timer;
|
||||
|
||||
// Update the system tick counter every half of the timer overflow period; this should keep the tick counter correct
|
||||
// even if something blocks timer interrupts for 1/2 of the timer overflow period.
|
||||
# define UPDATE_INTERVAL (((sysinterval_t)1) << (CH_CFG_ST_RESOLUTION - 1))
|
||||
|
||||
// VT callback function to keep the overflow bits of the system tick counter updated.
|
||||
static void update_fn(void *arg) {
|
||||
(void)arg;
|
||||
chSysLockFromISR();
|
||||
get_system_time_ticks();
|
||||
chVTSetI(&update_timer, UPDATE_INTERVAL, update_fn, NULL);
|
||||
chSysUnlockFromISR();
|
||||
}
|
||||
#endif
|
||||
|
||||
// The highest multiple of CH_CFG_ST_FREQUENCY that fits into uint32_t. This number of ticks will necessarily
|
||||
// correspond to some integer number of seconds.
|
||||
#define OVERFLOW_ADJUST_TICKS ((uint32_t)((UINT32_MAX / CH_CFG_ST_FREQUENCY) * CH_CFG_ST_FREQUENCY))
|
||||
|
||||
// The time in milliseconds which corresponds to OVERFLOW_ADJUST_TICKS ticks (this is a precise conversion, because
|
||||
// OVERFLOW_ADJUST_TICKS corresponds to an integer number of seconds).
|
||||
#define OVERFLOW_ADJUST_MS (TIME_I2MS(OVERFLOW_ADJUST_TICKS))
|
||||
|
||||
void timer_init(void) {
|
||||
timer_clear();
|
||||
#if CH_CFG_ST_RESOLUTION < 32
|
||||
chVTObjectInit(&update_timer);
|
||||
chVTSet(&update_timer, UPDATE_INTERVAL, update_fn, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t timer_elapsed(uint16_t last) { return TIMER_DIFF_16(timer_read(), last); }
|
||||
void timer_clear(void) {
|
||||
chSysLock();
|
||||
ticks_offset = get_system_time_ticks();
|
||||
last_ticks = 0;
|
||||
ms_offset = 0;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
uint32_t timer_elapsed32(uint32_t last) { return TIMER_DIFF_32(timer_read32(), last); }
|
||||
uint16_t timer_read(void) {
|
||||
return (uint16_t)timer_read32();
|
||||
}
|
||||
|
||||
uint32_t timer_read32(void) {
|
||||
chSysLock();
|
||||
uint32_t ticks = get_system_time_ticks() - ticks_offset;
|
||||
if (ticks < last_ticks) {
|
||||
// The 32-bit tick counter overflowed and wrapped around. We cannot just extend the counter to 64 bits here,
|
||||
// because TIME_I2MS() may encounter overflows when handling a 64-bit argument; therefore the solution here is
|
||||
// to subtract a reasonably large number of ticks from the tick counter to bring its value below the 32-bit
|
||||
// limit again, and then add the equivalent number of milliseconds to the converted value. (Adjusting just the
|
||||
// converted value to account for 2**32 ticks is not possible in general, because 2**32 ticks may not correspond
|
||||
// to an integer number of milliseconds).
|
||||
ticks -= OVERFLOW_ADJUST_TICKS;
|
||||
ticks_offset += OVERFLOW_ADJUST_TICKS;
|
||||
ms_offset += OVERFLOW_ADJUST_MS;
|
||||
}
|
||||
last_ticks = ticks;
|
||||
uint32_t ms_offset_copy = ms_offset; // read while still holding the lock to ensure a consistent value
|
||||
chSysUnlock();
|
||||
|
||||
return (uint32_t)TIME_I2MS(ticks) + ms_offset_copy;
|
||||
}
|
||||
|
||||
uint16_t timer_elapsed(uint16_t last) {
|
||||
return TIMER_DIFF_16(timer_read(), last);
|
||||
}
|
||||
|
||||
uint32_t timer_elapsed32(uint32_t last) {
|
||||
return TIMER_DIFF_32(timer_read32(), last);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
PLATFORM_COMMON_DIR = $(PLATFORM_PATH)/$(PLATFORM_KEY)
|
||||
|
||||
TMK_COMMON_SRC += \
|
||||
$(PLATFORM_PATH)/suspend.c \
|
||||
$(PLATFORM_COMMON_DIR)/platform.c \
|
||||
$(PLATFORM_COMMON_DIR)/suspend.c \
|
||||
$(PLATFORM_COMMON_DIR)/timer.c \
|
||||
$(PLATFORM_COMMON_DIR)/bootloader.c \
|
||||
$(PLATFORM_COMMON_DIR)/bootloaders/$(BOOTLOADER_TYPE).c
|
||||
|
||||
# Search Path
|
||||
VPATH += $(PLATFORM_PATH)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// Copyright 2018-2022 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#if defined(__AVR__) && !defined(EEPROM_DRIVER)
|
||||
@@ -19,3 +21,50 @@ void eeprom_update_word(uint16_t *__p, uint16_t __value);
|
||||
void eeprom_update_dword(uint32_t *__p, uint32_t __value);
|
||||
void eeprom_update_block(const void *__src, void *__dst, size_t __n);
|
||||
#endif
|
||||
|
||||
#if defined(EEPROM_CUSTOM)
|
||||
# ifndef EEPROM_SIZE
|
||||
# error EEPROM_SIZE has not been defined for custom driver.
|
||||
# endif
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (EEPROM_SIZE)
|
||||
#elif defined(EEPROM_TRANSIENT)
|
||||
# include "eeprom_transient.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (TRANSIENT_EEPROM_SIZE)
|
||||
#elif defined(EEPROM_I2C)
|
||||
# include "eeprom_i2c.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (EXTERNAL_EEPROM_BYTE_COUNT)
|
||||
#elif defined(EEPROM_SPI)
|
||||
# include "eeprom_spi.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (EXTERNAL_EEPROM_BYTE_COUNT)
|
||||
#elif defined(EEPROM_STM32_L0_L1)
|
||||
# include "eeprom_stm32_L0_L1.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (STM32_ONBOARD_EEPROM_SIZE)
|
||||
#elif defined(EEPROM_TEENSY)
|
||||
# include "eeprom_teensy.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (EEPROM_SIZE)
|
||||
#elif defined(EEPROM_STM32_FLASH_EMULATED)
|
||||
# include "eeprom_stm32_defs.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (FEE_DENSITY_BYTES)
|
||||
#elif defined(EEPROM_SAMD)
|
||||
# include "eeprom_samd.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (EEPROM_SIZE)
|
||||
#elif defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny85__)
|
||||
# define TOTAL_EEPROM_BYTE_COUNT 512
|
||||
#elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32A__)
|
||||
# define TOTAL_EEPROM_BYTE_COUNT 1024
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
|
||||
# define TOTAL_EEPROM_BYTE_COUNT 2048
|
||||
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
|
||||
# define TOTAL_EEPROM_BYTE_COUNT 4096
|
||||
#elif defined(EEPROM_TEST_HARNESS)
|
||||
# ifndef FLASH_STM32_MOCKED
|
||||
// Normal tests
|
||||
# define TOTAL_EEPROM_BYTE_COUNT 32
|
||||
# else
|
||||
// Flash wear-leveling testing
|
||||
# include "eeprom_stm32_tests.h"
|
||||
# define TOTAL_EEPROM_BYTE_COUNT (EEPROM_SIZE)
|
||||
# endif
|
||||
#else
|
||||
# error Unknown EEPROM driver.
|
||||
#endif
|
||||
|
||||
51
platforms/suspend.c
Normal file
51
platforms/suspend.c
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2022 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "suspend.h"
|
||||
#include "matrix.h"
|
||||
|
||||
// TODO: Move to more correct location
|
||||
__attribute__((weak)) void matrix_power_up(void) {}
|
||||
__attribute__((weak)) void matrix_power_down(void) {}
|
||||
|
||||
/** \brief Run user level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_power_down_user(void) {}
|
||||
|
||||
/** \brief Run keyboard level Power down
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_power_down_kb(void) {
|
||||
suspend_power_down_user();
|
||||
}
|
||||
|
||||
/** \brief run user level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_wakeup_init_user(void) {}
|
||||
|
||||
/** \brief run keyboard level code immediately after wakeup
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void suspend_wakeup_init_kb(void) {
|
||||
suspend_wakeup_init_user();
|
||||
}
|
||||
|
||||
/** \brief suspend wakeup condition
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
bool suspend_wakeup_condition(void) {
|
||||
matrix_power_up();
|
||||
matrix_scan();
|
||||
matrix_power_down();
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
if (matrix_get_row(r)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void suspend_idle(uint8_t timeout);
|
||||
void suspend_power_down(void);
|
||||
bool suspend_wakeup_condition(void);
|
||||
void suspend_wakeup_init(void);
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
#include "eeprom.h"
|
||||
|
||||
#define EEPROM_SIZE 32
|
||||
|
||||
static uint8_t buffer[EEPROM_SIZE];
|
||||
static uint8_t buffer[TOTAL_EEPROM_BYTE_COUNT];
|
||||
|
||||
uint8_t eeprom_read_byte(const uint8_t *addr) {
|
||||
uintptr_t offset = (uintptr_t)addr;
|
||||
@@ -70,7 +68,9 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); }
|
||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) {
|
||||
eeprom_write_byte(addr, value);
|
||||
}
|
||||
|
||||
void eeprom_update_word(uint16_t *addr, uint16_t value) {
|
||||
uint8_t *p = (uint8_t *)addr;
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
extern "C" {
|
||||
#include "flash_stm32.h"
|
||||
#include "eeprom_stm32.h"
|
||||
#include "eeprom.h"
|
||||
}
|
||||
|
||||
@@ -46,7 +44,6 @@ extern "C" {
|
||||
*
|
||||
*/
|
||||
|
||||
#define EEPROM_SIZE (FEE_PAGE_SIZE * FEE_PAGE_COUNT / 2)
|
||||
#define LOG_SIZE EEPROM_SIZE
|
||||
#define LOG_BASE (MOCK_FLASH_SIZE - LOG_SIZE)
|
||||
#define EEPROM_BASE (LOG_BASE - EEPROM_SIZE)
|
||||
@@ -63,7 +60,9 @@ class EepromStm32Test : public testing::Test {
|
||||
~EepromStm32Test() {}
|
||||
|
||||
protected:
|
||||
void SetUp() override { EEPROM_Erase(); }
|
||||
void SetUp() override {
|
||||
EEPROM_Erase();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
#ifdef EEPROM_DEBUG
|
||||
@@ -86,7 +85,7 @@ TEST_F(EepromStm32Test, TestReadGarbage) {
|
||||
garbage += i;
|
||||
FlashBuf[i] = garbage;
|
||||
}
|
||||
EEPROM_Init(); // Just verify we don't crash
|
||||
EEPROM_Init(); // Just verify we don't crash
|
||||
}
|
||||
|
||||
TEST_F(EepromStm32Test, TestWriteBadAddress) {
|
||||
@@ -209,11 +208,11 @@ TEST_F(EepromStm32Test, TestReadWord) {
|
||||
|
||||
TEST_F(EepromStm32Test, TestWriteWord) {
|
||||
/* Direct compacted-area: Address < 0x80 */
|
||||
EEPROM_WriteDataWord(0, 0xdead); // Aligned
|
||||
EEPROM_WriteDataWord(3, 0xbeef); // Unaligned
|
||||
EEPROM_WriteDataWord(0, 0xdead); // Aligned
|
||||
EEPROM_WriteDataWord(3, 0xbeef); // Unaligned
|
||||
/* Direct compacted-area: Address >= 0x80 */
|
||||
EEPROM_WriteDataWord(200, 0xabcd); // Aligned
|
||||
EEPROM_WriteDataWord(203, 0x9876); // Unaligned
|
||||
EEPROM_WriteDataWord(200, 0xabcd); // Aligned
|
||||
EEPROM_WriteDataWord(203, 0x9876); // Unaligned
|
||||
EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0x1234);
|
||||
EEPROM_WriteDataWord(EEPROM_SIZE - 2, 0x5678);
|
||||
/* Write Log word zero-encoded */
|
||||
@@ -221,10 +220,10 @@ TEST_F(EepromStm32Test, TestWriteWord) {
|
||||
/* Write Log word one-encoded */
|
||||
EEPROM_WriteDataWord(EEPROM_SIZE - 2, 1);
|
||||
/* Write Log word value aligned */
|
||||
EEPROM_WriteDataWord(200, 0x4321); // Aligned
|
||||
EEPROM_WriteDataWord(200, 0x4321); // Aligned
|
||||
/* Write Log word value unaligned */
|
||||
EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte
|
||||
EEPROM_WriteDataWord(203, 0xcdef); // Unaligned
|
||||
EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte
|
||||
EEPROM_WriteDataWord(203, 0xcdef); // Unaligned
|
||||
/* Check values */
|
||||
/* Direct compacted-area */
|
||||
EXPECT_EQ(*(uint16_t*)&FlashBuf[EEPROM_BASE], (uint16_t)~0xdead);
|
||||
@@ -252,11 +251,11 @@ TEST_F(EepromStm32Test, TestWriteWord) {
|
||||
|
||||
TEST_F(EepromStm32Test, TestWordRoundTrip) {
|
||||
/* Direct compacted-area: Address < 0x80 */
|
||||
EEPROM_WriteDataWord(0, 0xdead); // Aligned
|
||||
EEPROM_WriteDataWord(3, 0xbeef); // Unaligned
|
||||
EEPROM_WriteDataWord(0, 0xdead); // Aligned
|
||||
EEPROM_WriteDataWord(3, 0xbeef); // Unaligned
|
||||
/* Direct compacted-area: Address >= 0x80 */
|
||||
EEPROM_WriteDataWord(200, 0xabcd); // Aligned
|
||||
EEPROM_WriteDataWord(203, 0x9876); // Unaligned
|
||||
EEPROM_WriteDataWord(200, 0xabcd); // Aligned
|
||||
EEPROM_WriteDataWord(203, 0x9876); // Unaligned
|
||||
EEPROM_WriteDataWord(EEPROM_SIZE - 4, 0x1234);
|
||||
EEPROM_WriteDataWord(EEPROM_SIZE - 2, 0x5678);
|
||||
/* Check values */
|
||||
@@ -273,10 +272,10 @@ TEST_F(EepromStm32Test, TestWordRoundTrip) {
|
||||
/* Write Log word one-encoded */
|
||||
EEPROM_WriteDataWord(EEPROM_SIZE - 2, 1);
|
||||
/* Write Log word value aligned */
|
||||
EEPROM_WriteDataWord(200, 0x4321); // Aligned
|
||||
EEPROM_WriteDataWord(200, 0x4321); // Aligned
|
||||
/* Write Log word value unaligned */
|
||||
EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte
|
||||
EEPROM_WriteDataWord(203, 0xcdef); // Unaligned
|
||||
EEPROM_WriteDataByte(202, 0x3c); // Set neighboring byte
|
||||
EEPROM_WriteDataWord(203, 0xcdef); // Unaligned
|
||||
/* Check values */
|
||||
EEPROM_Init();
|
||||
EXPECT_EQ(EEPROM_ReadDataWord(200), 0x4321);
|
||||
@@ -327,34 +326,34 @@ TEST_F(EepromStm32Test, TestByteWordBoundary) {
|
||||
|
||||
TEST_F(EepromStm32Test, TestDWordRoundTrip) {
|
||||
/* Direct compacted-area: Address < 0x80 */
|
||||
eeprom_write_dword((uint32_t*)0, 0xdeadbeef); // Aligned
|
||||
eeprom_write_dword((uint32_t*)9, 0x12345678); // Unaligned
|
||||
eeprom_write_dword((uint32_t*)0, 0xdeadbeef); // Aligned
|
||||
eeprom_write_dword((uint32_t*)9, 0x12345678); // Unaligned
|
||||
/* Direct compacted-area: Address >= 0x80 */
|
||||
eeprom_write_dword((uint32_t*)200, 0xfacef00d);
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xba5eba11); // Aligned
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0xcafed00d); // Unaligned
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xba5eba11); // Aligned
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0xcafed00d); // Unaligned
|
||||
/* Check direct values */
|
||||
EEPROM_Init();
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdeadbeef);
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)9), 0x12345678);
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)200), 0xfacef00d);
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xba5eba11); // Aligned
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0xcafed00d); // Unaligned
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xba5eba11); // Aligned
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0xcafed00d); // Unaligned
|
||||
/* Write Log byte encoded */
|
||||
eeprom_write_dword((uint32_t*)0, 0xdecafbad);
|
||||
eeprom_write_dword((uint32_t*)9, 0x87654321);
|
||||
/* Write Log word encoded */
|
||||
eeprom_write_dword((uint32_t*)200, 1);
|
||||
/* Write Log word value aligned */
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xdeadc0de); // Aligned
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0x6789abcd); // Unaligned
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 4), 0xdeadc0de); // Aligned
|
||||
eeprom_write_dword((uint32_t*)(EEPROM_SIZE - 9), 0x6789abcd); // Unaligned
|
||||
/* Check log values */
|
||||
EEPROM_Init();
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)0), 0xdecafbad);
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)9), 0x87654321);
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)200), 1);
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xdeadc0de); // Aligned
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0x6789abcd); // Unaligned
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 4)), 0xdeadc0de); // Aligned
|
||||
EXPECT_EQ(eeprom_read_dword((uint32_t*)(EEPROM_SIZE - 9)), 0x6789abcd); // Unaligned
|
||||
}
|
||||
|
||||
TEST_F(EepromStm32Test, TestBlockRoundTrip) {
|
||||
|
||||
8
platforms/test/eeprom_stm32_tests.h
Normal file
8
platforms/test/eeprom_stm32_tests.h
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2018-2022 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include "flash_stm32.h"
|
||||
#include "eeprom_stm32.h"
|
||||
|
||||
#define EEPROM_SIZE (FEE_PAGE_SIZE * FEE_PAGE_COUNT / 2)
|
||||
@@ -44,6 +44,12 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
|
||||
}
|
||||
}
|
||||
|
||||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) { return FLASH_COMPLETE; }
|
||||
void FLASH_Unlock(void) { flash_locked = false; }
|
||||
void FLASH_Lock(void) { flash_locked = true; }
|
||||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) {
|
||||
return FLASH_COMPLETE;
|
||||
}
|
||||
void FLASH_Unlock(void) {
|
||||
flash_locked = false;
|
||||
}
|
||||
void FLASH_Lock(void) {
|
||||
flash_locked = true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user