diff --git a/software/main/CMakeLists.txt b/software/main/CMakeLists.txt index a2edbd5..3376faa 100644 --- a/software/main/CMakeLists.txt +++ b/software/main/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "src/main.cpp" "src/helper.cpp" "src/wav.cpp" "src/storage.cpp" "src/i2s.cpp" "src/bluetooth.cpp" "src/avrcp.cpp" "src/a2dp.cpp" "src/can.cpp" "src/twai.cpp" +idf_component_register(SRCS "src/main.cpp" "src/helper.cpp" "src/wav.cpp" "src/storage.cpp" "src/i2s.cpp" "src/bluetooth.cpp" "src/avrcp.cpp" "src/a2dp.cpp" "src/twai.cpp" INCLUDE_DIRS "include" EMBED_FILES "assets/connect.wav" "assets/disconnect.wav") diff --git a/software/main/include/can.h b/software/main/include/can.h deleted file mode 100644 index 34278b5..0000000 --- a/software/main/include/can.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -namespace can { - void init(); -} diff --git a/software/main/src/can.cpp b/software/main/src/can.cpp deleted file mode 100644 index f4bb27d..0000000 --- a/software/main/src/can.cpp +++ /dev/null @@ -1,451 +0,0 @@ -#include -#include -#include - -#include "esp_timer.h" -#include "freertos/FreeRTOS.h" -#include "freertos/portmacro.h" -#include "freertos/task.h" -#include "driver/spi_common.h" -#include "driver/spi_master.h" -#include "esp_err.h" -#include "esp_log.h" -#include "hal/spi_types.h" - -#include "can.h" -#include "can_data.h" -#include "avrcp.h" -#include "helper.h" - -#define CAN_TAG "APP_CAN" - -#define PIN_NUM_MOSI 23 -#define PIN_NUM_MISO 19 -#define PIN_NUM_CLK 18 -#define PIN_NUM_CS 5 - -#define MCP_SIDH 0 -#define MCP_SIDL 1 -#define MCP_EID8 2 -#define MCP_EID0 3 - -#define MCP_TXB_EXIDE_M 0x08 -#define MCP_DLC_MASK 0x0F -#define MCP_RTR_MASK 0x40 - -#define MCP_RXB_RX_STDEXT 0x00 -#define MCP_RXB_RX_MASK 0x60 -#define MCP_RXB_BUKT_MASK (1<<2) - -#define MCP_STAT_TXIF_MASK 0xA8 -#define MCP_STAT_TX0IF 0x08 -#define MCP_STAT_TX1IF 0x20 -#define MCP_STAT_TX2IF 0x80 -#define MCP_STAT_RXIF_MASK 0x03 - -// Instructions -#define MCP_WRITE 0x02 -#define MCP_READ 0x03 -#define MCP_BITMOD 0x05 -#define MCP_READ_RX0 0x90 -#define MCP_READ_RX1 0x94 -#define MCP_READ_STATUS 0xA0 -#define MCP_RESET 0xC0 - -// Registers -#define MCP_RXF0SIDH 0x00 -#define MCP_RXF1SIDH 0x04 -#define MCP_RXF2SIDH 0x08 -#define MCP_CANSTAT 0x0E -#define MCP_CANCTRL 0x0F -#define MCP_RXM0SIDH 0x20 -#define MCP_RXM1SIDH 0x24 -#define MCP_CNF3 0x28 -#define MCP_CNF2 0x29 -#define MCP_CNF1 0x2A -#define MCP_CANINTE 0x2B -#define MCP_CANINTF 0x2C -#define MCP_TXB0CTRL 0x30 -#define MCP_TXB1CTRL 0x40 -#define MCP_TXB2CTRL 0x50 -#define MCP_RXB0CTRL 0x60 -#define MCP_RXB1CTRL 0x70 - -// CANCTRL Register values -#define MODE_NORMAL 0x00 -#define MODE_SLEEP 0x20 -#define MODE_LISTENONLY 0x60 -#define MODE_CONFIG 0x80 -#define MODE_MASK 0xE0 - -// CANINTF Register bits -#define MCP_RX0IF 0x01 -#define MCP_RX1IF 0x02 -#define MCP_TX0IF 0x04 -#define MCP_TX1IF 0x08 -#define MCP_TX2IF 0x10 -#define MCP_WAKIF 0x40 - -static void send_cmd(spi_device_handle_t spi, const uint8_t cmd, bool keep_active = false) { - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8; - t.tx_buffer = &cmd; - if (keep_active) { - t.flags = SPI_TRANS_CS_KEEP_ACTIVE; - } - - esp_err_t ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); - -} - -static uint8_t read_register(spi_device_handle_t spi, const uint8_t address) { - // Acquire the bus in order to use SPI_TRANS_CS_KEEP_ACTIVE - esp_err_t ret = spi_device_acquire_bus(spi, portMAX_DELAY); - ESP_ERROR_CHECK(ret); - - // Send the command - { - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8*2; - uint8_t cmd[] = { MCP_READ, address }; - t.tx_buffer = cmd; - t.flags = SPI_TRANS_CS_KEEP_ACTIVE; - - ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); - } - - // Read the data - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8; - t.flags = SPI_TRANS_USE_RXDATA; - - ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); - - spi_device_release_bus(spi); - ESP_ERROR_CHECK(ret); - - return t.rx_data[0]; -} - -static void set_register(spi_device_handle_t spi, const uint8_t address, const uint8_t value) { - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8*3; - uint8_t cmd[] = { MCP_WRITE, address, value }; - t.tx_buffer = cmd; - - esp_err_t ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); -} - -static void modify_register(spi_device_handle_t spi, const uint8_t address, const uint8_t mask, const uint8_t data) { - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8*4; - uint8_t cmd[] = { MCP_BITMOD, address, mask, data }; - t.tx_buffer = cmd; - - esp_err_t ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); -} - -static bool request_new_mode(spi_device_handle_t spi, const uint8_t new_mode) { - unsigned long start = esp_timer_get_time() / 1000; - - for (;;) { - modify_register(spi, MCP_CANCTRL, MODE_MASK, new_mode); - uint8_t state = read_register(spi, MCP_CANSTAT); - if ((state & MODE_MASK) == new_mode) { - return true; - } else if ((esp_timer_get_time() / 1000 - start) > 200) { - ESP_LOGE(CAN_TAG, "Failed to set new mode"); - abort(); - } - } - -} - -static void set_CANCTRL_mode(spi_device_handle_t spi, uint8_t new_mode) { - ESP_LOGI(CAN_TAG, "set_CANCTRL_mode"); - if ((read_register(spi, MCP_CANSTAT) & MODE_MASK) == MODE_SLEEP && new_mode != MODE_SLEEP) { - ESP_LOGI(CAN_TAG, "if"); - uint8_t wake_int_enabled = (read_register(spi, MCP_CANINTE) & MCP_WAKIF); - if (!wake_int_enabled) { - modify_register(spi, MCP_CANINTE, MCP_WAKIF, MCP_WAKIF); - } - - modify_register(spi, MCP_CANINTF, MCP_WAKIF, MCP_WAKIF); - - request_new_mode(spi, MODE_LISTENONLY); - - if (!wake_int_enabled) { - modify_register(spi, MCP_CANINTE, MCP_WAKIF, 0); - } - } - - modify_register(spi, MCP_CANINTF, MCP_WAKIF, 0); - - request_new_mode(spi, new_mode); - ESP_LOGI(CAN_TAG, "done!"); -} - -static void config_rate(spi_device_handle_t spi) { - // This is for 16MHz, 125kBPS - set_register(spi, MCP_CNF1, 0x01); - set_register(spi, MCP_CNF2, 0xb1); - set_register(spi, MCP_CNF3, 0x05); -} - -static void init_CAN_buffers(spi_device_handle_t spi) { - uint8_t a1 = MCP_TXB0CTRL; - uint8_t a2 = MCP_TXB1CTRL; - uint8_t a3 = MCP_TXB2CTRL; - - for (int i = 0; i < 14; i++) { - set_register(spi, a1, 0); - set_register(spi, a2, 0); - set_register(spi, a3, 0); - - a1++; - a2++; - a3++; - } - - set_register(spi, MCP_RXB0CTRL, 0); - set_register(spi, MCP_RXB1CTRL, 0); -} - -static uint8_t read_status(spi_device_handle_t spi) { - // Acquire the bus in order to use SPI_TRANS_CS_KEEP_ACTIVE - esp_err_t ret = spi_device_acquire_bus(spi, portMAX_DELAY); - ESP_ERROR_CHECK(ret); - - send_cmd(spi, MCP_READ_STATUS, true); - - // Read the data - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8; - t.flags = SPI_TRANS_USE_RXDATA; - - ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); - - spi_device_release_bus(spi); - ESP_ERROR_CHECK(ret); - - return t.rx_data[0]; -} - -static void read_can_msg(spi_device_handle_t spi, uint8_t buffer_load_addr, uint16_t* id, uint8_t* len, uint8_t* buf) { - // Acquire the bus in order to use SPI_TRANS_CS_KEEP_ACTIVE - esp_err_t ret = spi_device_acquire_bus(spi, portMAX_DELAY); - ESP_ERROR_CHECK(ret); - - send_cmd(spi, buffer_load_addr, true); - - // Read id + length + data - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8*(5+8); - uint8_t data[5+8]; - t.rx_buffer = data; - - ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); - - *id = (data[MCP_SIDH] << 3) + (data[MCP_SIDL] >> 5); - - *len = data[4] & MCP_DLC_MASK; - - for (int i = 0; i < *len; ++i) { - buf[i] = data[5 + i]; - } - - // Make sure we release the bus - spi_device_release_bus(spi); - ESP_ERROR_CHECK(ret); -} - -static void write_id(spi_device_handle_t spi, const uint8_t addr, const uint16_t id) { - uint8_t cmd[6]; - cmd[0] = MCP_WRITE; - cmd[1] = addr; - cmd[MCP_SIDH+2] = id >> 3; - cmd[MCP_SIDL+2] = (id & 0x07) << 5; - cmd[MCP_EID0+2] = 0; - cmd[MCP_EID8+2] = 0; - - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8*6; - t.tx_buffer = cmd; - - esp_err_t ret = spi_device_polling_transmit(spi, &t); - ESP_ERROR_CHECK(ret); -} - -static bool available(uint8_t status) { - return status & MCP_STAT_RXIF_MASK; -} - -static uint8_t read_rx_tx_status(uint8_t status) { - uint8_t ret = (status & (MCP_STAT_TXIF_MASK | MCP_STAT_RXIF_MASK)); - - ret = (ret & MCP_STAT_TX0IF ? MCP_TX0IF : 0) | - (ret & MCP_STAT_TX1IF ? MCP_TX1IF : 0) | - (ret & MCP_STAT_TX2IF ? MCP_TX2IF : 0) | - (ret & MCP_STAT_RXIF_MASK); - - return ret; -} - -static void can_task(void* params) { - spi_device_handle_t spi = *(spi_device_handle_t*)params; - - for (;;) { - uint8_t status = read_status(spi); - - if (available(status)) { - uint8_t rx_tx_status = read_rx_tx_status(status); - - uint16_t id; - uint8_t len; - uint8_t buf[8]; - - if (rx_tx_status & MCP_RX0IF) { - read_can_msg(spi, MCP_READ_RX0, &id, &len, buf); - } else if (rx_tx_status & MCP_RX1IF) { - read_can_msg(spi, MCP_READ_RX0, &id, &len, buf); - } - - // @TODO Set this to false again once source detections works - static bool enabled = true; - switch (id) { - case BUTTONS_ID: - if (enabled) { - can::Buttons buttons = can::convert(buf, len); - - static MultiPurposeButton button_forward(avrcp::play_pause, avrcp::forward); - button_forward.update(buttons.forward); - - static MultiPurposeButton button_backward(nullptr, avrcp::backward); - button_backward.update(buttons.backward); - - static uint8_t scroll = 0; - if (scroll != buttons.scroll) { - int8_t diff = buttons.scroll - scroll; - - if (diff < 0) { - // 6 times to skip 6x5s = 30s - avrcp::seek_forward(); - avrcp::seek_forward(); - avrcp::seek_forward(); - avrcp::seek_forward(); - avrcp::seek_forward(); - avrcp::seek_forward(); - } else { - avrcp::seek_backward(); - avrcp::seek_backward(); - avrcp::seek_backward(); - avrcp::seek_backward(); - avrcp::seek_backward(); - avrcp::seek_backward(); - } - - scroll = buttons.scroll; - } - } - break; - - case VOLUME_ID: - if (enabled) { - can::Volume volume = can::convert(buf, len); - avrcp::set_volume(ceil(volume.volume * 4.2f)); - } - break; - - case RADIO_ID: - { - can::Radio radio = can::convert(buf, len); - enabled = (radio.source == can::Source::AUX2) && (radio.enabled); - } - break; - - default: - break; - } - } - } -} - -void can::init() { - ESP_LOGI(CAN_TAG, "Initializing can"); - - spi_bus_config_t buscfg = { - .mosi_io_num=PIN_NUM_MOSI, - .miso_io_num=PIN_NUM_MISO, - .sclk_io_num=PIN_NUM_CLK, - .quadwp_io_num=-1, - .quadhd_io_num=-1, - .max_transfer_sz=0 - }; - esp_err_t ret = spi_bus_initialize(VSPI_HOST, &buscfg, SPI_DMA_CH_AUTO); - ESP_ERROR_CHECK(ret); - - ESP_LOGI(CAN_TAG, "Adding device"); - spi_device_interface_config_t devcfg = { - .mode=0, - .clock_speed_hz=10*1000*1000, - .spics_io_num=PIN_NUM_CS, - .queue_size=7, - }; - spi_device_handle_t* spi = new spi_device_handle_t; - ret = spi_bus_add_device(VSPI_HOST, &devcfg, spi); - ESP_ERROR_CHECK(ret); - - ESP_LOGI(CAN_TAG, "Resetting MCP1525"); - send_cmd(*spi, MCP_RESET); - // @TODO Check if this is really needed - // Copied from other libary, here to give the MCP2515 time to wake up - vTaskDelay(5 / portTICK_PERIOD_MS); - - ESP_LOGI(CAN_TAG, "Enter config mode"); - set_CANCTRL_mode(*spi, MODE_CONFIG); - - ESP_LOGI(CAN_TAG, "Setting rate"); - config_rate(*spi); - - ESP_LOGI(CAN_TAG, "Init CAN buffers"); - init_CAN_buffers(*spi); - - ESP_LOGI(CAN_TAG, "Setting interrupt mode"); - set_register(*spi, MCP_CANINTE, MCP_RX0IF | MCP_RX1IF); - - ESP_LOGI(CAN_TAG, "Enable receive buffers"); - /* modify_register(*spi, MCP_RXB0CTRL, MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK); */ - modify_register(*spi, MCP_RXB0CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT); - modify_register(*spi, MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT); - - ESP_LOGI(CAN_TAG, "Init mask"); - write_id(*spi, MCP_RXM0SIDH, 0x3ff); - write_id(*spi, MCP_RXM1SIDH, 0x3ff); - - ESP_LOGI(CAN_TAG, "Init filter"); - write_id(*spi, MCP_RXF0SIDH, BUTTONS_ID); - /* write_id(*spi, MCP_RXF1SIDH, VOLUME_ID); */ - /* write_id(*spi, MCP_RXF2SIDH, RADIO_ID); */ - - ESP_LOGI(CAN_TAG, "Enter normal mode"); - set_CANCTRL_mode(*spi, MODE_NORMAL); - - ESP_LOGI(CAN_TAG, "Init done!"); - - xTaskCreatePinnedToCore(can_task, "CAN Task", 4096, spi, 0, nullptr, 0); -}