Added more RGBLED programs, ADC fixups

This commit is contained in:
true 2023-10-31 07:46:11 -07:00
parent 724a2402ab
commit aa52d57149
8 changed files with 414 additions and 65 deletions

20
include/rand.h Normal file
View File

@ -0,0 +1,20 @@
/*
* rand.c: good enough for flashing led bits
*
* file creation: 20231031 0506
*/
#ifndef _INC_RAND_H
#define _INC_RAND_H
#include <stdint.h>
void rand_init(uint32_t init);
uint32_t rand();
#endif /* _INC_RAND_H */

View File

@ -56,27 +56,28 @@ static uint8_t calibrate = 0;
void adc_init()
{
// ensure ADC is disabled
// ensure ADC is DISABLED to write to registers
// this is opposite of what the RM says... the RM is wrong
ADC1->CR = 0;
// calibration configuration
ADC1->CCSR = LL_ADC_CAL_SAMPLINGTIME_8CYCLES | ADC_CCSR_CALSEL;
// enable VREFINT
ADC->CCR = ADC_CCR_VREFEN; // ADC_CCR_TSEN |
// configure scan channels, sampling time (11 = temp, 12 = vrefint)
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and VREFEXT are
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
ADC_CHSELR_CHSEL12;
ADC1->SMPR = SAMPLE_TIME;
// run in one-shot mode (all channel conversion per trigger)
// enable end of conversion interrupt
ADC1->IER = ADC_IER_EOCIE;
// run in one-shot mode (all channel conversion per trigger)
// with wait mode (anti-overrun) active
ADC1->CFGR1 = ADC_CFGR1_OVRMOD | ADC_CFGR1_WAIT;
// enable end of conversion interrupt
ADC1->IER = ADC_IER_EOCIE;
// configure scan channels, sampling time (11 = temp, 12 = vrefint)
ADC1->SMPR = SAMPLE_TIME;
ADC1->CHSELR = CONF_SET1_AN | PROBE_AN | // note: SET1 and VREFEXT are
CONF_MODE_AN | CONF_SET0_AN | // shared and reflect one chan
ADC_CHSELR_CHSEL12;
// calibration configuration
ADC1->CCSR = LL_ADC_CAL_SAMPLINGTIME_8CYCLES | ADC_CCSR_CALSEL;
// and enable the interrupt source in the NVIC
NVIC_EnableIRQ(ADC_COMP_IRQn);
@ -103,12 +104,10 @@ void adc_go()
adc_stop();
// restart sequence
adc_seq = 0;
// enable and start ADC
ADC1->ISR = 0x1e; // clear all interrupt flags (per DS; mistranslated)
ADC1->CR = ADC_CR_ADEN;
ADC1->CR |= ADC_CR_ADSTART;
ADC1->CR = ADC_CR_ADEN; // enable ADC
adc_seq = 0; // reset channel read sequence
ADC1->ISR = 0x1e; // clear all interrupt flags (per DS; mistranslated)
ADC1->CR = ADC_CR_ADSTART | ADC_CR_ADEN; // begin conversion
}
/*

View File

@ -1,6 +1,9 @@
/*
* led.c: rgbled (and piezo) routines
*
* LED functions expect 11-bit values (0-2047).
* Actual output is right shifted by one and clamped 0-999.
*
* file creation: 20231015 0037
*/
@ -47,9 +50,9 @@ void led_next()
if (!led_sel || (led_mode == MODE_RGB)) {
// set PWMs in RGB mode, or when right LED set
PWM_RGB_R = (rgb[led_sel][RED] >> 1) + (rgb[led_sel][RED] >> 2); // 75%
PWM_RGB_G = (rgb[led_sel][GRN] >> 2) + (rgb[led_sel][GRN] >> 3); // 62%
PWM_RGB_B = (rgb[led_sel][BLU] ) + (rgb[led_sel][BLU] << 2); // 125%
PWM_RGB_R = (rgb[led_sel][RED] >> 2) + (rgb[led_sel][RED] >> 3); // 75%
PWM_RGB_G = (rgb[led_sel][GRN] >> 2) + (rgb[led_sel][GRN] >> 4); // 62%
PWM_RGB_B = (rgb[led_sel][BLU] >> 1); // 100%
} else {
// clear PWMs in piezo mode when piezo should be active
PWM_RGB_R = PWM_RGB_G = PWM_RGB_B = 0;

View File

@ -10,11 +10,16 @@
#include "testo.h"
#include "adc.h"
#include "flash.h"
#include "led.h"
#include "probe.h"
#include "userio.h"
#include "led.h"
#include "rgbprog.h"
#include "rand.h"
#include "flash.h"
uint16_t ctr;
@ -71,6 +76,8 @@ static inline void clk_init()
LL_IOP_GRP1_PERIPH_GPIOB |
LL_IOP_GRP1_PERIPH_GPIOF;
RCC->AHBENR |= LL_AHB1_GRP1_PERIPH_CRC;
RCC->APBENR1 = LL_APB1_GRP1_PERIPH_TIM3;
RCC->APBENR2 = LL_APB1_GRP2_PERIPH_ADC1;
}
@ -110,7 +117,9 @@ int main()
while (1) {
// run LED programs out of interrupt context at 256Hz
if ((ctr & 0xf) == 0) {
if (userio_get_mode() == MODE_FUN) {
rgbprog_run();
}
}
// nap time
@ -122,7 +131,7 @@ int main()
* main application interrupt
*/
__attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void)
void SysTick_Handler(void)
{
uint16_t cs;
@ -142,13 +151,6 @@ __attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void)
// shifted counter for use in the program
cs = ctr >> 2;
// run LED program (if in LED mode) at 256Hz
if (!(cs & 0x3)) {
if (userio_get_mode() == MODE_FUN) {
rgbprog_run();
}
}
// adc tested to result in about 61 reads/second
if (!adc_next()) {
// adc has new computed results
@ -156,6 +158,9 @@ __attribute__ ((long_call, section(".ramfunc"))) void SysTick_Handler(void)
// figure out knobs, buttons, switches
userio_parse();
// initialize randomness
rand_init((knob[0] << 8) | knob[1]);
// show probe measurement results, or if not in a measurement mode,
// run RGBLED program
probe_measure();

View File

@ -71,7 +71,7 @@ static inline void probe_measure_cont()
// indicate continuity
if (x >= 2420) latch--; // hysteresis
led_setrgb(0, 0, 200, ((buzzer) ? 500 : 0));
led_setrgb(0, 0, 250, ((buzzer) ? 100 : 0));
led_buzz(0);
if (buzzer) led_buzz(1);
} else {

31
src/rand.c Normal file
View File

@ -0,0 +1,31 @@
/*
* rand.c: good enough for flashing led bits
*
* file creation: 20231031 0501
*/
#include "py32f0xx_conf.h"
uint8_t done = 0;
void rand_init(uint32_t init)
{
if (done) return;
CRC->CR = CRC_CR_RESET;
while (CRC->CR & CRC_CR_RESET);
CRC->DR = init;
done = 1;
}
uint32_t rand()
{
CRC->DR = 1;
return CRC->DR;
}

View File

@ -1,37 +1,106 @@
/*
* rgbprog.c: making your eyes light up
*
* program notes:
* knob[0] is the left knob, 0-255.
* there are 8 programs selected by the knob[0] position.
*
* k0 passed to rgb programs is the 5 bits of position
* of the knob[0] value for the selected program.
* these can be used within the program.
*
* knob[1] is the right knob, 0-255.
*
* raw knob values can be read from adc_avg[ADC_SET0] (left)
* and adc_avg[ADC_SET1] (right).
*
* raw values are safe to use from the left knob,
* but will vary on the right knob depending on board version.
* thus it is recommended to only use the 8-bit smoothed
* value for the right knob.
*
* file creation: 20231015 0119
*/
#include "led.h"
#include "hsv2rgb.h"
#include "rand.h"
#include "userio.h"
void rgbprog_rainbow();
void rgbprog_rainbow_offset();
#define hsv2rgb(idx, h, s, v) hsv2rgb_8b(h, s, v, &rgb[idx].r, &rgb[idx].g, &rgb[idx].b)
static void (*proglist[8])(void) = {
void rgbprog_rainbow(uint8_t k0);
void rgbprog_rainbow_offset(uint8_t k0);
void rgbprog_static(uint8_t k0);
void rgbprog_flicker(uint8_t k0);
void rgbprog_randcolorfadebetween(uint8_t k0);
void rgbprog_randcolor(uint8_t k0);
void rgbprog_randcolorfadeinout(uint8_t k0);
void rgbprog_prog7(uint8_t k0);
static void (*proglist[8])(uint8_t) = {
rgbprog_rainbow,
rgbprog_rainbow_offset,
rgbprog_static,
rgbprog_flicker,
rgbprog_randcolorfadebetween,
rgbprog_randcolor,
rgbprog_randcolorfadeinout,
rgbprog_prog7
};
static uint8_t prog_active;
static uint8_t prog_next;
static uint8_t prog_cntr;
static uint16_t brightness = 0;
static uint16_t brite = 0;
static color_hsv hsv[2];
static color_rgb rgb[2];
static color_rgb rfade;
void rgb_setled(uint8_t ledidx, color_rgb *rgb)
{
led_setrgb(ledidx, rgb->r << brite, rgb->g << brite, rgb->b << brite);
}
void rgb_fromhsv(uint8_t ledidx, uint16_t h, uint8_t s, uint8_t v)
{
hsv2rgb_8b(h, s, v, &rgb[ledidx].r, &rgb[ledidx].g, &rgb[ledidx].b);
}
void rgb_fade(uint8_t fade)
{
uint8_t i;
uint16_t mod, invmod;
uint8_t *rf = (uint8_t *)&rfade;
uint8_t *r[2] = { (uint8_t *)&rgb[0], (uint8_t *)&rgb[1] };
mod = fade + 1;
invmod = (255 - fade) + 1;
for (i = 0; i < 3; i++) {
if (!fade) {
rf[i] = r[0][i];
continue;
}
if (fade == 0xff) {
rf[i] = r[1][i];
continue;
}
rf[i] = ((r[0][i] * invmod) >> 8) + ((r[1][i] * mod) >> 8);
}
}
void rgbprog_run()
{
uint32_t i;
@ -39,8 +108,8 @@ void rgbprog_run()
// if the button has been pushed, change the brightness
if (userio_get_btn() > 0) {
brightness++;
if (brightness > 2) brightness = 0;
brite++;
brite &= 0x3;
}
// which program to run?
@ -48,7 +117,7 @@ void rgbprog_run()
for (i = 32; i <= 256; i += 32) {
if (knob[0] < i) {
if (proglist[j]) {
proglist[j]();
proglist[j](knob[0] & 0x1f);
}
break;
}
@ -56,7 +125,12 @@ void rgbprog_run()
}
}
void rgbprog_rainbow()
/*
* program 0: rainbow program
*
* both eyes are set to same rgb rainbow pattern
*/
void rgbprog_rainbow(uint8_t k0)
{
int16_t w;
@ -68,34 +142,251 @@ void rgbprog_rainbow()
if (hsv[0].h < 0) hsv[0].h += 0x3000;
hsv[0].h %= 0x3000;
hsv2rgb_8b(hsv[0].h >> 3, 255, 255, &rgb[0].r, &rgb[0].g, &rgb[0].b);
led_setrgb(0, rgb[0].r << brightness, rgb[0].g << brightness, rgb[0].b << brightness);
led_setrgb(1, rgb[0].r << brightness, rgb[0].g << brightness, rgb[0].b << brightness);
hsv2rgb(0, hsv[0].h >> 3, 255, 255);
rgb_setled(0, &rgb[0]);
rgb_setled(1, &rgb[0]);
}
void rgbprog_rainbow_offset()
/*
* program 1: rainbow program
*
* both eyes are set to rgb rainbow pattern,
* with offset between the eyes
*/
void rgbprog_rainbow_offset(uint8_t k0)
{
rgbprog_rainbow();
rgbprog_rainbow(k0);
hsv[1].h = hsv[0].h;
hsv[1].h += (knob[0] - 32) << 6;
hsv[1].h = hsv[0].h;
hsv[1].h += k0 << 6;
hsv[1].h %= 0x3000;
hsv2rgb_8b(hsv[1].h >> 3, 255, 255, &rgb[0].r, &rgb[0].g, &rgb[0].b);
led_setrgb(1, rgb[0].r << brightness, rgb[0].g << brightness, rgb[0].b << brightness);
hsv2rgb(1, hsv[1].h >> 3, 255, 255);
rgb_setled(1, &rgb[1]);
}
void rgbprog_randcolorfade()
/*
* program 2: static color
*
* both eyes are set to a static color
*
* left knob adjusts saturation
* right knob adjusts color hue
*/
void rgbprog_static(uint8_t k0)
{
hsv[0].h = knob[1] * 6;
hsv2rgb(0, hsv[0].h, 131 + (k0 << 2), 255);
rgb_setled(0, &rgb[0]);
rgb_setled(1, &rgb[0]);
}
void rgbprog_randcolorfade_single()
/*
* program 3: flicker
*
* both eyes are set to a static flickering color
* left knob adjusts flicker level
* right knob adjusts color hue
*/
void rgbprog_flicker(uint8_t k0)
{
uint8_t i;
uint8_t val;
}
void rgbprog_randcolorfade_dual()
{
// operate only 1/4 of the time
hsv[0].s++;
hsv[0].s &= 3;
if (hsv[0].s) return;
hsv[0].h = knob[1] * 6;
// independent flicker for each eye
for (i = 0; i < 2; i++) {
// left knob sets flicker
if ((rand() & 0xff) > (k0 << 3)) {
// full bright
val = 0xff;
} else {
// flicker
val = 0x2f;
}
hsv2rgb(i, hsv[0].h, 255, val);
rgb_setled(i, &rgb[i]);
}
}
/*
* program 4: random fade between colors
*
* linear fade between two random colors
*/
void rgbprog_randcolorfadebetween(uint8_t k0)
{
int16_t w;
// set delay based on left knob
hsv[0].s++;
if (hsv[0].s > (k0 >> 1)) hsv[0].s = 0;
if (hsv[0].s) return;
// update new colors at the end of every fade
hsv[0].v += 3;
if (hsv[0].v <= 2) {
// set new initial colors
hsv[0].h = hsv[1].h;
hsv[1].h = rand() % 1536;
// clamp discrete colors to 64
w = 4 * 6;
hsv[1].h /= w;
hsv[1].h *= w;
hsv2rgb(0, hsv[0].h, 255, 255);
hsv2rgb(1, hsv[1].h, 255, 255);
}
// do the fade
rgb_fade(hsv[0].v);
// and output the result
rgb_setled(0, &rfade);
rgb_setled(1, &rfade);
}
/*
* program 5:
*
* change between two random colors
*
* left knob sets single color or dual color
* right knob sets speed
*/
void rgbprog_randcolor(uint8_t k0)
{
// set delay based on right knob
hsv[1].h += knob[1];
hsv[1].h++;
if (hsv[1].h >= 0x1000) { // 1/16 rate
hsv[1].h -= 0x1000;
// update time
hsv[0].h = rand() % 1536;
hsv2rgb(0, hsv[0].h, 255, 255);
if (k0 >= 16) {
rgb_setled(rand() & 1, &rgb[0]);
} else {
rgb_setled(0, &rgb[0]);
rgb_setled(1, &rgb[0]);
}
}
}
/*
* program 6:
*
* fade up into a random color, hold, then fade out
*
* left knob sets dwell
* right knob sets cycle time
*/
void rgbprog_randcolorfadeinout(uint8_t k0)
{
uint16_t w;
// operate only 1/4 of the time
hsv[0].s++;
hsv[0].s &= 3;
if (hsv[0].s) return;
// hsv[1].h contains fade counter
// hsv[1].s contains dwell counter
// hsv[1].v contains our state
hsv[1].v &= 0x3;
switch (hsv[1].v) {
case 0:
case 2: {
// ramp up/down
// first run or new run?
if (!hsv[1].h) {
// set a new hue
hsv[0].h = rand() % 1536;
}
// fade up or down
hsv[1].h += (knob[1]);
hsv[1].h++;
// clamp value
if (hsv[1].h > 0x7ff) {
hsv[1].h = 0x7ff;
}
// set output
w = hsv[1].v ? (0x7ff - hsv[1].h) : hsv[1].h;
w >>= 3;
hsv2rgb(0, hsv[0].h, 255, (w & 0xff));
// are we done?
if (hsv[1].h == 0x7ff) {
hsv[1].h = 0;
hsv[1].v++;
}
break;
}
case 1:
case 3: {
// hold
// just getting to this step?
if (!hsv[1].h) {
// initialize step
hsv[1].h++;
hsv[1].s = 0;
} else {
// delay here
w = hsv[1].s;
w += k0;
w++;
// are we done?
if (w > 0x100) {
if (hsv[1].v == 3) {
hsv[1].h = 0;
}
hsv[1].v++;
} else {
hsv[1].s = w & 0xff;
}
}
}
}
rgb_setled(0, &rgb[0]);
rgb_setled(1, &rgb[0]);
}
/*
* program 7:
*
* turns LEDs off.
*
* it's basically an empty program.
* if you want to write your own, do it here
*
* maybe you could write a smart morse generator,
* or a cop mode, or...
*/
void rgbprog_prog7(uint8_t k0)
{
rgb[0].r = rgb[0].g = rgb[0].b = 0;
rgb_setled(0, &rgb[0]);
rgb_setled(1, &rgb[0]);
}

View File

@ -15,15 +15,15 @@
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz*/
#define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
#if !defined (LSI_VALUE)
#define LSI_VALUE 32768U /*!< Value of LSI in Hz*/
#define LSI_VALUE 32768U /*!< Value of LSI in Hz*/
#endif /* LSI_VALUE */
#if !defined (LSE_VALUE)
#define LSE_VALUE 32768U /*!< Value of LSE in Hz*/
#define LSE_VALUE 32768U /*!< Value of LSE in Hz*/
#endif /* LSE_VALUE */
@ -120,7 +120,7 @@ void SystemInit(void)
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
#elif !BOOTLOADED
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}