mirror of
https://github.com/justinian/edmfd_firmware.git
synced 2025-12-09 16:24:31 -08:00
Support feather board, move to broken out source
This commit is contained in:
@@ -22,7 +22,7 @@ include(pico_sdk_import.cmake)
|
|||||||
project(EDMFD C CXX)
|
project(EDMFD C CXX)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
set(PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS 3000)
|
set(PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS 3000)
|
||||||
pico_sdk_init()
|
pico_sdk_init()
|
||||||
@@ -35,18 +35,36 @@ add_compile_options(
|
|||||||
|
|
||||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||||
add_compile_options(-Wno-maybe-uninitialized)
|
add_compile_options(-Wno-maybe-uninitialized)
|
||||||
|
add_compile_options(-ffile-prefix-map=${CMAKE_SOURCE_DIR}/src/=)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include_directories(src)
|
||||||
|
|
||||||
|
add_library(logging STATIC
|
||||||
|
src/logging/log.cc
|
||||||
|
)
|
||||||
|
target_include_directories(logging PRIVATE src)
|
||||||
|
|
||||||
add_executable(edmfd)
|
add_executable(edmfd)
|
||||||
target_include_directories(edmfd PUBLIC src)
|
|
||||||
target_sources(edmfd PUBLIC
|
target_sources(edmfd PUBLIC
|
||||||
src/blink.cc
|
src/edmfd/blink.cc
|
||||||
src/hid.cc
|
src/edmfd/hid.cc
|
||||||
src/main.cc
|
src/edmfd/main.cc
|
||||||
src/usb_descriptors.cc
|
src/edmfd/mcp23017.cc
|
||||||
src/vendor.cc
|
src/edmfd/screen.cc
|
||||||
|
src/edmfd/usb_descriptors.cc
|
||||||
|
src/edmfd/vendor.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
pico_enable_stdio_usb(edmfd 1)
|
pico_enable_stdio_uart(edmfd 1)
|
||||||
|
pico_enable_stdio_uart(edmfd 0)
|
||||||
pico_add_extra_outputs(edmfd)
|
pico_add_extra_outputs(edmfd)
|
||||||
target_link_libraries(edmfd PUBLIC pico_stdlib pico_unique_id tinyusb_device tinyusb_board)
|
target_link_libraries(edmfd PUBLIC
|
||||||
|
logging
|
||||||
|
pico_stdlib
|
||||||
|
pico_stdio_uart
|
||||||
|
pico_unique_id
|
||||||
|
hardware_i2c
|
||||||
|
tinyusb_device
|
||||||
|
tinyusb_board
|
||||||
|
)
|
||||||
|
|||||||
163
src/edmfd/main.cc
Normal file
163
src/edmfd/main.cc
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/binary_info.h"
|
||||||
|
#include "hardware/i2c.h"
|
||||||
|
|
||||||
|
#include "tusb_config.h"
|
||||||
|
#include "bsp/board_api.h"
|
||||||
|
#include "tusb.h"
|
||||||
|
|
||||||
|
#include "logging/log.hh"
|
||||||
|
|
||||||
|
#include "blink.hh"
|
||||||
|
#include "hid.hh"
|
||||||
|
#include "mcp23017.hh"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// TinyUSB callbacks
|
||||||
|
void tud_mount_cb();
|
||||||
|
void tud_unmount_cb();
|
||||||
|
void tud_suspend_cb(bool);
|
||||||
|
void tud_resume_cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2C reserves some addresses for special purposes. We exclude these from the scan.
|
||||||
|
// These are any addresses of the form 000 0xxx or 111 1xxx
|
||||||
|
bool reserved_addr(uint8_t addr) {
|
||||||
|
return (addr & 0x78) == 0 || (addr & 0x78) == 0x78;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_i2c()
|
||||||
|
{
|
||||||
|
i2c_init(i2c_default, 100 * 1000);
|
||||||
|
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
|
||||||
|
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
|
||||||
|
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
|
||||||
|
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
|
||||||
|
|
||||||
|
// Make the I2C pins available to picotool
|
||||||
|
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_mcp(uint8_t addr, uint8_t reg, uint8_t value, const char *regname)
|
||||||
|
{
|
||||||
|
uint8_t txdata[2] = { reg, value };
|
||||||
|
int ret = i2c_write_blocking(i2c_default, addr, txdata, 2, false);
|
||||||
|
if (ret)
|
||||||
|
printf("Error %02x writing %02x to %02x:%s", ret, value, addr, regname);
|
||||||
|
else
|
||||||
|
printf("Wrote %02x to %02x:%s", value, addr, regname);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_mcp()
|
||||||
|
{
|
||||||
|
// A7 is button, B0 is LED
|
||||||
|
static constexpr uint8_t addr = 0x20;
|
||||||
|
if (write_mcp(addr, 0x00, 0xff, "IODIRA")) return;
|
||||||
|
if (write_mcp(addr, 0x10, 0x00, "IODIRB")) return;
|
||||||
|
if (write_mcp(addr, 0x02, 0xff, "GPINTENA")) return;
|
||||||
|
if (write_mcp(addr, 0x06, 0xff, "GPPUA")) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_scan()
|
||||||
|
{
|
||||||
|
printf("\nI2C Bus Scan\n");
|
||||||
|
printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
|
||||||
|
|
||||||
|
for (int addr = 0; addr < (1 << 7); ++addr) {
|
||||||
|
if (addr % 16 == 0) {
|
||||||
|
printf("%02x ", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a 1-byte dummy read from the probe address. If a slave
|
||||||
|
// acknowledges this address, the function returns the number of bytes
|
||||||
|
// transferred. If the address byte is ignored, the function returns
|
||||||
|
// -1.
|
||||||
|
|
||||||
|
// Skip over any reserved addresses.
|
||||||
|
int ret;
|
||||||
|
uint8_t rxdata;
|
||||||
|
if (reserved_addr(addr))
|
||||||
|
ret = PICO_ERROR_GENERIC;
|
||||||
|
else
|
||||||
|
ret = i2c_read_blocking(i2c_default, addr, &rxdata, 1, false);
|
||||||
|
|
||||||
|
printf(ret < 0 ? "." : "@");
|
||||||
|
printf(addr % 16 == 15 ? "\n" : " ");
|
||||||
|
}
|
||||||
|
printf("Done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
setup_default_uart();
|
||||||
|
stdio_init_all();
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||||
|
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||||
|
|
||||||
|
board_init();
|
||||||
|
log::info("board initialized");
|
||||||
|
|
||||||
|
tud_init(BOARD_TUD_RHPORT);
|
||||||
|
|
||||||
|
if (board_init_after_tusb)
|
||||||
|
board_init_after_tusb();
|
||||||
|
log::info("tinyusb initialized");
|
||||||
|
|
||||||
|
setup_i2c();
|
||||||
|
log::info("i2c initialized");
|
||||||
|
|
||||||
|
using mcp23017::reg;
|
||||||
|
mcp23017::gpios gpios {0x20};
|
||||||
|
|
||||||
|
uint8_t iocon = 0xba;
|
||||||
|
gpios.read(reg::iocona, &iocon);
|
||||||
|
gpios.read(reg::iodira, &iocon);
|
||||||
|
|
||||||
|
/*
|
||||||
|
gpios.write(reg::iodira, 0xff);
|
||||||
|
gpios.write(reg::gpintena, 0xff);
|
||||||
|
gpios.write(reg::gppua, 0xff);
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint32_t time = board_millis();
|
||||||
|
tud_task(); // tinyusb device task
|
||||||
|
blink::task(time);
|
||||||
|
hid::task(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Device callbacks
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
// Invoked when device is mounted
|
||||||
|
void tud_mount_cb() {
|
||||||
|
blink::set_pattern(blink::pattern::mounted);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when device is unmounted
|
||||||
|
void tud_umount_cb() {
|
||||||
|
blink::set_pattern(blink::pattern::not_mounted);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when usb bus is suspended
|
||||||
|
// argumen : if host allow us to perform remote wakeup
|
||||||
|
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
|
||||||
|
void tud_suspend_cb(bool) {
|
||||||
|
blink::set_pattern(blink::pattern::suspended);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked when usb bus is resumed
|
||||||
|
void tud_resume_cb() {
|
||||||
|
blink::pattern pat = tud_mounted() ? blink::pattern::mounted : blink::pattern::not_mounted;
|
||||||
|
blink::set_pattern(pat);
|
||||||
|
}
|
||||||
60
src/edmfd/mcp23017.cc
Normal file
60
src/edmfd/mcp23017.cc
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "hardware/i2c.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#include "logging/log.hh"
|
||||||
|
#include "mcp23017.hh"
|
||||||
|
|
||||||
|
namespace mcp23017 {
|
||||||
|
|
||||||
|
static const char * regnames[] = {
|
||||||
|
"iodira", "iodirb",
|
||||||
|
"ipola", "ipolb",
|
||||||
|
"gpintena", "gpintenb",
|
||||||
|
"defvala", "defvalb",
|
||||||
|
"intcona", "intconb",
|
||||||
|
"iocona", "ioconb",
|
||||||
|
"gppua", "gppub",
|
||||||
|
"intfa", "intfb",
|
||||||
|
"intcapa", "intcapb",
|
||||||
|
"gpioa", "gpiob",
|
||||||
|
"olata", "olatb",
|
||||||
|
};
|
||||||
|
|
||||||
|
gpios::gpios(uint8_t addr) :
|
||||||
|
m_addr {addr}
|
||||||
|
{}
|
||||||
|
|
||||||
|
int
|
||||||
|
gpios::read(reg r, uint8_t *value)
|
||||||
|
{
|
||||||
|
uint8_t txdata = uint8_t(r);
|
||||||
|
int ret = i2c_write_burst_blocking(i2c_default, m_addr, &txdata, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
log::error("writing read address {%02x:%s}: %d", m_addr, regnames[uint8_t(r)], ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = i2c_read_blocking(i2c_default, m_addr, value, 1, false);
|
||||||
|
if (ret < 0) {
|
||||||
|
log::error("reading {%02x:%s}: %d", m_addr, regnames[uint8_t(r)], ret);
|
||||||
|
} else {
|
||||||
|
log::info("read {%02x:%s}: 0x%02x", m_addr, regnames[uint8_t(r)], *value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
gpios::write(reg r, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t txdata[2] = { uint8_t(r), value };
|
||||||
|
int ret = i2c_write_blocking(i2c_default, m_addr, txdata, sizeof(txdata), false);
|
||||||
|
if (ret != PICO_OK) {
|
||||||
|
log::error("writing {%02x:%s}: %d", m_addr, regnames[uint8_t(r)], ret);
|
||||||
|
} else {
|
||||||
|
log::info("wrote {%02x:%s}: 0x%02x", m_addr, regnames[uint8_t(r)], value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mcp23017
|
||||||
31
src/edmfd/mcp23017.hh
Normal file
31
src/edmfd/mcp23017.hh
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace mcp23017 {
|
||||||
|
|
||||||
|
enum class reg : uint8_t {
|
||||||
|
iodira, iodirb,
|
||||||
|
ipola, ipolb,
|
||||||
|
gpintena, gpintenb,
|
||||||
|
defvala, defvalb,
|
||||||
|
intcona, intconb,
|
||||||
|
iocona, ioconb,
|
||||||
|
gppua, gppub,
|
||||||
|
intfa, intfb,
|
||||||
|
intcapa, intcapb,
|
||||||
|
gpioa, gpiob,
|
||||||
|
olata, olatb,
|
||||||
|
};
|
||||||
|
|
||||||
|
class gpios
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gpios(uint8_t addr);
|
||||||
|
|
||||||
|
int read(reg r, uint8_t *value);
|
||||||
|
int write(reg r, uint8_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mcp23017
|
||||||
9
src/edmfd/proto.cc
Normal file
9
src/edmfd/proto.cc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "proto.hh"
|
||||||
|
|
||||||
|
namespace proto {
|
||||||
|
|
||||||
|
void parse(const uint8_t *buffer, unsigned len) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace proto
|
||||||
8
src/edmfd/proto.hh
Normal file
8
src/edmfd/proto.hh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace proto {
|
||||||
|
|
||||||
|
void parse(const uint8_t *buffer, unsigned len);
|
||||||
|
|
||||||
|
} // namespace proto
|
||||||
14
src/edmfd/screen.cc
Normal file
14
src/edmfd/screen.cc
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include "screen.hh"
|
||||||
|
|
||||||
|
namespace screen {
|
||||||
|
|
||||||
|
palette g_palette = {0};
|
||||||
|
|
||||||
|
void set_color(unsigned index, color_t color) {
|
||||||
|
if (index >= num_colors) return;
|
||||||
|
g_palette[index] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const palette & get_colors() { return g_palette; }
|
||||||
|
|
||||||
|
} // namespace screen
|
||||||
15
src/edmfd/screen.hh
Normal file
15
src/edmfd/screen.hh
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <array>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace screen {
|
||||||
|
|
||||||
|
inline constexpr unsigned color_bits = 4;
|
||||||
|
inline constexpr unsigned num_colors = 1 << color_bits;
|
||||||
|
using color_t = uint16_t;
|
||||||
|
using palette = std::array<color_t, num_colors>;
|
||||||
|
|
||||||
|
void set_color(unsigned index, color_t color);
|
||||||
|
const palette & get_colors();
|
||||||
|
|
||||||
|
} // namepsace screen
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
* [MSB] HID | MSC | CDC [LSB]
|
* [MSB] HID | MSC | CDC [LSB]
|
||||||
*/
|
*/
|
||||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||||
#define USB_PID (0x0000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
#define USB_PID (0x0200 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||||
|
|
||||||
#define USB_VID 0x4a33 // J3 in ascii
|
#define USB_VID 0x4a33 // J3 in ascii
|
||||||
@@ -123,12 +123,12 @@ uint8_t const desc_configuration[config_total_len] = {
|
|||||||
// Config number, interface count, string index, total length, attribute, power in mA
|
// Config number, interface count, string index, total length, attribute, power in mA
|
||||||
TUD_CONFIG_DESCRIPTOR(1, uint8_t(interface::_count), 0, config_total_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
TUD_CONFIG_DESCRIPTOR(1, uint8_t(interface::_count), 0, config_total_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||||
|
|
||||||
// Interface number, string index, EP Out & IN address, EP size
|
|
||||||
TUD_VENDOR_DESCRIPTOR(uint8_t(interface::vendor), uint8_t(strings::interface), uint8_t(endpoint::vendor_out), uint8_t(endpoint::vendor_in), 64),
|
|
||||||
|
|
||||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
||||||
TUD_HID_DESCRIPTOR(uint8_t(interface::HID), 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), uint8_t(endpoint::HID), CFG_TUD_HID_EP_BUFSIZE, 5),
|
TUD_HID_DESCRIPTOR(uint8_t(interface::HID), 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), uint8_t(endpoint::HID), CFG_TUD_HID_EP_BUFSIZE, 5),
|
||||||
|
|
||||||
|
// Interface number, string index, EP Out & IN address, EP size
|
||||||
|
TUD_VENDOR_DESCRIPTOR(uint8_t(interface::vendor), uint8_t(strings::interface), uint8_t(endpoint::vendor_out), uint8_t(endpoint::vendor_in), 64),
|
||||||
|
|
||||||
// CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
// CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||||
//TUD_CDC_DESCRIPTOR(uint8_t(interface::CDC), 4, uint8_t(endpoint::CDCnotify), 8, uint8_t(endpoint::CDCout), uint8_t(endpoint::CDCin), 64)
|
//TUD_CDC_DESCRIPTOR(uint8_t(interface::CDC), 4, uint8_t(endpoint::CDCnotify), 8, uint8_t(endpoint::CDCout), uint8_t(endpoint::CDCin), 64)
|
||||||
};
|
};
|
||||||
@@ -14,8 +14,8 @@ enum class strings : uint8_t {
|
|||||||
_count
|
_count
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class interface : uint8_t { vendor, HID, _count };
|
enum class interface : uint8_t { HID, vendor, _count };
|
||||||
enum class endpoint : uint8_t { HID = 0x81, vendor_out = 0x02, vendor_in = 0x82 };
|
enum class endpoint : uint8_t { HID = 0x81, vendor_out = 0x02, vendor_in = 0x83 };
|
||||||
|
|
||||||
enum class vendor_req : uint8_t {
|
enum class vendor_req : uint8_t {
|
||||||
microsoft = 1,
|
microsoft = 1,
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "class/vendor/vendor_device.h"
|
#include "class/vendor/vendor_device.h"
|
||||||
|
|
||||||
#include "blink.hh"
|
#include "blink.hh"
|
||||||
|
#include "screen.hh"
|
||||||
#include "usb_descriptors.hh"
|
#include "usb_descriptors.hh"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -30,11 +31,34 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
|
|||||||
|
|
||||||
// Invoked when received new data
|
// Invoked when received new data
|
||||||
void tud_vendor_rx_cb(uint8_t, uint8_t const* buffer, uint16_t bufsize) {
|
void tud_vendor_rx_cb(uint8_t, uint8_t const* buffer, uint16_t bufsize) {
|
||||||
tud_vendor_write(buffer, bufsize);
|
if (!bufsize) return;
|
||||||
|
|
||||||
|
|
||||||
|
switch (buffer[0]) {
|
||||||
|
case 0x02: { // set colors
|
||||||
|
for (unsigned i = 1; i < bufsize-3u; i += 3u) {
|
||||||
|
unsigned index = buffer[i];
|
||||||
|
screen::color_t color =
|
||||||
|
*reinterpret_cast<const screen::color_t*>(&buffer[i+1]);
|
||||||
|
screen::set_color(index, color);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x03: {// get colors
|
||||||
|
const screen::palette &pal = screen::get_colors();
|
||||||
|
tud_vendor_write(&pal, sizeof(pal));
|
||||||
|
tud_vendor_write_flush();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
tud_vendor_read_flush();
|
tud_vendor_read_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoked when last rx (tx?) transfer finished
|
// Invoked when last rx (tx?) transfer finished
|
||||||
void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
|
void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
|
||||||
tud_vendor_write_flush();
|
|
||||||
}
|
}
|
||||||
26
src/logging/log.cc
Normal file
26
src/logging/log.cc
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "log.hh"
|
||||||
|
|
||||||
|
namespace logging {
|
||||||
|
namespace {
|
||||||
|
const char *level_strings[] = {
|
||||||
|
nullptr,
|
||||||
|
"\e[90mTRACE\e[0m",
|
||||||
|
"\e[94mDEBUG\e[0m",
|
||||||
|
"\e[92mINFO\e[0m",
|
||||||
|
"\e[93mWARN\e[0m",
|
||||||
|
"\e[91mERROR\e[0m",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void log(level lv, const format &fmt, ...) {
|
||||||
|
printf("%20s:%-3d: %5s ", fmt.loc.file_name(), fmt.loc.line(), level_strings[int(lv)]);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vprintf(fmt.fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace log
|
||||||
26
src/logging/log.hh
Normal file
26
src/logging/log.hh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <source_location>
|
||||||
|
|
||||||
|
namespace logging {
|
||||||
|
|
||||||
|
enum class level { none, trace, debug, info, warn, error };
|
||||||
|
|
||||||
|
class format
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
format() = default;
|
||||||
|
format(const char *fmt, const std::source_location &loc = std::source_location::current()) :
|
||||||
|
fmt {fmt}, loc {loc} {}
|
||||||
|
const char *fmt;
|
||||||
|
const std::source_location &loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
void log(level lv, const format &fmt, ...);
|
||||||
|
inline void trace(const format &fmt, auto&&... args) { log(level::trace, fmt, args...); }
|
||||||
|
inline void debug(const format &fmt, auto&&... args) { log(level::debug, fmt, args...); }
|
||||||
|
inline void info (const format &fmt, auto&&... args) { log(level::info, fmt, args...); }
|
||||||
|
inline void warn (const format &fmt, auto&&... args) { log(level::warn, fmt, args...); }
|
||||||
|
inline void error(const format &fmt, auto&&... args) { log(level::error, fmt, args...); }
|
||||||
|
|
||||||
|
} // namespace logging
|
||||||
|
namespace log = logging;
|
||||||
88
src/main.cc
88
src/main.cc
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tusb_config.h"
|
|
||||||
#include "bsp/board_api.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
|
|
||||||
#include "blink.hh"
|
|
||||||
#include "hid.hh"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
// TinyUSB callbacks
|
|
||||||
void tud_mount_cb();
|
|
||||||
void tud_unmount_cb();
|
|
||||||
void tud_suspend_cb(bool);
|
|
||||||
void tud_resume_cb();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
board_init();
|
|
||||||
|
|
||||||
tud_init(BOARD_TUD_RHPORT);
|
|
||||||
|
|
||||||
if (board_init_after_tusb)
|
|
||||||
board_init_after_tusb();
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
uint32_t time = board_millis();
|
|
||||||
tud_task(); // tinyusb device task
|
|
||||||
blink::task(time);
|
|
||||||
hid::task(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
// Device callbacks
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// Invoked when device is mounted
|
|
||||||
void tud_mount_cb() {
|
|
||||||
blink::set_pattern(blink::pattern::mounted);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked when device is unmounted
|
|
||||||
void tud_umount_cb() {
|
|
||||||
blink::set_pattern(blink::pattern::not_mounted);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked when usb bus is suspended
|
|
||||||
// argumen : if host allow us to perform remote wakeup
|
|
||||||
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
|
|
||||||
void tud_suspend_cb(bool) {
|
|
||||||
blink::set_pattern(blink::pattern::suspended);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked when usb bus is resumed
|
|
||||||
void tud_resume_cb() {
|
|
||||||
blink::pattern pat = tud_mounted() ? blink::pattern::mounted : blink::pattern::not_mounted;
|
|
||||||
blink::set_pattern(pat);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user