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_flash
|
||||||
hardware_exception
|
hardware_exception
|
||||||
hardware_pwm
|
hardware_pwm
|
||||||
|
hardware_pio
|
||||||
pico_flash
|
pico_flash
|
||||||
pico_multicore
|
pico_multicore
|
||||||
hardware_adc
|
hardware_adc
|
||||||
|
|
|
@ -11,6 +11,10 @@ target_include_directories(raspikeyer PUBLIC
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pico_generate_pio_header(raspikeyer
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/tm1637.pio
|
||||||
|
)
|
||||||
|
|
||||||
target_sources(raspikeyer PRIVATE
|
target_sources(raspikeyer PRIVATE
|
||||||
raspikeyer.cpp
|
raspikeyer.cpp
|
||||||
settings.cpp
|
settings.cpp
|
||||||
|
@ -19,5 +23,6 @@ target_sources(raspikeyer PRIVATE
|
||||||
morse.cpp
|
morse.cpp
|
||||||
winkeyer.cpp
|
winkeyer.cpp
|
||||||
utils.cpp
|
utils.cpp
|
||||||
|
tm1637.cpp
|
||||||
usb_descriptors.c
|
usb_descriptors.c
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "bsp/board.h"
|
#include "bsp/board.h"
|
||||||
#include "hardware/adc.h"
|
#include "hardware/adc.h"
|
||||||
|
#include "pico/binary_info/code.h"
|
||||||
#include "pico/multicore.h"
|
#include "pico/multicore.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "pico/util/queue.h"
|
#include "pico/util/queue.h"
|
||||||
|
@ -10,10 +11,11 @@
|
||||||
|
|
||||||
#include "keyer.h"
|
#include "keyer.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include <config.h>
|
#include "tm1637.h"
|
||||||
#include "tusb_config.h"
|
#include "tusb_config.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "winkeyer.h"
|
#include "winkeyer.h"
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
extern const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
extern const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||||
extern const uint LEFT_PADDLE_PIN = 14;
|
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 CW_OUT_PIN = 17;
|
||||||
// extern const uint AUDIO_OUT_PIN = 16;
|
// extern const uint AUDIO_OUT_PIN = 16;
|
||||||
extern const uint ADC_PIN = 26;
|
extern const uint ADC_PIN = 26;
|
||||||
|
const uint DISPLAY_DIO_PIN = 20;
|
||||||
|
const uint DISPLAY_CLK_PIN = 21;
|
||||||
|
|
||||||
queue_t keyerQueue;
|
queue_t keyerQueue;
|
||||||
|
|
||||||
|
@ -120,6 +124,13 @@ int main()
|
||||||
|
|
||||||
WinKeyer winKeyer;
|
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) {
|
while (true) {
|
||||||
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
|
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
|
||||||
|
|
||||||
|
@ -129,6 +140,8 @@ int main()
|
||||||
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
||||||
printf("WPM has changed to: %d\n", currentWpm);
|
printf("WPM has changed to: %d\n", currentWpm);
|
||||||
lastWpm = currentWpm;
|
lastWpm = currentWpm;
|
||||||
|
display.displaySpeed(currentWpm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tud_task(); // Internal PICO purposes
|
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