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": {
 | 
			
		||||
    "cpu": "cortex-m0plus",
 | 
			
		||||
    "extra_flags": "-DPY32F003x6",
 | 
			
		||||
    "extra_flags": "-DPY32F030x6",
 | 
			
		||||
    "f_cpu": "8000000L",
 | 
			
		||||
    "mcu": "py32f030x6",
 | 
			
		||||
    "product_line": "PY32F030x6"
 | 
			
		||||
@ -21,7 +21,7 @@
 | 
			
		||||
      "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",
 | 
			
		||||
  "vendor": "trueControl"
 | 
			
		||||
}
 | 
			
		||||
@ -5,6 +5,18 @@
 | 
			
		||||
 * file creation: 20231016 0102
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _INC_ADC_H
 | 
			
		||||
#define _INC_ADC_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void adc_init();
 | 
			
		||||
void adc_next();
 | 
			
		||||
 | 
			
		||||
uint8_t adc_next();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* _INC_ADC_H */
 | 
			
		||||
							
								
								
									
										20
									
								
								include/flash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/flash.h
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _INC_LED_H
 | 
			
		||||
#define _INC_LED_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_buzz(uint8_t buzz);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* _INC_LED_H */
 | 
			
		||||
@ -4,6 +4,9 @@
 | 
			
		||||
 * file creation: 20231015 0021
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _INC_TESTO_H
 | 
			
		||||
#define _INC_TESTO_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "py32f0xx_conf.h"
 | 
			
		||||
 | 
			
		||||
@ -78,3 +81,6 @@
 | 
			
		||||
#define ADC_VREF_EXT		0
 | 
			
		||||
#define ADC_THERM			4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* _INC_TESTO_H */
 | 
			
		||||
							
								
								
									
										12
									
								
								include/userio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								include/userio.h
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
 | 
			
		||||
  /* set bit EOPIE */
 | 
			
		||||
  FLASH->CR|=FLASH_CR_EOPIE;
 | 
			
		||||
  // FLASH->CR|=FLASH_CR_EOPIE;
 | 
			
		||||
 | 
			
		||||
  /* trigger program */
 | 
			
		||||
  *((__IO uint32_t *)(0x40022080))=0xff;
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@
 | 
			
		||||
 | 
			
		||||
[env]
 | 
			
		||||
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
 | 
			
		||||
board = generic_py32f030x6
 | 
			
		||||
 | 
			
		||||
@ -28,13 +28,17 @@ debug_extra_cmds =
 | 
			
		||||
upload_protocol = custom
 | 
			
		||||
upload_command = $PYTHONEXE ${platformio.packages_dir}/tool-pyocd/pyocd-flashtool.py --config $PROJECT_DIR/pyocd.yaml -t PY32F030x6 $SOURCE
 | 
			
		||||
 | 
			
		||||
build_flags = 
 | 
			
		||||
    -DUSE_FULL_LL_DRIVER
 | 
			
		||||
    -L.
 | 
			
		||||
    -Os
 | 
			
		||||
    -std=gnu11
 | 
			
		||||
platform_packages =
 | 
			
		||||
    toolchain-gccarmnoneeabi@1.100301.220327    ; build issues with GCC12, use GCC10 for now
 | 
			
		||||
    tool-pyocd                                  ; user won't have to install it
 | 
			
		||||
 | 
			
		||||
debug_build_flags = 
 | 
			
		||||
 | 
			
		||||
[env:sc7-testobot-py32f-dbg_pyocd]
 | 
			
		||||
build_type = debug
 | 
			
		||||
board_build.ldscript = py32f030x6.ld
 | 
			
		||||
 | 
			
		||||
debug_build_flags =
 | 
			
		||||
    -Wl,-Map=.pio/output_dbg.map
 | 
			
		||||
    -DUSE_FULL_LL_DRIVER
 | 
			
		||||
    -L.
 | 
			
		||||
    -Os
 | 
			
		||||
@ -42,26 +46,15 @@ debug_build_flags =
 | 
			
		||||
    -Wl,-Map=.pio/output_dbg.map
 | 
			
		||||
    -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]
 | 
			
		||||
build_type = release
 | 
			
		||||
board_build.ldscript = py32f030x6_bl.ld
 | 
			
		||||
board_upload.maximum_size = 30720				; 2K reserved for bootloader
 | 
			
		||||
 | 
			
		||||
build_flags =
 | 
			
		||||
    -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
 | 
			
		||||
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 32K
 | 
			
		||||
  PERIPHERAL (rw): ORIGIN = 0x40000000, LENGTH = 512M
 | 
			
		||||
  PPB (rw)       : ORIGIN = 0xe0000000, LENGTH = 512M
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Define output sections */
 | 
			
		||||
 | 
			
		||||
@ -3,12 +3,13 @@
 | 
			
		||||
def will_connect(board):
 | 
			
		||||
    print("notice: adding peripheral memory map...");
 | 
			
		||||
 | 
			
		||||
    target.memory_map.add_region(DeviceRegion(
 | 
			
		||||
        name="Peripheral",
 | 
			
		||||
        start=0x40000000,
 | 
			
		||||
        length=0x20000000,
 | 
			
		||||
        access='rw'
 | 
			
		||||
    ))
 | 
			
		||||
#    target.memory_map.add_region(DeviceRegion(
 | 
			
		||||
#        name="Peripheral",
 | 
			
		||||
#        start=0x40000000,
 | 
			
		||||
#        length=0x20000000,
 | 
			
		||||
#        access='rw'
 | 
			
		||||
#    ))
 | 
			
		||||
 | 
			
		||||
    target.memory_map.add_region(DeviceRegion(
 | 
			
		||||
        name="PPB",
 | 
			
		||||
        start=0xE0000000,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										117
									
								
								src/adc.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								src/adc.c
									
									
									
									
									
								
							@ -9,9 +9,9 @@
 | 
			
		||||
 * voltage - only the analog supply can be the reference.
 | 
			
		||||
 * 
 | 
			
		||||
 * because most inputs are high impedance, which is not ideal,
 | 
			
		||||
 * sampling time is increased to the maximum. this results in
 | 
			
		||||
 * a final ADC sample rate of ~33KHz, still well beyond
 | 
			
		||||
 * what is needed in this application.
 | 
			
		||||
 * sampling time is increased. this results in a final ADC sample rate
 | 
			
		||||
 * of about 33KHz, still well beyond what is needed in this application.
 | 
			
		||||
 * this value may change in the future.
 | 
			
		||||
 *
 | 
			
		||||
 * file creation: 20231015 0121
 | 
			
		||||
 */
 | 
			
		||||
@ -28,13 +28,16 @@
 | 
			
		||||
#define ADC_CHANNELS	6
 | 
			
		||||
#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_hist[ADC_CHANNELS][ADC_HISTLEN];
 | 
			
		||||
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 uint8_t calibrate = 0;
 | 
			
		||||
@ -52,39 +55,97 @@ void adc_init()
 | 
			
		||||
    // enable VREFINT and temperature sensor
 | 
			
		||||
    ADC->CCR = ADC_CCR_TSEN | ADC_CCR_VREFEN;
 | 
			
		||||
 | 
			
		||||
    // configure scan channels, sampling time
 | 
			
		||||
    ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | 
 | 
			
		||||
                    CONF_MODE_AN | CONF_SET0_AN |
 | 
			
		||||
    // configure scan channels, sampling time (11 = temp, 12 = vrefint)
 | 
			
		||||
    ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | 		// note: SET1 and PROBE are
 | 
			
		||||
                    CONF_MODE_AN | CONF_SET0_AN |	// shared and reflect one chan
 | 
			
		||||
                    ADC_CHSELR_CHSEL11 | ADC_CHSELR_CHSEL12;
 | 
			
		||||
    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
 | 
			
		||||
    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;
 | 
			
		||||
	int16_t w;
 | 
			
		||||
 | 
			
		||||
    // start ADC calibration
 | 
			
		||||
    // stop if conversion in progress (it shouldn't ever be)
 | 
			
		||||
	adc_stop();
 | 
			
		||||
		
 | 
			
		||||
	// start ADC calibration
 | 
			
		||||
    if (calibrate) {
 | 
			
		||||
		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
 | 
			
		||||
        ADC1->CR &= ~(ADC_CR_ADEN);
 | 
			
		||||
        ADC1->CR |=   ADC_CR_ADCAL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	// copy data to history from last read
 | 
			
		||||
	adc_idx++;
 | 
			
		||||
	if (adc_idx > ADC_HISTLEN) {
 | 
			
		||||
		// nothing to copy when first starting
 | 
			
		||||
		adc_idx = 0;
 | 
			
		||||
@ -122,21 +183,9 @@ void adc_next()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// wait for calibration to complete, if started
 | 
			
		||||
    while (ADC1->CR & ADC_CR_ADCAL);
 | 
			
		||||
    while (ADC1->CR & ADC_CR_ADCAL) {};
 | 
			
		||||
 | 
			
		||||
    // configure and enable DMA
 | 
			
		||||
    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
 | 
			
		||||
	ADC1->ISR = 0x8e;			// clear all interrupt flags (per DS; mistranslated)
 | 
			
		||||
    ADC1->CR  = ADC_CR_ADEN;
 | 
			
		||||
    ADC1->CR |= ADC_CR_ADSTART;
 | 
			
		||||
	adc_go();
 | 
			
		||||
 | 
			
		||||
	return adc_idx;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								src/flash.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/flash.c
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
 | 
			
		||||
	// clear outputs
 | 
			
		||||
	RGBSEL0_PORT->BRR = (1 << RGBSEL0_PIN);
 | 
			
		||||
	RGBSEL1_PORT->BRR = (1 << RGBSEL1_PIN);
 | 
			
		||||
	RGBSEL0_PORT->BSRR = (1 << RGBSEL0_PIN);
 | 
			
		||||
	RGBSEL1_PORT->BSRR = (1 << RGBSEL1_PIN);
 | 
			
		||||
 | 
			
		||||
	if (!led_sel || (led_mode == MODE_RGB)) {
 | 
			
		||||
		// set PWMs in RGB mode, or when right LED set
 | 
			
		||||
		PWM_RGB_R = rgb[led_sel][RED];
 | 
			
		||||
		PWM_RGB_R = rgb[led_sel][GRN];
 | 
			
		||||
		PWM_RGB_R = rgb[led_sel][BLU];
 | 
			
		||||
		PWM_RGB_G = rgb[led_sel][GRN];
 | 
			
		||||
		PWM_RGB_B = rgb[led_sel][BLU];
 | 
			
		||||
	} else {
 | 
			
		||||
		// clear PWMs in piezo mode when piezo should be active
 | 
			
		||||
		PWM_RGB_R = PWM_RGB_G = PWM_RGB_B = 0;
 | 
			
		||||
@ -58,9 +58,9 @@ void led_next()
 | 
			
		||||
	// enable selected LED
 | 
			
		||||
	if (led_sel) {
 | 
			
		||||
		if ((led_mode == MODE_BUZZ) && !snd_buzz) return;
 | 
			
		||||
		RGBSEL1_PORT->BSRR = (1 << RGBSEL1_PIN);
 | 
			
		||||
		RGBSEL1_PORT->BRR = (1 << RGBSEL1_PIN);
 | 
			
		||||
	} else {
 | 
			
		||||
		RGBSEL0_PORT->BSRR = (1 << RGBSEL0_PIN);
 | 
			
		||||
		RGBSEL0_PORT->BRR = (1 << RGBSEL0_PIN);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -145,6 +145,9 @@ void led_init()
 | 
			
		||||
	led_mode = MODE_RGB;
 | 
			
		||||
	led_sel = 1;
 | 
			
		||||
	snd_buzz = 0;
 | 
			
		||||
 | 
			
		||||
	rgb[0][0] = 100;
 | 
			
		||||
	rgb[1][1] = 100;
 | 
			
		||||
	
 | 
			
		||||
	// start outputting data
 | 
			
		||||
	led_next();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/main.c
									
									
									
									
									
								
							@ -10,7 +10,9 @@
 | 
			
		||||
#include "testo.h"
 | 
			
		||||
 | 
			
		||||
#include "adc.h"
 | 
			
		||||
#include "flash.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "userio.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -30,8 +32,8 @@ static inline void gpio_init()
 | 
			
		||||
    // enable pullups on I2C outputs
 | 
			
		||||
    GPIOA->PUPDR   = 0x24000050;
 | 
			
		||||
    // datasheet doesn't say what the speeds are for GPIO...
 | 
			
		||||
    // so set SWDIO to very high speed, all other outputs as high speed
 | 
			
		||||
    GPIOA->OSPEEDR = 0x2E002AA0;
 | 
			
		||||
    // so set SWDIO to very high speed, PA12 low speed, all other outputs as high speed
 | 
			
		||||
    GPIOA->OSPEEDR = 0x2C002AA0;
 | 
			
		||||
    // alternate function select
 | 
			
		||||
    // PA6=T3C1, PA5=T3C2, PA4=T3C3, PA3=I2C_SCL, PA2=I2C_SDA
 | 
			
		||||
    GPIOA->AFR[0]  = 0x01DDCC00;
 | 
			
		||||
@ -44,26 +46,27 @@ static inline void gpio_init()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // PB1=OUT, PB0=AN
 | 
			
		||||
    // unused pins are analog
 | 
			
		||||
    GPIOB->OSPEEDR = 0x00000008;
 | 
			
		||||
    // unused pins are analog, all outputs are low speed
 | 
			
		||||
    GPIOB->OSPEEDR = 0x00000000;
 | 
			
		||||
    GPIOB->MODER   = 0xfffffff7;
 | 
			
		||||
 | 
			
		||||
    // PF2=OUT, low speed
 | 
			
		||||
    // PF2=OUT(low), low speed
 | 
			
		||||
    // unused pins are analog
 | 
			
		||||
    GPIOF->ODR     = (1 << 2);
 | 
			
		||||
    GPIOF->MODER   = 0xFFFFFCDF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void clk_init()
 | 
			
		||||
{
 | 
			
		||||
    // run all buses at core clock speed
 | 
			
		||||
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_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 |
 | 
			
		||||
                    LL_IOP_GRP1_PERIPH_GPIOB |
 | 
			
		||||
                    LL_IOP_GRP1_PERIPH_GPIOF;
 | 
			
		||||
 | 
			
		||||
    // enable peripheral clocks
 | 
			
		||||
    RCC->AHBENR  = LL_AHB1_GRP1_PERIPH_DMA1;
 | 
			
		||||
    RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3;
 | 
			
		||||
    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
 | 
			
		||||
    // this assumes we'll always be running at 8MHz
 | 
			
		||||
    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
 | 
			
		||||
    clk_init();
 | 
			
		||||
    flash_init();   // also configures option bytes, if necessary
 | 
			
		||||
    gpio_init();
 | 
			
		||||
 | 
			
		||||
    // peripheral initialization
 | 
			
		||||
@ -116,20 +126,36 @@ int main()
 | 
			
		||||
 */
 | 
			
		||||
void SysTick_Handler(void)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t cs;
 | 
			
		||||
 | 
			
		||||
    ctr++;
 | 
			
		||||
 | 
			
		||||
    // run LED programs quickly
 | 
			
		||||
    led_next();
 | 
			
		||||
 | 
			
		||||
    // limit counter to 4096
 | 
			
		||||
    // limit counter to 4096 counts
 | 
			
		||||
    ctr &= 0xfff;
 | 
			
		||||
    if (!ctr) {
 | 
			
		||||
        uptime++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // run main logic at 1024Hz
 | 
			
		||||
    if ((ctr & 0x3) == 0) {
 | 
			
		||||
        // adc
 | 
			
		||||
        adc_next();
 | 
			
		||||
    if (!(ctr & 0x3)) {
 | 
			
		||||
        // shifted counter for use in the program
 | 
			
		||||
        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
 | 
			
		||||
 * pushed, as button being pushed negates the mode switch response.
 | 
			
		||||
@ -29,23 +29,26 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MODE_CONT           0
 | 
			
		||||
#define MODE_CONT_TARGET    0x46d
 | 
			
		||||
#define MODE_CONT_TARGET    (4096 * (1 - (1 / 4)))
 | 
			
		||||
 | 
			
		||||
#define MODE_FUN            1
 | 
			
		||||
#define MODE_FUN_TARGET     0xa2b
 | 
			
		||||
#define MODE_FUN_TARGET     (4096 * (1 - (1 / 3)))
 | 
			
		||||
 | 
			
		||||
#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 modesw_next;
 | 
			
		||||
uint8_t modesw_count;
 | 
			
		||||
uint8_t mode;
 | 
			
		||||
uint8_t mode_next;
 | 
			
		||||
uint8_t mode_count;
 | 
			
		||||
static const uint16_t mode_targets[] = {
 | 
			
		||||
    MODE_CONT_TARGET, MODE_FUN_TARGET, MODE_DIODE_TARGET
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
uint8_t knob[2];
 | 
			
		||||
 | 
			
		||||
@ -54,6 +57,11 @@ uint16_t btn_held = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void userio_update()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void userio_parse()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user