display support added
This commit is contained in:
parent
12a7cb3d85
commit
64b6f6fbd8
6 changed files with 258 additions and 1 deletions
|
@ -51,6 +51,7 @@ target_link_libraries(raspikeyer
|
|||
hardware_flash
|
||||
hardware_exception
|
||||
hardware_pwm
|
||||
hardware_pio
|
||||
pico_flash
|
||||
pico_multicore
|
||||
hardware_adc
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
150
src/tm1637.cpp
Normal 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
32
src/tm1637.h
Normal 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
56
src/tm1637.pio
Normal 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;
|
Loading…
Reference in a new issue