Skip to content

Commit

Permalink
Seven segment display handling and refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
merrittlj committed Apr 29, 2024
1 parent 77e978b commit 898ff93
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 33 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ROOT_DIR := $(SRC_DIR)/root
HAL_DIR := $(SRC_DIR)/hal
PROG_DIR := $(SRC_DIR)/prog
STATE_DIR := $(SRC_DIR)/state
SEG_DIR := $(SRC_DIR)/seg

INC_SRCH_PATH :=
INC_SRCH_PATH += -I$(INCLUDE_DIR)
Expand All @@ -17,11 +18,12 @@ INC_SRCH_PATH += -I$(ROOT_DIR)
INC_SRCH_PATH += -I$(HAL_DIR)
INC_SRCH_PATH += -I$(PROG_DIR)
INC_SRCH_PATH += -I$(STATE_DIR)
INC_SRCH_PATH += -I$(SEG_DIR)

LIB_SRCH_PATH :=
LIB_SRCH_PATH += -L$(MAKE_DIR)/libs

LIBS := -lhal -lprog -lstate -lc -lgcc
LIBS := -lhal -lprog -lstate -lseg -lc -lgcc -lm

# Toolchain
CC := arm-none-eabi-gcc
Expand Down Expand Up @@ -56,6 +58,7 @@ build: dep
@$(MAKE) -C $(HAL_DIR) -f hal.mk
@$(MAKE) -C $(PROG_DIR) -f prog.mk
@$(MAKE) -C $(STATE_DIR) -f state.mk
@$(MAKE) -C $(SEG_DIR) -f seg.mk
@$(MAKE) -C $(ROOT_DIR) -f root.mk

full_clean: clean dep_clean
Expand All @@ -64,6 +67,7 @@ clean:
@$(MAKE) -C $(HAL_DIR) -f hal.mk clean
@$(MAKE) -C $(PROG_DIR) -f prog.mk clean
@$(MAKE) -C $(STATE_DIR) -f state.mk clean
@$(MAKE) -C $(SEG_DIR) -f seg.mk clean
@$(MAKE) -C $(ROOT_DIR) -f root.mk clean

dep_clean:
Expand Down
27 changes: 9 additions & 18 deletions src/prog/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,35 @@ const struct state DEFAULT_FSM[NUM_DEFAULT_STATES] = {
}
};

void write_builtin_led(uint8_t color, uint8_t mode)
{
gpio_set_mode(PIN('C', color), GPIO_MODE_OUTPUT);
gpio_write(PIN('C', color), mode);
}

void max_speed_action()
{
gpio_set_mode(PIN('C', 14), GPIO_MODE_OUTPUT);
gpio_write(PIN('C', 14), GPIO_OUTPUT_SET);
gpio_set_mode(LED_RED_PIN, GPIO_MODE_OUTPUT);
gpio_write(LED_RED_PIN, GPIO_OUTPUT_SET);
}

void max_speed_transition()
{
gpio_set_mode(PIN('C', 14), GPIO_MODE_OUTPUT);
gpio_write(PIN('C', 14), GPIO_OUTPUT_CLEAR);
gpio_write(LED_RED_PIN, GPIO_OUTPUT_CLEAR);
}

void trip_distance_action()
{
gpio_set_mode(PIN('C', 15), GPIO_MODE_OUTPUT);
gpio_write(PIN('C', 15), GPIO_OUTPUT_SET);
gpio_set_mode(LED_GREEN_PIN, GPIO_MODE_OUTPUT);
gpio_write(LED_GREEN_PIN, GPIO_OUTPUT_SET);
}

void trip_distance_transition()
{
gpio_set_mode(PIN('C', 15), GPIO_MODE_OUTPUT);
gpio_write(PIN('C', 15), GPIO_OUTPUT_CLEAR);
gpio_write(LED_GREEN_PIN, GPIO_OUTPUT_CLEAR);
}

void total_distance_action()
{
gpio_set_mode(PIN('F', 0), GPIO_MODE_OUTPUT);
gpio_write(PIN('F', 0), GPIO_OUTPUT_SET);
gpio_set_mode(LED_BLUE_PIN, GPIO_MODE_OUTPUT);
gpio_write(LED_BLUE_PIN, GPIO_OUTPUT_SET);
}

void total_distance_transition()
{
gpio_set_mode(PIN('F', 0), GPIO_MODE_OUTPUT);
gpio_write(PIN('F', 0), GPIO_OUTPUT_CLEAR);
gpio_write(LED_BLUE_PIN, GPIO_OUTPUT_CLEAR);
}
14 changes: 9 additions & 5 deletions src/prog/prog.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@
#define PROG_H
#include <stdint.h>

#include "hal.h"
#include "state.h"


/* LED pin #'s. */
enum {LED_COLOR_RED = 6, LED_COLOR_BLUE, LED_COLOR_ORANGE, LED_COLOR_GREEN};

/* Write LED color on port to mode. */
extern void write_builtin_led(uint8_t color, uint8_t mode);
/* Pins */
#define STATEBTN_PIN (PIN('C', 13))
#define LED_RED_PIN (PIN('B', 5))
#define LED_GREEN_PIN (PIN('B', 4))
#define LED_BLUE_PIN (PIN('B', 3))
#define SHIFT_SER_PIN (PIN('A', 10))
#define SHIFT_RCLK_PIN (PIN('A', 9))
#define SHIFT_SRCLK_PIN (PIN('A', 8))

/* States for the default FSM. */
enum {STATE_MAX_SPEED, STATE_TRIP_DISTANCE, STATE_TOTAL_DISTANCE, NUM_DEFAULT_STATES};
Expand Down
41 changes: 32 additions & 9 deletions src/root/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,58 @@
#include "prog.h"
#include "hal.h"
#include "state.h"
#include "seg.h"


int main()
{
uint32_t debounce_timer, debounce_period = 20;
uint32_t idle_timer, idle_period = 10000;
uint8_t is_idle = 0;
uint32_t seg_timer, seg_period = 1000;

uint16_t usrbtn = PIN('C', 13);
uint8_t button_pressed = 0;
gpio_set_mode(usrbtn, GPIO_MODE_INPUT);
gpio_set_mode(STATEBTN_PIN, GPIO_MODE_INPUT);

struct fsm machine;
fsm_init(&machine, DEFAULT_FSM, STATE_MAX_SPEED);


gpio_set_mode(SHIFT_SER_PIN, GPIO_MODE_OUTPUT);
gpio_set_mode(SHIFT_RCLK_PIN, GPIO_MODE_OUTPUT);
gpio_set_mode(SHIFT_SRCLK_PIN, GPIO_MODE_OUTPUT);

seg_pins(SHIFT_SER_PIN, SHIFT_RCLK_PIN, SHIFT_SRCLK_PIN);
seg_clear_output();

NVIC_SetPriority (SysTick_IRQn, 0);
uint8_t x = 0;
for (;;) {
/* To prevent debounce, simply poll the button every 50ms or so. */
if (timer_expired(&debounce_timer, debounce_period, s_ticks)) {
if (!gpio_read(usrbtn) && !button_pressed) { /* Button input is pull-up. */
if (!gpio_read(STATEBTN_PIN) && !button_pressed) { /* Button input is pull-up. */
button_pressed = 1;
/* Capture first button press and re-do the action. */
if (is_idle) {
is_idle = 0;
fsm_action(&machine);
continue;
}

idle_timer = s_ticks + idle_period;
fsm_next(&machine);
} else if (gpio_read(usrbtn)) button_pressed = 0;
} else if (gpio_read(STATEBTN_PIN)) button_pressed = 0;
}
if (timer_expired(&idle_timer, idle_period, s_ticks) && !is_idle) {
is_idle = 1;
gpio_write(LED_RED_PIN, GPIO_OUTPUT_CLEAR);
gpio_write(LED_GREEN_PIN, GPIO_OUTPUT_CLEAR);
gpio_write(LED_BLUE_PIN, GPIO_OUTPUT_CLEAR);
seg_clear_output();
}
if (timer_expired(&idle_timer, idle_period, s_ticks)) {
gpio_write(PIN('C', 14), GPIO_OUTPUT_CLEAR);
gpio_write(PIN('C', 15), GPIO_OUTPUT_CLEAR);
gpio_write(PIN('F', 0), GPIO_OUTPUT_CLEAR);
if (timer_expired(&seg_timer, seg_period, s_ticks)) {
seg_clear_output();
seg_display_digit(x, 0);
++x; x = x % 10;
}
}

Expand Down
110 changes: 110 additions & 0 deletions src/seg/seg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* filename: seg.c
* date: 04.28.24
* author: Lucas Merritt/merrittlj
* description: Implementation for seg.h
*/
#include <stdint.h>
#include <math.h>

#include "seg.h"
#include "hal.h"


static uint16_t _display_num;
static uint8_t _decimal_loc;
static uint8_t _num_index;

static uint16_t _ser;
static uint16_t _rclk;
static uint16_t _srclk;

void seg_pins(uint16_t ser, uint16_t rclk, uint16_t srclk)
{
_ser = ser;
_rclk = rclk;
_srclk = srclk;
}

void seg_update_output()
{
gpio_write(_rclk, GPIO_OUTPUT_SET);
gpio_write(_rclk, GPIO_OUTPUT_CLEAR);
}

void seg_send_bit(uint8_t bit)
{
gpio_write(_ser, bit);
gpio_write(_srclk, GPIO_OUTPUT_SET);
gpio_write(_srclk, GPIO_OUTPUT_CLEAR);
gpio_write(_ser, GPIO_OUTPUT_CLEAR);
}

void seg_clear_output()
{
for (uint8_t i = 0; i < 8; ++i) seg_send_bit(0);
seg_update_output();
}

void seg_display_digit(uint8_t digit, uint8_t decimal_enabled)
{
/*
* Index correspondent to digit. Encodings are little-endian from A-G, with 0 = off and 1 = on.
* Ex: 0 is all segments but G on, 0x3F = 0b0111111, we send 0, then 1, then 1, etc.
*/
uint8_t decode_nums[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

/* We iterate in reverse order through the bits (ex: 0 = 0, then 1, then 1, etc.) because of how the shift register is buffered. */
seg_send_bit(decimal_enabled);
for (int8_t i = 6; i >= 0; --i) seg_send_bit((decode_nums[digit] >> i) & 1);

seg_update_output();
}

void seg_init(uint16_t num, uint8_t decimal)
{
set_display_num(num);
set_decimal_loc(decimal);
set_num_index(0);
}

void set_display_num(uint16_t num)
{
_display_num = num;
}

uint16_t get_display_num()
{
return _display_num;
}

void set_decimal_loc(uint8_t decimal)
{
_decimal_loc = decimal;
}

uint8_t get_decimal_loc()
{
return _decimal_loc;
}

void set_num_index(uint8_t index)
{
_num_index = index;
}

uint8_t get_num_index()
{
return _num_index;
}

void seg_display_next()
{
seg_clear_output();
/* TODO: set display to _num_index */
seg_display_digit((uint8_t)((_display_num / (uint16_t)(pow(10, 3 - _num_index))) % 10), _num_index == _decimal_loc);

++_num_index;
_num_index = _num_index % 4;
}

38 changes: 38 additions & 0 deletions src/seg/seg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* filename: seg.h
* date: 04.28.24
* author: Lucas Merritt/merrittlj
* description: Driver code for 4-digit seven segment display with 8-bit shift register.
*/

#ifndef SEG_H
#define SEG_H
#include <stdint.h>

#include "common.h"


extern void seg_pins(uint16_t ser, uint16_t rclk, uint16_t srclk); /* Set pins to use. */

extern void seg_update_output(); /* Clock RCLK. */
extern void seg_send_bit(uint8_t bit); /* Send a bit to the shift register. */
extern void seg_clear_output();
extern void seg_display_digit(uint8_t digit, uint8_t decimal_enabled);

extern void seg_init(uint16_t num, uint8_t decimal);

/* To display a multiple-digit number, we have to multiplex. Set a number to display and display each digit with a function. */
extern void set_display_num(uint16_t num);
extern uint16_t get_display_num();

/* Where the decimal is in _display_num, 0:3. */
extern void set_decimal_loc(uint8_t decimal);
extern uint8_t get_decimal_loc();

/* Current digit index in _display_num, 0:3. */
extern void set_num_index(uint8_t index);
extern uint8_t get_num_index();

extern void seg_display_next(); /* Display the next digit in the num. */

#endif
19 changes: 19 additions & 0 deletions src/seg/seg.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
LIB = $(MAKE_DIR)/libs/libseg.a
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))

$(LIB): $(OBJS)
@mkdir -p $(MAKE_DIR)/libs
@$(AR) cr $@ $^
@echo "Archive $(notdir $@)"

%.o: %.c
@$(CC) $(CFLAGS) -c $^ -o $@
@echo "CC $@"

clean:
@$(RM) -f $(LIB) $(OBJS)
@$(RM) -f *.expand
@echo "Remove objects: $(OBJS)"

.PHONY = clean
5 changes: 5 additions & 0 deletions src/state/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ void fsm_init(struct fsm *f, const struct state *table, uint8_t state)
f->table[f->cur].action();
}

void fsm_action(struct fsm *f)
{
f->table[f->cur].action();
}

void fsm_next(struct fsm *f)
{
f->table[f->cur].transition();
Expand Down
1 change: 1 addition & 0 deletions src/state/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct fsm {

/* Set appropriate variables in struct and start first state's action. */
extern void fsm_init(struct fsm *f, const struct state *table, uint8_t state);
extern void fsm_action(struct fsm *f); /* Run current state action. */
/* Transition out of current state, go to next state, start state action. */
extern void fsm_next(struct fsm *f);

Expand Down

0 comments on commit 898ff93

Please sign in to comment.