WIP code
ADC is sort of functioning, but not reliably. LEDs are sort of working. Buzzer isn't working right and is nearly always on as I can't set the PF2 mode.
This commit is contained in:
parent
096131b87b
commit
ecc478661f
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"cpu": "cortex-m0plus",
|
"cpu": "cortex-m0plus",
|
||||||
"extra_flags": "-DPY32F003x6",
|
"extra_flags": "-DPY32F030x6",
|
||||||
"f_cpu": "8000000L",
|
"f_cpu": "8000000L",
|
||||||
"mcu": "py32f030x6",
|
"mcu": "py32f030x6",
|
||||||
"product_line": "PY32F030x6"
|
"product_line": "PY32F030x6"
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
"cmsis-dap"
|
"cmsis-dap"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"name": "Generic PY32F002/003/030 (configured as 32K PY32F030x6)",
|
"name": "Generic 16/32K PY32F002/003/030 (configured as 32K PY32F030x6)",
|
||||||
"url": "https://github.com/trueserve",
|
"url": "https://github.com/trueserve",
|
||||||
"vendor": "trueControl"
|
"vendor": "trueControl"
|
||||||
}
|
}
|
|
@ -5,6 +5,18 @@
|
||||||
* file creation: 20231016 0102
|
* file creation: 20231016 0102
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _INC_ADC_H
|
||||||
|
#define _INC_ADC_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void adc_init();
|
void adc_init();
|
||||||
void adc_next();
|
|
||||||
|
uint8_t adc_next();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _INC_ADC_H */
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* flash.h: flashing user config and system option bytes
|
||||||
|
*
|
||||||
|
* file creation: 20231019 0129
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INC_FLASH_H
|
||||||
|
#define _INC_FLASH_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void flash_optr_checkfix();
|
||||||
|
|
||||||
|
void flash_optr_set();
|
||||||
|
|
||||||
|
void flash_init();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _INC_FLASH_H */
|
|
@ -5,6 +5,9 @@
|
||||||
* file creation: 20231015 0059
|
* file creation: 20231015 0059
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _INC_LED_H
|
||||||
|
#define _INC_LED_H
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -18,3 +21,7 @@ void led_mode_buzzer();
|
||||||
|
|
||||||
void led_setrgb(uint8_t i, uint16_t r, uint16_t g, uint16_t b);
|
void led_setrgb(uint8_t i, uint16_t r, uint16_t g, uint16_t b);
|
||||||
void led_buzz(uint8_t buzz);
|
void led_buzz(uint8_t buzz);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _INC_LED_H */
|
|
@ -4,6 +4,9 @@
|
||||||
* file creation: 20231015 0021
|
* file creation: 20231015 0021
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _INC_TESTO_H
|
||||||
|
#define _INC_TESTO_H
|
||||||
|
|
||||||
|
|
||||||
#include "py32f0xx_conf.h"
|
#include "py32f0xx_conf.h"
|
||||||
|
|
||||||
|
@ -78,3 +81,6 @@
|
||||||
#define ADC_VREF_EXT 0
|
#define ADC_VREF_EXT 0
|
||||||
#define ADC_THERM 4
|
#define ADC_THERM 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _INC_TESTO_H */
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* userio.h: reacting when you fiddle with buttons, switches, and knobs
|
||||||
|
*
|
||||||
|
* file creation: 20231016 1505
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void userio_parse();
|
|
@ -871,7 +871,7 @@ ErrorStatus LL_FLASH_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
|
||||||
FLASH->CR|=FLASH_CR_OPTSTRT;
|
FLASH->CR|=FLASH_CR_OPTSTRT;
|
||||||
|
|
||||||
/* set bit EOPIE */
|
/* set bit EOPIE */
|
||||||
FLASH->CR|=FLASH_CR_EOPIE;
|
// FLASH->CR|=FLASH_CR_EOPIE;
|
||||||
|
|
||||||
/* trigger program */
|
/* trigger program */
|
||||||
*((__IO uint32_t *)(0x40022080))=0xff;
|
*((__IO uint32_t *)(0x40022080))=0xff;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
platform = nxplpc ; not actually this and we are not using a framework
|
platform = nxplpc ; not actually this and we are not using a framework
|
||||||
build_type = debug ; setting platform = nxplpc makes everything happy
|
; setting platform = nxplpc makes everything happy
|
||||||
; as we'll get nano specs and any other needed shit
|
; as we'll get nano specs and any other needed shit
|
||||||
board = generic_py32f030x6
|
board = generic_py32f030x6
|
||||||
|
|
||||||
|
@ -28,13 +28,17 @@ debug_extra_cmds =
|
||||||
upload_protocol = custom
|
upload_protocol = custom
|
||||||
upload_command = $PYTHONEXE ${platformio.packages_dir}/tool-pyocd/pyocd-flashtool.py --config $PROJECT_DIR/pyocd.yaml -t PY32F030x6 $SOURCE
|
upload_command = $PYTHONEXE ${platformio.packages_dir}/tool-pyocd/pyocd-flashtool.py --config $PROJECT_DIR/pyocd.yaml -t PY32F030x6 $SOURCE
|
||||||
|
|
||||||
build_flags =
|
platform_packages =
|
||||||
-DUSE_FULL_LL_DRIVER
|
toolchain-gccarmnoneeabi@1.100301.220327 ; build issues with GCC12, use GCC10 for now
|
||||||
-L.
|
tool-pyocd ; user won't have to install it
|
||||||
-Os
|
|
||||||
-std=gnu11
|
|
||||||
|
[env:sc7-testobot-py32f-dbg_pyocd]
|
||||||
|
build_type = debug
|
||||||
|
board_build.ldscript = py32f030x6.ld
|
||||||
|
|
||||||
debug_build_flags =
|
debug_build_flags =
|
||||||
|
-Wl,-Map=.pio/output_dbg.map
|
||||||
-DUSE_FULL_LL_DRIVER
|
-DUSE_FULL_LL_DRIVER
|
||||||
-L.
|
-L.
|
||||||
-Os
|
-Os
|
||||||
|
@ -42,26 +46,15 @@ debug_build_flags =
|
||||||
-Wl,-Map=.pio/output_dbg.map
|
-Wl,-Map=.pio/output_dbg.map
|
||||||
-g
|
-g
|
||||||
|
|
||||||
platform_packages =
|
|
||||||
toolchain-gccarmnoneeabi@1.100301.220327 ; build issues with GCC12, use GCC10 for now
|
|
||||||
tool-pyocd ; user won't have to install it
|
|
||||||
|
|
||||||
|
|
||||||
[env:sc7-testobot-py32f-dbg_pyocd]
|
|
||||||
board_build.ldscript = py32f030x6.ld
|
|
||||||
|
|
||||||
debug_build_flags =
|
|
||||||
-Wl,-Map=.pio/output_dbg.map
|
|
||||||
|
|
||||||
|
|
||||||
[env:sc7-testobot-py32f-rel_bl]
|
[env:sc7-testobot-py32f-rel_bl]
|
||||||
|
build_type = release
|
||||||
board_build.ldscript = py32f030x6_bl.ld
|
board_build.ldscript = py32f030x6_bl.ld
|
||||||
|
board_upload.maximum_size = 30720 ; 2K reserved for bootloader
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
-Wl,-Map=.pio/output_rel.map
|
-Wl,-Map=.pio/output_rel.map
|
||||||
|
-DUSE_FULL_LL_DRIVER
|
||||||
|
-L.
|
||||||
|
-Os
|
||||||
|
-std=gnu11
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ MEMORY
|
||||||
{
|
{
|
||||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||||
|
PERIPHERAL (rw): ORIGIN = 0x40000000, LENGTH = 512M
|
||||||
|
PPB (rw) : ORIGIN = 0xe0000000, LENGTH = 512M
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define output sections */
|
/* Define output sections */
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
def will_connect(board):
|
def will_connect(board):
|
||||||
print("notice: adding peripheral memory map...");
|
print("notice: adding peripheral memory map...");
|
||||||
|
|
||||||
target.memory_map.add_region(DeviceRegion(
|
# target.memory_map.add_region(DeviceRegion(
|
||||||
name="Peripheral",
|
# name="Peripheral",
|
||||||
start=0x40000000,
|
# start=0x40000000,
|
||||||
length=0x20000000,
|
# length=0x20000000,
|
||||||
access='rw'
|
# access='rw'
|
||||||
))
|
# ))
|
||||||
|
|
||||||
target.memory_map.add_region(DeviceRegion(
|
target.memory_map.add_region(DeviceRegion(
|
||||||
name="PPB",
|
name="PPB",
|
||||||
start=0xE0000000,
|
start=0xE0000000,
|
||||||
|
|
115
src/adc.c
115
src/adc.c
|
@ -9,9 +9,9 @@
|
||||||
* voltage - only the analog supply can be the reference.
|
* voltage - only the analog supply can be the reference.
|
||||||
*
|
*
|
||||||
* because most inputs are high impedance, which is not ideal,
|
* because most inputs are high impedance, which is not ideal,
|
||||||
* sampling time is increased to the maximum. this results in
|
* sampling time is increased. this results in a final ADC sample rate
|
||||||
* a final ADC sample rate of ~33KHz, still well beyond
|
* of about 33KHz, still well beyond what is needed in this application.
|
||||||
* what is needed in this application.
|
* this value may change in the future.
|
||||||
*
|
*
|
||||||
* file creation: 20231015 0121
|
* file creation: 20231015 0121
|
||||||
*/
|
*/
|
||||||
|
@ -28,13 +28,16 @@
|
||||||
#define ADC_CHANNELS 6
|
#define ADC_CHANNELS 6
|
||||||
#define ADC_HISTLEN 16
|
#define ADC_HISTLEN 16
|
||||||
|
|
||||||
|
#define CONF_CALIBRATE (1 << 0)
|
||||||
|
#define CONF_USEPROBE (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static uint16_t adc_read[ADC_CHANNELS];
|
static uint16_t adc_read[ADC_CHANNELS];
|
||||||
static uint16_t adc_hist[ADC_CHANNELS][ADC_HISTLEN];
|
static uint16_t adc_hist[ADC_CHANNELS][ADC_HISTLEN];
|
||||||
static uint16_t adc_avg[ADC_CHANNELS];
|
static uint16_t adc_avg[ADC_CHANNELS];
|
||||||
|
|
||||||
static uint8_t adc_idx = ADC_HISTLEN;
|
static uint8_t adc_idx = ADC_HISTLEN + 1;
|
||||||
|
|
||||||
static int16_t vref;
|
static int16_t vref;
|
||||||
static uint8_t calibrate = 0;
|
static uint8_t calibrate = 0;
|
||||||
|
@ -52,39 +55,97 @@ void adc_init()
|
||||||
// enable VREFINT and temperature sensor
|
// enable VREFINT and temperature sensor
|
||||||
ADC->CCR = ADC_CCR_TSEN | ADC_CCR_VREFEN;
|
ADC->CCR = ADC_CCR_TSEN | ADC_CCR_VREFEN;
|
||||||
|
|
||||||
// configure scan channels, sampling time
|
// configure scan channels, sampling time (11 = temp, 12 = vrefint)
|
||||||
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN |
|
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and PROBE are
|
||||||
CONF_MODE_AN | CONF_SET0_AN |
|
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
|
||||||
ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL12;
|
ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL12;
|
||||||
ADC1->SMPR = SAMPLE_TIME;
|
ADC1->SMPR = SAMPLE_TIME;
|
||||||
|
|
||||||
// by default, DMA selection for all channels is ADC
|
// run in non-circular DMA mode, with wait mode enabled
|
||||||
|
ADC1->CFGR1 = ADC_CFGR1_OVRMOD | ADC_CFGR1_WAIT | LL_ADC_REG_DMA_TRANSFER_LIMITED;
|
||||||
|
|
||||||
|
// by default, DMA selection for all channels is ADC
|
||||||
// so all we need to do is set the peripheral address
|
// so all we need to do is set the peripheral address
|
||||||
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
|
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
|
||||||
|
DMA1_Channel1->CMAR = (uint32_t)adc_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adc_next()
|
/*
|
||||||
|
* internal function for stopping ADC conversion in progress.
|
||||||
|
*/
|
||||||
|
void adc_stop()
|
||||||
|
{
|
||||||
|
if (ADC1->CR & ADC_CR_ADSTART) {
|
||||||
|
ADC1->CR |= ADC_CR_ADSTP;
|
||||||
|
while (ADC1->CR & ADC_CR_ADSTP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* internal function for setting up the ADC for a read.
|
||||||
|
*/
|
||||||
|
void adc_go()
|
||||||
|
{
|
||||||
|
// stop if conversion in progress (it shouldn't ever be)
|
||||||
|
adc_stop();
|
||||||
|
|
||||||
|
// configure and enable DMA
|
||||||
|
DMA1_Channel1->CCR = 0;
|
||||||
|
DMA1_Channel1->CNDTR = ADC_CHANNELS;
|
||||||
|
DMA1_Channel1->CCR = LL_DMA_PRIORITY_HIGH |
|
||||||
|
LL_DMA_MDATAALIGN_HALFWORD |
|
||||||
|
LL_DMA_PDATAALIGN_HALFWORD |
|
||||||
|
LL_DMA_MEMORY_INCREMENT |
|
||||||
|
LL_DMA_MODE_NORMAL |
|
||||||
|
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
|
||||||
|
DMA_CCR_EN;
|
||||||
|
|
||||||
|
// enable and start ADC
|
||||||
|
ADC1->ISR = 0x1e; // clear all interrupt flags (per DS; mistranslated)
|
||||||
|
ADC1->CR = ADC_CR_ADEN;
|
||||||
|
ADC1->CR |= ADC_CR_ADSTART;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* when switching AN0 to/from SET1 and VREFEXT, we need to clear
|
||||||
|
* old history stored for the first analog input as well as reset the
|
||||||
|
* history index to start over. finally we need to trigger the ADC
|
||||||
|
* to get fresh data.
|
||||||
|
*/
|
||||||
|
void adc_switch0()
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
adc_read[0] = 0;
|
||||||
|
adc_avg[0] = 0;
|
||||||
|
for (i = 0; i < ADC_HISTLEN; i++) {
|
||||||
|
adc_hist[0][i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_idx = 0;
|
||||||
|
|
||||||
|
// force ADC read to get fresh data
|
||||||
|
adc_go();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t adc_next()
|
||||||
{
|
{
|
||||||
uint8_t i, j;
|
uint8_t i, j;
|
||||||
int16_t w;
|
int16_t w;
|
||||||
|
|
||||||
// start ADC calibration
|
// stop if conversion in progress (it shouldn't ever be)
|
||||||
|
adc_stop();
|
||||||
|
|
||||||
|
// start ADC calibration
|
||||||
if (calibrate) {
|
if (calibrate) {
|
||||||
calibrate = 0;
|
calibrate = 0;
|
||||||
|
|
||||||
// stop if conversion in progress (it shouldn't ever be)
|
|
||||||
if (ADC1->CR & ADC_CR_ADSTART) {
|
|
||||||
ADC1->CR |= ADC_CR_ADSTP;
|
|
||||||
while (ADC1->CR & ADC_CR_ADSTP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable ADC and start calibration
|
// disable ADC and start calibration
|
||||||
ADC1->CR &= ~(ADC_CR_ADEN);
|
ADC1->CR &= ~(ADC_CR_ADEN);
|
||||||
ADC1->CR |= ADC_CR_ADCAL;
|
ADC1->CR |= ADC_CR_ADCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy data to history from last read
|
// copy data to history from last read
|
||||||
adc_idx++;
|
|
||||||
if (adc_idx > ADC_HISTLEN) {
|
if (adc_idx > ADC_HISTLEN) {
|
||||||
// nothing to copy when first starting
|
// nothing to copy when first starting
|
||||||
adc_idx = 0;
|
adc_idx = 0;
|
||||||
|
@ -122,21 +183,9 @@ void adc_next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for calibration to complete, if started
|
// wait for calibration to complete, if started
|
||||||
while (ADC1->CR & ADC_CR_ADCAL);
|
while (ADC1->CR & ADC_CR_ADCAL) {};
|
||||||
|
|
||||||
// configure and enable DMA
|
adc_go();
|
||||||
DMA1_Channel1->CNDTR = ADC_CHANNELS;
|
|
||||||
DMA1_Channel1->CMAR = (uint32_t)adc_read;
|
|
||||||
DMA1_Channel1->CCR = LL_DMA_PRIORITY_MEDIUM |
|
|
||||||
LL_DMA_MDATAALIGN_HALFWORD |
|
|
||||||
LL_DMA_PDATAALIGN_HALFWORD |
|
|
||||||
LL_DMA_MEMORY_INCREMENT |
|
|
||||||
LL_DMA_MODE_CIRCULAR |
|
|
||||||
LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
|
|
||||||
DMA_CCR_EN;
|
|
||||||
|
|
||||||
// enable and start ADC
|
return adc_idx;
|
||||||
ADC1->ISR = 0x8e; // clear all interrupt flags (per DS; mistranslated)
|
|
||||||
ADC1->CR = ADC_CR_ADEN;
|
|
||||||
ADC1->CR |= ADC_CR_ADSTART;
|
|
||||||
}
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* flash.c: flashing user config and system option bytes
|
||||||
|
*
|
||||||
|
* by default, the pin used for PF2 is configured as a reset.
|
||||||
|
* this code will check that the no-reset bit is set.
|
||||||
|
* if it is not, this code will update the option bytes to
|
||||||
|
* set the BOR voltage, enable BOR, and enable the no-reset bit.
|
||||||
|
*
|
||||||
|
* file creation: 20231019 0126
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "py32f0xx_conf.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checks the flash option byte to determine if the reset pin
|
||||||
|
* is configured to be PF2. if not, sets this bit as well as
|
||||||
|
* the BOR values. if the bits were updated, they will be reloaded.
|
||||||
|
*
|
||||||
|
* only call this function during startup, before interrupts
|
||||||
|
* are enabled.
|
||||||
|
*
|
||||||
|
* note: this code caused me to lose MCU. consider it buggy.
|
||||||
|
*/
|
||||||
|
void flash_optr_checkfix()
|
||||||
|
{
|
||||||
|
FLASH_OBProgramInitTypeDef opt;
|
||||||
|
|
||||||
|
if ((FLASH->OPTR & FLASH_OPTR_NRST_MODE) == OB_RESET_MODE_RESET) {
|
||||||
|
// let's update this
|
||||||
|
opt.OptionType = OPTIONBYTE_RDP | OPTIONBYTE_USER;
|
||||||
|
opt.USERType = 0xff00;
|
||||||
|
opt.USERConfig = OB_BOR_ENABLE | OB_BOR_LEVEL_2p3_2p4 | OB_IWDG_SW | OB_WWDG_SW | OB_RESET_MODE_GPIO | OB_BOOT1_SYSTEM | OB_RDP_LEVEL_0;
|
||||||
|
|
||||||
|
if (LL_FLASH_Unlock() != SUCCESS) return;
|
||||||
|
if (LL_FLASH_OB_Unlock() != SUCCESS) return;
|
||||||
|
|
||||||
|
LL_FLASH_OBProgram(&opt);
|
||||||
|
|
||||||
|
LL_FLASH_OB_Lock();
|
||||||
|
LL_FLASH_Lock();
|
||||||
|
|
||||||
|
// reload newly programmed option bytes
|
||||||
|
LL_FLASH_OB_Launch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* manually load values into flash option byte, to configure
|
||||||
|
* the BOR and configure the reset pin to be PF2.
|
||||||
|
*/
|
||||||
|
void flash_optr_set()
|
||||||
|
{
|
||||||
|
FLASH->OPTR &= (FLASH_OPTR_BOR_EN_Msk | FLASH_OPTR_BOR_LEV_Msk | FLASH_OPTR_NRST_MODE_Msk);
|
||||||
|
FLASH->OPTR |= OB_BOR_ENABLE | OB_BOR_LEVEL_2p3_2p4 | OB_RESET_MODE_GPIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_init()
|
||||||
|
{
|
||||||
|
// load flash write timings for 8MHz operation
|
||||||
|
// (these are listed in the datasheet)
|
||||||
|
FLASH->TS0 = 0x3c;
|
||||||
|
FLASH->TS2P = 0x3c;
|
||||||
|
FLASH->TS3 = 0x3c;
|
||||||
|
|
||||||
|
FLASH->TS1 = 0x90;
|
||||||
|
FLASH->TPS3 = 0x240;
|
||||||
|
|
||||||
|
FLASH->PERTPE = 0x5dc0;
|
||||||
|
FLASH->SMERTPE = 0x5dc0;
|
||||||
|
FLASH->PRGTPE = 0x1f40;
|
||||||
|
FLASH->PRETPE = 0x640;
|
||||||
|
}
|
15
src/led.c
15
src/led.c
|
@ -39,14 +39,14 @@ void led_next()
|
||||||
led_sel &= 1;
|
led_sel &= 1;
|
||||||
|
|
||||||
// clear outputs
|
// clear outputs
|
||||||
RGBSEL0_PORT->BRR = (1 << RGBSEL0_PIN);
|
RGBSEL0_PORT->BSRR = (1 << RGBSEL0_PIN);
|
||||||
RGBSEL1_PORT->BRR = (1 << RGBSEL1_PIN);
|
RGBSEL1_PORT->BSRR = (1 << RGBSEL1_PIN);
|
||||||
|
|
||||||
if (!led_sel || (led_mode == MODE_RGB)) {
|
if (!led_sel || (led_mode == MODE_RGB)) {
|
||||||
// set PWMs in RGB mode, or when right LED set
|
// set PWMs in RGB mode, or when right LED set
|
||||||
PWM_RGB_R = rgb[led_sel][RED];
|
PWM_RGB_R = rgb[led_sel][RED];
|
||||||
PWM_RGB_R = rgb[led_sel][GRN];
|
PWM_RGB_G = rgb[led_sel][GRN];
|
||||||
PWM_RGB_R = rgb[led_sel][BLU];
|
PWM_RGB_B = rgb[led_sel][BLU];
|
||||||
} else {
|
} else {
|
||||||
// clear PWMs in piezo mode when piezo should be active
|
// clear PWMs in piezo mode when piezo should be active
|
||||||
PWM_RGB_R = PWM_RGB_G = PWM_RGB_B = 0;
|
PWM_RGB_R = PWM_RGB_G = PWM_RGB_B = 0;
|
||||||
|
@ -58,9 +58,9 @@ void led_next()
|
||||||
// enable selected LED
|
// enable selected LED
|
||||||
if (led_sel) {
|
if (led_sel) {
|
||||||
if ((led_mode == MODE_BUZZ) && !snd_buzz) return;
|
if ((led_mode == MODE_BUZZ) && !snd_buzz) return;
|
||||||
RGBSEL1_PORT->BSRR = (1 << RGBSEL1_PIN);
|
RGBSEL1_PORT->BRR = (1 << RGBSEL1_PIN);
|
||||||
} else {
|
} else {
|
||||||
RGBSEL0_PORT->BSRR = (1 << RGBSEL0_PIN);
|
RGBSEL0_PORT->BRR = (1 << RGBSEL0_PIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +146,9 @@ void led_init()
|
||||||
led_sel = 1;
|
led_sel = 1;
|
||||||
snd_buzz = 0;
|
snd_buzz = 0;
|
||||||
|
|
||||||
|
rgb[0][0] = 100;
|
||||||
|
rgb[1][1] = 100;
|
||||||
|
|
||||||
// start outputting data
|
// start outputting data
|
||||||
led_next();
|
led_next();
|
||||||
}
|
}
|
48
src/main.c
48
src/main.c
|
@ -10,7 +10,9 @@
|
||||||
#include "testo.h"
|
#include "testo.h"
|
||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
|
#include "userio.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,8 +32,8 @@ static inline void gpio_init()
|
||||||
// enable pullups on I2C outputs
|
// enable pullups on I2C outputs
|
||||||
GPIOA->PUPDR = 0x24000050;
|
GPIOA->PUPDR = 0x24000050;
|
||||||
// datasheet doesn't say what the speeds are for GPIO...
|
// datasheet doesn't say what the speeds are for GPIO...
|
||||||
// so set SWDIO to very high speed, all other outputs as high speed
|
// so set SWDIO to very high speed, PA12 low speed, all other outputs as high speed
|
||||||
GPIOA->OSPEEDR = 0x2E002AA0;
|
GPIOA->OSPEEDR = 0x2C002AA0;
|
||||||
// alternate function select
|
// alternate function select
|
||||||
// PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA
|
// PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA
|
||||||
GPIOA->AFR[0] = 0x01DDCC00;
|
GPIOA->AFR[0] = 0x01DDCC00;
|
||||||
|
@ -44,26 +46,27 @@ static inline void gpio_init()
|
||||||
|
|
||||||
|
|
||||||
// PB1=OUT, PB0=AN
|
// PB1=OUT, PB0=AN
|
||||||
// unused pins are analog
|
// unused pins are analog, all outputs are low speed
|
||||||
GPIOB->OSPEEDR = 0x00000008;
|
GPIOB->OSPEEDR = 0x00000000;
|
||||||
GPIOB->MODER = 0xfffffff7;
|
GPIOB->MODER = 0xfffffff7;
|
||||||
|
|
||||||
// PF2=OUT, low speed
|
// PF2=OUT(low), low speed
|
||||||
// unused pins are analog
|
// unused pins are analog
|
||||||
|
GPIOF->ODR = (1 << 2);
|
||||||
GPIOF->MODER = 0xFFFFFCDF;
|
GPIOF->MODER = 0xFFFFFCDF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void clk_init()
|
static inline void clk_init()
|
||||||
{
|
{
|
||||||
|
// run all buses at core clock speed
|
||||||
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
|
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
|
||||||
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
|
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
|
||||||
|
|
||||||
// enable GPIO clocks
|
// enable GPIO and peripheral clocks
|
||||||
RCC->IOPENR = LL_IOP_GRP1_PERIPH_GPIOA |
|
RCC->IOPENR = LL_IOP_GRP1_PERIPH_GPIOA |
|
||||||
LL_IOP_GRP1_PERIPH_GPIOB |
|
LL_IOP_GRP1_PERIPH_GPIOB |
|
||||||
LL_IOP_GRP1_PERIPH_GPIOF;
|
LL_IOP_GRP1_PERIPH_GPIOF;
|
||||||
|
|
||||||
// enable peripheral clocks
|
|
||||||
RCC->AHBENR = LL_AHB1_GRP1_PERIPH_DMA1;
|
RCC->AHBENR = LL_AHB1_GRP1_PERIPH_DMA1;
|
||||||
RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3;
|
RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3;
|
||||||
RCC->APBENR2 = LL_APB1_GRP2_PERIPH_ADC1 | LL_APB1_GRP2_PERIPH_SYSCFG;
|
RCC->APBENR2 = LL_APB1_GRP2_PERIPH_ADC1 | LL_APB1_GRP2_PERIPH_SYSCFG;
|
||||||
|
@ -78,6 +81,12 @@ static inline void systick_init()
|
||||||
// configure timebase with interrupt at 4096Hz
|
// configure timebase with interrupt at 4096Hz
|
||||||
// this assumes we'll always be running at 8MHz
|
// this assumes we'll always be running at 8MHz
|
||||||
SysTick_Config((8000000 / 4096) - 1);
|
SysTick_Config((8000000 / 4096) - 1);
|
||||||
|
|
||||||
|
// configure unused DMA channels to not be on ADC
|
||||||
|
// (otherwise ADC can shows reads of 0... it's a hardware bug)
|
||||||
|
SYSCFG->CFGR3 = LL_SYSCFG_DMA_MAP_ADC | // ch0
|
||||||
|
LL_SYSCFG_DMA_MAP_TIM17_UP << 8 | // ch1
|
||||||
|
LL_SYSCFG_DMA_MAP_TIM17_UP << 16; // ch2
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -88,6 +97,7 @@ int main()
|
||||||
{
|
{
|
||||||
// base hardware initialization
|
// base hardware initialization
|
||||||
clk_init();
|
clk_init();
|
||||||
|
flash_init(); // also configures option bytes, if necessary
|
||||||
gpio_init();
|
gpio_init();
|
||||||
|
|
||||||
// peripheral initialization
|
// peripheral initialization
|
||||||
|
@ -116,20 +126,36 @@ int main()
|
||||||
*/
|
*/
|
||||||
void SysTick_Handler(void)
|
void SysTick_Handler(void)
|
||||||
{
|
{
|
||||||
|
uint16_t cs;
|
||||||
|
|
||||||
ctr++;
|
ctr++;
|
||||||
|
|
||||||
// run LED programs quickly
|
// run LED programs quickly
|
||||||
led_next();
|
led_next();
|
||||||
|
|
||||||
// limit counter to 4096
|
// limit counter to 4096 counts
|
||||||
ctr &= 0xfff;
|
ctr &= 0xfff;
|
||||||
if (!ctr) {
|
if (!ctr) {
|
||||||
uptime++;
|
uptime++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// run main logic at 1024Hz
|
// run main logic at 1024Hz
|
||||||
if ((ctr & 0x3) == 0) {
|
if (!(ctr & 0x3)) {
|
||||||
// adc
|
// shifted counter for use in the program
|
||||||
adc_next();
|
cs = ctr >> 2;
|
||||||
|
|
||||||
|
// adc (512Hz/16 avg = 32Hz update rate)
|
||||||
|
if (cs & 1) {
|
||||||
|
if (!adc_next()) {
|
||||||
|
// adc has new computed results,
|
||||||
|
// so we can do userio, probe, etc
|
||||||
|
|
||||||
|
// but the results are only valid
|
||||||
|
// after our first cycle
|
||||||
|
if (uptime || cs) {
|
||||||
|
userio_parse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
26
src/userio.c
26
src/userio.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* adc.c: reacting when you fiddle with buttons, switches, and knobs
|
* userio.c: reacting when you fiddle with buttons, switches, and knobs
|
||||||
*
|
*
|
||||||
* mode switch: modes are changed only when the button is not being
|
* mode switch: modes are changed only when the button is not being
|
||||||
* pushed, as button being pushed negates the mode switch response.
|
* pushed, as button being pushed negates the mode switch response.
|
||||||
|
@ -29,23 +29,26 @@
|
||||||
|
|
||||||
|
|
||||||
#define MODE_CONT 0
|
#define MODE_CONT 0
|
||||||
#define MODE_CONT_TARGET 0x46d
|
#define MODE_CONT_TARGET (4096 * (1 - (1 / 4)))
|
||||||
|
|
||||||
#define MODE_FUN 1
|
#define MODE_FUN 1
|
||||||
#define MODE_FUN_TARGET 0xa2b
|
#define MODE_FUN_TARGET (4096 * (1 - (1 / 3)))
|
||||||
|
|
||||||
#define MODE_DIODE 2
|
#define MODE_DIODE 2
|
||||||
#define MODE_DIODE_TARGET 0xf80
|
#define MODE_DIODE_TARGET (4096 * (1 - (1 / 2)))
|
||||||
|
|
||||||
#define MODE_HYSTERESIS 20
|
#define MODE_HYSTERESIS 60 // 3x worst case expected (1% tol)
|
||||||
|
|
||||||
#define MODE_ANALOG_MIN 0x80
|
#define MODE_ANALOG_MIN 20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t modesw;
|
uint8_t mode;
|
||||||
uint8_t modesw_next;
|
uint8_t mode_next;
|
||||||
uint8_t modesw_count;
|
uint8_t mode_count;
|
||||||
|
static const uint16_t mode_targets[] = {
|
||||||
|
MODE_CONT_TARGET, MODE_FUN_TARGET, MODE_DIODE_TARGET
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t knob[2];
|
uint8_t knob[2];
|
||||||
|
|
||||||
|
@ -54,6 +57,11 @@ uint16_t btn_held = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void userio_update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void userio_parse()
|
void userio_parse()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue