handle button input

config read/writes should be protected with a semaphore?

changing adc speed works somehow, might need to change to avoid unseen TI-RTOS clobbers
This commit is contained in:
Andy Killorin 2025-04-12 17:57:48 -04:00
parent 564d05b183
commit e8946f2a03
4 changed files with 78 additions and 70 deletions

View file

@ -6,6 +6,17 @@
*
* ECE 3849 Lab button handling
*/
/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/cfg/global.h>
/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
@ -32,17 +43,6 @@ extern volatile uint32_t gTime; // time in hundredths of a second
// initialize all button and joystick handling hardware
void ButtonInit(void)
{
// initialize a general purpose timer for periodic interrupts
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
TimerDisable(TIMER0_BASE, TIMER_BOTH);
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
TimerLoadSet(TIMER0_BASE, TIMER_A, roundf((float)gSystemClock / BUTTON_SCAN_RATE) - 1);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerEnable(TIMER0_BASE, TIMER_BOTH);
// initialize interrupt controller to respond to timer interrupts
IntPrioritySet(INT_TIMER0A, BUTTON_INT_PRIORITY);
IntEnable(INT_TIMER0A);
// GPIO PJ0 and PJ1 = EK-TM4C1294XL buttons 1 and 2
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
GPIOPinTypeGPIOInput(GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
@ -153,9 +153,19 @@ uint32_t ButtonAutoRepeat(void)
return presses;
}
// ISR for scanning and debouncing buttons
void ButtonISR(void) {
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // clear interrupt flag
void clock_buttons(void) {
Semaphore_post(button_clock_sem);
}
void button_task(void) {
while(1) {
Semaphore_pend(button_clock_sem, BIOS_WAIT_FOREVER);
handle_buttons();
}
}
// Task for scanning and debouncing buttons
void handle_buttons(void) {
// read hardware button state
uint32_t gpio_buttons =
~GPIOPinRead(GPIO_PORTJ_BASE, 0xff) & (GPIO_PIN_1 | GPIO_PIN_0); // EK-TM4C1294XL buttons in positions 0 and 1
@ -181,25 +191,12 @@ void ButtonISR(void) {
ButtonReadJoystick(); // Convert joystick state to button presses. The result is in gButtons.
uint32_t presses = ~old_buttons & gButtons; // detect button presses (transitions from not pressed to pressed)
presses |= ButtonAutoRepeat(); // autorepeat presses if a button is held long enough
#ifdef DISPLAY_TIME
static bool tic = false;
static bool running = true;
if (presses & 1) { // EK-TM4C1294XL button 1 pressed
running = !running;
}
if (presses & 2) { // EK-TM4C1294XL button 2 pressed
gTime = 0;
}
if (running) {
if (tic) gTime++; // increment time every other ISR call
tic = !tic;
}
#endif // DISPLAY_TIME
Button buttons[9];
uint8_t length, i;
length = buttons_from_mask(buttons, presses);
for (i=0; i<length; i++) {
fifo_put(buttons[i]);
Mailbox_post(button_mailbox,buttons+i, BIOS_WAIT_FOREVER);
}
}
@ -217,39 +214,3 @@ uint8_t buttons_from_mask(Button *array, uint32_t buttons) {
return len;
}
volatile DataType button_fifo[FIFO_SIZE]; // FIFO storage array
volatile int fifo_head = 0; // index of the first item in the FIFO
volatile int fifo_tail = 0; // index one step past the last item
// put data into the FIFO, skip if full
// returns 1 on success, 0 if FIFO was full
int fifo_put(DataType data)
{
int new_tail = fifo_tail + 1;
if (new_tail >= FIFO_SIZE) new_tail = 0; // wrap around
if (fifo_head != new_tail) { // if the FIFO is not full
button_fifo[fifo_tail] = data; // store data into the FIFO
fifo_tail = new_tail; // advance FIFO tail index
return 1; // success
}
return 0; // full
}
// get data from the FIFO
// returns 1 on success, 0 if FIFO was empty
int fifo_get(DataType *data)
{
if (fifo_head != fifo_tail) { // if the FIFO is not empty
*data = button_fifo[fifo_head]; // read data from the FIFO
if (fifo_head >= FIFO_SIZE-1) {
fifo_head = 0; // reset if past end
} else {
fifo_head++; // increment if within buffer
}
return 1; // success
}
return 0; // empty
}

View file

@ -69,9 +69,6 @@ typedef enum {
// returns length
uint8_t buttons_from_mask(Button *array, uint32_t buttons);
#define FIFO_SIZE 11 // FIFO capacity is 1 item fewer
typedef Button DataType; // FIFO data type
int fifo_put(DataType data);
int fifo_get(DataType *data);
void handle_buttons(void);
#endif /* BUTTONS_H_ */

30
main.c
View file

@ -110,6 +110,7 @@ int main(void)
// hardware initialization goes here
start_signal();
start_sampler();
ButtonInit();
Crystalfontz128x128_Init(); // Initialize the LCD display driver
Crystalfontz128x128_SetOrientation(LCD_ORIENTATION_UP); // set screen orientation
@ -177,6 +178,35 @@ void process_waveform(UArg arg1, UArg arg2) {
}
}
void handle_user_input() {
// handle buttons
Button button = (Button) 0;
while (true) {
Mailbox_pend(button_mailbox, &button, BIOS_WAIT_FOREVER);
switch (button) {
case S1: // toggle edge
trigger_mode++;
trigger_mode %= 3;
break;
case Up: // next scale
voltage_scale = (voltage_scale + 1) % VOLTAGE_SCALES;
break;
case Down: // previous scale
voltage_scale = (voltage_scale + VOLTAGE_SCALES - 1) % VOLTAGE_SCALES;
break;
case Right: // next scale
time_scale = (time_scale + 1) % TIME_SCALES;
set_frequency(gTImeScale[time_scale]);
break;
case Left: // previous scale
time_scale = (time_scale + TIME_SCALES - 1) % TIME_SCALES;
set_frequency(gTImeScale[time_scale]);
break;
}
}
}
void display_waveform(UArg arg1, UArg arg2)
{
char str[50]; // string buffer

View file

@ -566,10 +566,30 @@ task2Params.priority = 2;
Program.global.processing = Task.create("&process_waveform", task2Params);
var task3Params = new Task.Params();
task3Params.instance.name = "display";
task3Params.priority = 3;
task3Params.priority = 5;
task3Params.stackSize = 1024;
Program.global.display = Task.create("&display_waveform", task3Params);
var semaphore2Params0 = new Semaphore.Params();
semaphore2Params0.instance.name = "display_sem";
semaphore2Params0.mode = Semaphore.Mode_BINARY;
Program.global.display_sem = Semaphore.create(null, semaphore2Params0);
var clock0Params = new Clock.Params();
clock0Params.instance.name = "button_clock";
clock0Params.period = 5;
clock0Params.startFlag = true;
Program.global.button_clock = Clock.create("&clock_buttons", 1, clock0Params);
var semaphore3Params = new Semaphore.Params();
semaphore3Params.instance.name = "button_clock_sem";
semaphore3Params.mode = Semaphore.Mode_BINARY;
Program.global.button_clock_sem = Semaphore.create(null, semaphore3Params);
var task4Params = new Task.Params();
task4Params.instance.name = "button";
task4Params.priority = 14;
Program.global.button = Task.create("&button_task", task4Params);
var mailbox0Params = new Mailbox.Params();
mailbox0Params.instance.name = "button_mailbox";
Program.global.button_mailbox = Mailbox.create(1, 9, mailbox0Params);
var task5Params = new Task.Params();
task5Params.instance.name = "user_input";
task5Params.priority = 4;
Program.global.user_input = Task.create("&handle_user_input", task5Params);