Compare commits
No commits in common. "67814ef2ceb866722d13b88f6778678c8d9486a8" and "f5b7492de6c05a73d776a1f753959d0a15c57bc4" have entirely different histories.
67814ef2ce
...
f5b7492de6
5 changed files with 15 additions and 257 deletions
63
buttons.c
63
buttons.c
|
@ -28,6 +28,7 @@ uint32_t gADCSamplingRate; // [Hz] actual ADC sampling rate
|
|||
// imported globals
|
||||
extern uint32_t gSystemClock; // [Hz] system clock frequency
|
||||
extern volatile uint32_t gTime; // time in hundredths of a second
|
||||
extern volatile uint8_t drawRequested;
|
||||
|
||||
// initialize all button and joystick handling hardware
|
||||
void ButtonInit(void)
|
||||
|
@ -181,7 +182,6 @@ 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
|
||||
|
@ -190,66 +190,11 @@ void ButtonISR(void) {
|
|||
if (presses & 2) { // EK-TM4C1294XL button 2 pressed
|
||||
gTime = 0;
|
||||
}
|
||||
if (presses & 4) { // boosterpack button 1 pressed
|
||||
drawRequested = 1;
|
||||
}
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t buttons_from_mask(Button *array, uint32_t buttons) {
|
||||
uint8_t i, len;
|
||||
len = 0;
|
||||
|
||||
for(i=0; i<9; i++) {
|
||||
if (buttons & 1) {
|
||||
array[len++] = (Button) i;
|
||||
}
|
||||
|
||||
buttons >>= 1;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
26
buttons.h
26
buttons.h
|
@ -27,8 +27,8 @@
|
|||
#define BUTTON_AUTOREPEAT_INITIAL 100 // how many samples must read pressed before autorepeat starts
|
||||
#define BUTTON_AUTOREPEAT_NEXT 10 // how many samples must read pressed before the next repetition
|
||||
|
||||
#define JOYSTICK_UPPER_PRESS_THRESHOLD 2200 // above this ADC value, button is pressed
|
||||
#define JOYSTICK_UPPER_RELEASE_THRESHOLD 2100 // below this ADC value, button is released
|
||||
#define JOYSTICK_UPPER_PRESS_THRESHOLD 2100 // above this ADC value, button is pressed
|
||||
#define JOYSTICK_UPPER_RELEASE_THRESHOLD 2000 // below this ADC value, button is released
|
||||
#define JOYSTICK_LOWER_PRESS_THRESHOLD 1700 // below this ADC value, button is pressed
|
||||
#define JOYSTICK_LOWER_RELEASE_THRESHOLD 1800 // above this ADC value, button is released
|
||||
|
||||
|
@ -52,26 +52,4 @@ void ButtonReadJoystick(void);
|
|||
// autorepeat button presses if a button is held long enough
|
||||
uint32_t ButtonAutoRepeat(void);
|
||||
|
||||
typedef enum {
|
||||
SW1 = 0,
|
||||
SW2,
|
||||
S1,
|
||||
S2,
|
||||
Select,
|
||||
Right,
|
||||
Left,
|
||||
Up,
|
||||
Down,
|
||||
} Button;
|
||||
|
||||
// convert mask into array of buttons
|
||||
//
|
||||
// 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);
|
||||
|
||||
#endif /* BUTTONS_H_ */
|
||||
|
|
153
main.c
153
main.c
|
@ -13,7 +13,6 @@
|
|||
#include "driverlib/fpu.h"
|
||||
#include "driverlib/sysctl.h"
|
||||
#include "driverlib/interrupt.h"
|
||||
#include "driverlib/timer.h"
|
||||
#include "Crystalfontz128x128_ST7735.h"
|
||||
#include <stdio.h>
|
||||
#include "grlib/grlib.h"
|
||||
|
@ -29,43 +28,7 @@
|
|||
|
||||
uint32_t gSystemClock; // [Hz] system clock frequency
|
||||
volatile uint32_t gTime = 0; // time in hundredths of a second
|
||||
volatile uint8_t refresh = 1;
|
||||
|
||||
// assumming square lcd
|
||||
#define HEIGHT LCD_VERTICAL_MAX
|
||||
#define WIDTH LCD_HORIZONTAL_MAX
|
||||
#define PIXELS_PER_DIV 20
|
||||
|
||||
#define VIN_RANGE 3.3 // volts
|
||||
#define ADC_BITS 12
|
||||
#define ADC_OFFSET 30
|
||||
|
||||
#define VOLTAGE_SCALES 5
|
||||
const char * const gVoltageScaleStr[VOLTAGE_SCALES] = {
|
||||
"100 mV", "200 mV", "500 mV", " 1 V", " 2 V"
|
||||
};
|
||||
|
||||
const float gVoltageScale[VOLTAGE_SCALES] = {
|
||||
0.1, 0.2, 0.5, 1., 2.
|
||||
};
|
||||
|
||||
#define TIME_SCALES 6
|
||||
const char * const gTimeScaleStr[TIME_SCALES] = {
|
||||
"100 ms", "50 ms", "20 ms", " 10 ms", "50 us", "20 us"
|
||||
};
|
||||
|
||||
const uint64_t gTImeScale[TIME_SCALES] = {
|
||||
100 * 1000 / PIXELS_PER_DIV,
|
||||
50 * 1000 / PIXELS_PER_DIV,
|
||||
20 * 1000 / PIXELS_PER_DIV,
|
||||
10 * 1000 / PIXELS_PER_DIV,
|
||||
50 / PIXELS_PER_DIV,
|
||||
20 / PIXELS_PER_DIV,
|
||||
};
|
||||
|
||||
uint32_t cputime_unloaded;
|
||||
|
||||
int Trigger(bool rising);
|
||||
volatile uint8_t drawRequested = 1;
|
||||
|
||||
// start a pwm test signal
|
||||
void start_signal() {
|
||||
|
@ -89,26 +52,6 @@ void start_signal() {
|
|||
PWMGenEnable(PWM0_BASE, PWM_GEN_1);
|
||||
}
|
||||
|
||||
uint32_t cpu_load_count(void)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
|
||||
TimerEnable(TIMER1_BASE, TIMER_A); // start one-shot timer
|
||||
while (!(TimerIntStatus(TIMER1_BASE, false) & TIMER_TIMA_TIMEOUT))
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
void start_cputimer() {
|
||||
// initialize timer 1 in one-shot mode for polled timing
|
||||
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
|
||||
TimerDisable(TIMER1_BASE, TIMER_BOTH);
|
||||
TimerConfigure(TIMER1_BASE, TIMER_CFG_ONE_SHOT);
|
||||
TimerLoadSet(TIMER1_BASE, TIMER_A, gSystemClock/100); // 10ms interval
|
||||
// baseline load
|
||||
cputime_unloaded = cpu_load_count();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
IntMasterDisable();
|
||||
|
||||
|
@ -128,61 +71,22 @@ int main(void) {
|
|||
GrContextInit(&sContext, &g_sCrystalfontz128x128); // Initialize the grlib graphics context
|
||||
GrContextFontSet(&sContext, &g_sFontFixed6x8); // select font
|
||||
|
||||
#ifdef DISPLAY_TIME
|
||||
uint32_t time; // local copy of gTime
|
||||
#endif // DISPLAY_TIME
|
||||
char str[50]; // string buffer
|
||||
|
||||
// full-screen rectangle
|
||||
tRectangle rectFullScreen = {0, 0, GrContextDpyWidthGet(&sContext)-1, GrContextDpyHeightGet(&sContext)-1};
|
||||
|
||||
ButtonInit();
|
||||
|
||||
start_cputimer();
|
||||
|
||||
IntMasterEnable();
|
||||
|
||||
uint8_t voltage_scale = 0;
|
||||
uint8_t time_scale = 0;
|
||||
uint8_t rising = 1;
|
||||
|
||||
while (true) {
|
||||
// calculate cpu usage
|
||||
uint32_t cputime_loaded;
|
||||
cputime_loaded = cpu_load_count();
|
||||
float usage_percent;
|
||||
usage_percent = (1.0 - (float) cputime_loaded / (float) cputime_unloaded) * (float) 100.;
|
||||
|
||||
// handle buttons
|
||||
Button button = (Button) 0;
|
||||
while (fifo_get(&button)) {
|
||||
switch (button) {
|
||||
case S1: // toggle edge
|
||||
rising = !rising;
|
||||
break;
|
||||
case S2: // draw
|
||||
refresh = !refresh;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
GrContextForegroundSet(&sContext, ClrBlack);
|
||||
GrRectFill(&sContext, &rectFullScreen); // fill screen with black
|
||||
|
||||
// assumming square lcd
|
||||
#define HEIGHT LCD_VERTICAL_MAX
|
||||
#define PIXELS_PER_DIV 20
|
||||
|
||||
GrContextForegroundSet(&sContext, ClrBlue);
|
||||
|
||||
// draw gridlines from the center out
|
||||
|
@ -196,39 +100,22 @@ int main(void) {
|
|||
}
|
||||
|
||||
|
||||
// info
|
||||
GrContextForegroundSet(&sContext, ClrWheat);
|
||||
GrStringDraw(&sContext, gVoltageScaleStr[voltage_scale], /*length*/ -1, /*x*/ 0, /*y*/ 0, /*opaque*/ false);
|
||||
GrStringDraw(&sContext, gTimeScaleStr[time_scale], /*length*/ -1, /*x*/ 60, /*y*/ 0, /*opaque*/ false);
|
||||
snprintf(str, sizeof(str), "CPU Load %.1f%%", usage_percent);
|
||||
GrStringDraw(&sContext, str, /*length*/ -1, /*x*/ 0, /*y*/ HEIGHT - 10, /*opaque*/ false);
|
||||
|
||||
if (rising) {
|
||||
GrStringDraw(&sContext, "^", /*length*/ -1, /*x*/ WIDTH - 10, /*y*/ 0, /*opaque*/ false);
|
||||
} else {
|
||||
GrStringDraw(&sContext, "v", /*length*/ -1, /*x*/ WIDTH - 10, /*y*/ 0, /*opaque*/ false);
|
||||
}
|
||||
|
||||
// display graph
|
||||
#define LOCAL_BUF_LEN 128
|
||||
uint16_t local_adc_buffer[LOCAL_BUF_LEN]; // copy of adc buffer
|
||||
int32_t adc_current_index;
|
||||
int32_t j;
|
||||
if (refresh) {
|
||||
int trigger = Trigger(rising);
|
||||
|
||||
adc_current_index = trigger - (WIDTH / 2);
|
||||
if (drawRequested) {
|
||||
adc_current_index = gADCBufferIndex - 128;
|
||||
for (j=0; j<LOCAL_BUF_LEN; j++) {
|
||||
local_adc_buffer[j] = gADCBuffer[ADC_BUFFER_WRAP(adc_current_index + j)];
|
||||
}
|
||||
drawRequested = 0;
|
||||
}
|
||||
|
||||
float fVoltsPerDiv = gVoltageScale[voltage_scale];
|
||||
float fScale = (VIN_RANGE * PIXELS_PER_DIV)/((1 << ADC_BITS) * fVoltsPerDiv);
|
||||
|
||||
GrContextForegroundSet(&sContext, ClrPink);
|
||||
for(j=0; j<LOCAL_BUF_LEN; j++) {
|
||||
#define TRANSPOSE(x) (HEIGHT/2) - (int)roundf(fScale * ((int)x - ADC_OFFSET));
|
||||
#define TRANSPOSE(x) (HEIGHT/2) - (x >> 6) // reduce from twelve to six bits, then flip and center
|
||||
uint32_t upper,lower, current, last;
|
||||
|
||||
if (j==0) {
|
||||
|
@ -284,25 +171,3 @@ int main(void) {
|
|||
GrFlush(&sContext); // flush the frame buffer to the LCD
|
||||
}
|
||||
}
|
||||
|
||||
int Trigger(bool rising) // search for edge trigger
|
||||
{
|
||||
int x = gADCBufferIndex - (WIDTH / 2); // half screen width
|
||||
int x_stop = x - ADC_BUFFER_SIZE/2;
|
||||
for (; x > x_stop; x--) {
|
||||
if (rising) {
|
||||
if ( gADCBuffer[ADC_BUFFER_WRAP(x)] >= ADC_OFFSET &&
|
||||
gADCBuffer[ADC_BUFFER_WRAP(x-1)] < ADC_OFFSET) {
|
||||
break;
|
||||
}
|
||||
} else { // falling edge trigger
|
||||
if ( gADCBuffer[ADC_BUFFER_WRAP(x)] <= ADC_OFFSET &&
|
||||
gADCBuffer[ADC_BUFFER_WRAP(x-1)] > ADC_OFFSET) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x == x_stop) // for loop ran to the end
|
||||
x = x = gADCBufferIndex - (WIDTH / 2); // reset x back to how it was initialized
|
||||
return x;
|
||||
}
|
||||
|
|
28
sampling.c
28
sampling.c
|
@ -6,7 +6,6 @@
|
|||
#include "driverlib/gpio.h"
|
||||
#include "driverlib/sysctl.h"
|
||||
#include "driverlib/interrupt.h"
|
||||
#include "driverlib/timer.h"
|
||||
#include "sysctl_pll.h"
|
||||
#include "inc/hw_types.h"
|
||||
#include "inc/hw_memmap.h"
|
||||
|
@ -14,8 +13,6 @@
|
|||
#include "buttons.h"
|
||||
#include "sampling.h"
|
||||
|
||||
extern uint32_t gSystemClock; // [Hz] system clock frequency
|
||||
|
||||
// latest sample index
|
||||
void ADC_ISR(void)
|
||||
{
|
||||
|
@ -44,9 +41,6 @@ void start_sampler() {
|
|||
// initialize ADC peripherals
|
||||
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
|
||||
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
|
||||
|
||||
// timer for low-speed
|
||||
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
|
||||
// ADC clock
|
||||
uint32_t pll_frequency = SysCtlFrequencyGet(CRYSTAL_FREQUENCY);
|
||||
uint32_t pll_divisor =
|
||||
|
@ -70,25 +64,3 @@ void start_sampler() {
|
|||
// enable ADC1 sequence 0 interrupt in int. controller
|
||||
IntEnable(INT_ADC1SS0);
|
||||
}
|
||||
|
||||
void set_frequency(uint64_t microseconds) {
|
||||
if (microseconds == 1) {
|
||||
ADCSequenceDisable(ADC1_BASE, 0);
|
||||
// don't use a timer for high speed
|
||||
ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 0);
|
||||
ADCSequenceEnable(ADC1_BASE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize timer 2 in periodic mode
|
||||
TimerDisable(TIMER2_BASE, TIMER_BOTH);
|
||||
TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
|
||||
#define MICROSECONDS_PER_SECOND 1000000
|
||||
TimerLoadSet(TIMER2_BASE, TIMER_A, (uint32_t) ((uint64_t) gSystemClock * microseconds / MICROSECONDS_PER_SECOND) - 1);
|
||||
TimerControlTrigger(TIMER2_BASE, TIMER_A, true);
|
||||
TimerEnable(TIMER2_BASE, TIMER_A);
|
||||
|
||||
ADCSequenceDisable(ADC1_BASE, 0);
|
||||
ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_TIMER, 0);
|
||||
ADCSequenceEnable(ADC1_BASE, 0);
|
||||
}
|
|
@ -15,6 +15,4 @@ volatile uint32_t gADCErrors; // number of missed ADC deadlines
|
|||
// initialize ADC and ISR
|
||||
void start_sampler(void);
|
||||
|
||||
void set_frequency(uint64_t microseconds);
|
||||
|
||||
#endif /* SAMPLING_H_ */
|
||||
|
|
Loading…
Reference in a new issue