display support added

This commit is contained in:
Martin Brodbeck 2024-03-04 12:05:48 +01:00
parent 12a7cb3d85
commit 64b6f6fbd8
6 changed files with 258 additions and 1 deletions

View file

@ -51,6 +51,7 @@ target_link_libraries(raspikeyer
hardware_flash
hardware_exception
hardware_pwm
hardware_pio
pico_flash
pico_multicore
hardware_adc

View file

@ -11,6 +11,10 @@ target_include_directories(raspikeyer PUBLIC
${CMAKE_CURRENT_BINARY_DIR}
)
pico_generate_pio_header(raspikeyer
${CMAKE_CURRENT_LIST_DIR}/tm1637.pio
)
target_sources(raspikeyer PRIVATE
raspikeyer.cpp
settings.cpp
@ -19,5 +23,6 @@ target_sources(raspikeyer PRIVATE
morse.cpp
winkeyer.cpp
utils.cpp
tm1637.cpp
usb_descriptors.c
)

View file

@ -3,6 +3,7 @@
#include "bsp/board.h"
#include "hardware/adc.h"
#include "pico/binary_info/code.h"
#include "pico/multicore.h"
#include "pico/stdlib.h"
#include "pico/util/queue.h"
@ -10,10 +11,11 @@
#include "keyer.h"
#include "settings.h"
#include <config.h>
#include "tm1637.h"
#include "tusb_config.h"
#include "utils.h"
#include "winkeyer.h"
#include <config.h>
extern const uint LED_PIN = PICO_DEFAULT_LED_PIN;
extern const uint LEFT_PADDLE_PIN = 14;
@ -22,6 +24,8 @@ extern const uint BUZZER_PIN = 18;
extern const uint CW_OUT_PIN = 17;
// extern const uint AUDIO_OUT_PIN = 16;
extern const uint ADC_PIN = 26;
const uint DISPLAY_DIO_PIN = 20;
const uint DISPLAY_CLK_PIN = 21;
queue_t keyerQueue;
@ -120,6 +124,13 @@ int main()
WinKeyer winKeyer;
pio_hw_t *pio = pio0;
TM1637 display {DISPLAY_DIO_PIN, DISPLAY_CLK_PIN, pio};
bi_decl(bi_1pin_with_name(DISPLAY_DIO_PIN, "[DIO] LED segments data pin"));
bi_decl(bi_1pin_with_name(DISPLAY_CLK_PIN, "[CLK] LED segments clock pin"));
display.displayIambicMode(settings.mode);
//display.displaySpeed(11);
while (true) {
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
@ -129,6 +140,8 @@ int main()
queue_add_blocking(&keyerQueue, &keyerQueueData);
printf("WPM has changed to: %d\n", currentWpm);
lastWpm = currentWpm;
display.displaySpeed(currentWpm);
}
tud_task(); // Internal PICO purposes

150
src/tm1637.cpp Normal file
View file

@ -0,0 +1,150 @@
#include "tm1637.h"
#include <array>
TM1637::TM1637(uint8_t dio, uint8_t clk, PIO pio) : m_pio(pio)
{
gpio_pull_up(dio);
gpio_pull_up(clk);
pio_gpio_init(pio, dio);
pio_gpio_init(pio, clk);
init(dio, clk);
}
void TM1637::init(uint8_t dio, uint8_t clk)
{
static constexpr size_t PULL_THRESHOLD = 32;
state_machine = static_cast<uint8_t>(pio_claim_unused_sm(m_pio, true));
auto offset = pio_add_program(m_pio, &tm1637_program);
state_machine_config = tm1637_program_get_default_config(offset);
sm_config_set_sideset_pins(&state_machine_config, clk);
uint32_t both_pins = (1 << clk) | (1 << dio);
pio_sm_set_pins_with_mask(m_pio, state_machine, both_pins, both_pins);
pio_sm_set_pindirs_with_mask(m_pio, state_machine, both_pins, both_pins);
sm_config_set_out_pins(&state_machine_config, dio, 1);
sm_config_set_set_pins(&state_machine_config, dio, 1);
sm_config_set_out_shift(&state_machine_config, true, false, PULL_THRESHOLD);
setClockDivider();
pio_sm_init(m_pio, state_machine, offset, &state_machine_config);
pio_sm_set_enabled(m_pio, state_machine, true);
}
void TM1637::setClockDivider()
{
static constexpr size_t FREQUENCY = 45'000;
static constexpr size_t MAX_DIVIDER_VALUE = 65'536;
uint32_t system_frequency = clock_get_hz(clk_sys);
float divider = static_cast<float>(system_frequency) / FREQUENCY;
if (divider > MAX_DIVIDER_VALUE) {
divider = MAX_DIVIDER_VALUE;
} else if (divider < 1) {
divider = 1;
}
sm_config_set_clkdiv(&state_machine_config, divider);
}
void TM1637::setColon([[maybe_unused]] bool on)
{
static constexpr size_t CONTROL_DISPLAY = 0x80'00;
// is_colon = true;
if (on)
m_currentSegments |= CONTROL_DISPLAY;
else
m_currentSegments &= ~CONTROL_DISPLAY;
send4Bytes(m_currentSegments);
}
void TM1637::send4Bytes(uint32_t data)
{
static constexpr size_t BIT_MASK = 0xFF'FF;
static constexpr size_t SHIFT_POSITIONS = 16;
static uint32_t data_1;
static uint32_t data_2;
data_1 = data & BIT_MASK;
data_2 = data >> SHIFT_POSITIONS;
pio_sm_put_blocking(m_pio, state_machine, (data_1 << (2 * BYTE_SIZE)) + (WRITE_ADDRESS << BYTE_SIZE) + WRITE_MODE);
pio_sm_put_blocking(m_pio, state_machine, data_2 << (2 * BYTE_SIZE));
pio_sm_put_blocking(m_pio, state_machine, BRIGHTNESS_BASE + m_brightness);
}
void TM1637::displayIambicMode(Mode iambic)
{
static constexpr size_t LEFT_BYTE_MASK = 0xFF'FF'00'00;
uint16_t segments {0};
switch (iambic) {
case Mode::IambicA:
segments = 0b0000'0000'0111'0111;
break;
case Mode::IambicB:
segments = 0b0000'0000'0111'1100;
break;
case Mode::Straight:
segments = 0b0000'0000'0110'1101;
break;
default:
segments = 0b0000'0000'0000'0000;
break;
}
m_currentSegments = (m_currentSegments & LEFT_BYTE_MASK) + segments;
if (m_isColon) {
setColon(m_isColon);
}
send4Bytes(m_currentSegments);
}
void TM1637::displaySpeed(uint8_t speed)
{
static constexpr std::array<uint8_t, 16> DIGIT_TO_SEGMENTS {
0x3F /* 0 */, 0x06 /* 1 */, 0x5B /* 2 */, 0x4F /* 3 */, 0x66 /* 4 */, 0x6D /* 5 */, 0x7D /* 6 */, 0x07 /* 7 */,
0x7F /* 8 */, 0x6F /* 9 */, 0x77 /* A */, 0x7C /* B */, 0x39 /* C */, 0x5E /* D */, 0x79 /* E */, 0x71 /* F */};
static constexpr size_t RIGHT_BYTE_MASK = 0x00'00'FF'FF;
uint8_t speed_orig = speed;
auto base = 10;
auto max_one_digit = base - 1;
uint32_t segments {0};
uint32_t temp_segments {0};
if (speed <= max_one_digit) {
segments = DIGIT_TO_SEGMENTS.at(speed);
}
else {
while (speed != 0) {
temp_segments = DIGIT_TO_SEGMENTS.at(speed % base);
speed /= base;
segments = temp_segments + (segments << BYTE_SIZE);
}
}
auto num_div = speed_orig / base;
if (num_div == 0) {
segments = segments << BYTE_SIZE;
}
m_currentSegments = (m_currentSegments & RIGHT_BYTE_MASK) + (segments << (2 * BYTE_SIZE));
if (m_isColon) {
setColon(m_isColon);
}
send4Bytes(m_currentSegments);
}

32
src/tm1637.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include <hardware/clocks.h>
#include <tm1637.pio.h>
#include "settings.h"
class TM1637
{
public:
TM1637(uint8_t dio, uint8_t clk, PIO pio);
void setColon(bool on);
void displayIambicMode(Mode iambic);
void displaySpeed(uint8_t speed);
private:
void init(uint8_t dio, uint8_t clk);
void setClockDivider();
void send4Bytes(uint32_t data);
PIO m_pio {};
uint8_t state_machine {};
pio_sm_config state_machine_config {};
uint8_t m_brightness {0};
uint32_t m_currentSegments {0};
bool m_isColon {false};
static constexpr uint8_t BYTE_SIZE = 8;
static constexpr uint8_t WRITE_MODE = 0x40;
static constexpr uint8_t WRITE_ADDRESS = 0xC0;
static constexpr uint8_t BRIGHTNESS_BASE = 0x88;
};

56
src/tm1637.pio Normal file
View file

@ -0,0 +1,56 @@
.program tm1637
.side_set 1 opt
set pins, 1 side 1
START:
pull block
START_COND:
set x, 7
set pins, 1 side 1 [7] ; set DIO (pins) and CLK (side) to 1. delay 8 PIO cycles
set pins, 0
set pins, 0 side 0
BIT_SHIFT_LOOP:
out pins, 1 side 0
nop side 1
jmp x-- BIT_SHIFT_LOOP side 0
ACK_COND:
set pins, 0 side 0
nop side 1
nop side 0 [1]
STOP_COND:
set pins, 0 side 1
set pins, 1 side 1
jmp !OSRE START_COND_SEND_DIGIT
jmp START
START_COND_SEND_DIGIT:
set pins, 1 side 1 [7]
set pins, 0
set pins, 0 side 0
SEND_CMD_AND_DATA:
set x, 7
BIT_SHIFT_LOOP_SEND_DIGIT:
out pins, 1 side 0
nop side 1
jmp x-- BIT_SHIFT_LOOP_SEND_DIGIT side 0
ACK_COND_SEND_DIGIT:
set pins, 0 side 0
set y, 1 side 1
nop side 0 [1]
jmp !OSRE SEND_CMD_AND_DATA
STOP_COND_SEND_DIGIT:
set pins, 0 side 1
set pins, 1 side 1
IN y, 32;
PUSH noblock;