Volume is now synced from car to phone
This commit is contained in:
parent
2f854ad54d
commit
d05f767827
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace avrcp {
|
||||
void init();
|
||||
bool is_playing();
|
||||
|
@ -7,4 +9,6 @@ namespace avrcp {
|
|||
void play_pause();
|
||||
void forward();
|
||||
void backward();
|
||||
|
||||
void set_volume(uint8_t volume);
|
||||
}
|
||||
|
|
|
@ -3,26 +3,11 @@
|
|||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BUTTONS_ID 0x21f
|
||||
#define RADIO_ID 0x165
|
||||
#define VOLUME_ID 0x1A5
|
||||
#define BUTTONS_ID 0x21f
|
||||
|
||||
namespace can {
|
||||
#pragma pack(1)
|
||||
struct Buttons {
|
||||
uint8_t _1 : 1;
|
||||
bool source : 1;
|
||||
bool volume_down : 1;
|
||||
bool volume_up : 1;
|
||||
uint8_t _2 : 2;
|
||||
bool backward : 1;
|
||||
bool forward : 1;
|
||||
|
||||
uint8_t scroll : 8;
|
||||
|
||||
uint8_t _3 : 8;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
enum Source : uint8_t {
|
||||
Bluetooth = 0b111,
|
||||
USB = 0b110,
|
||||
|
@ -58,4 +43,31 @@ namespace can {
|
|||
uint8_t _7 : 8;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
struct Buttons {
|
||||
uint8_t _1 : 1;
|
||||
bool source : 1;
|
||||
bool volume_down : 1;
|
||||
bool volume_up : 1;
|
||||
uint8_t _2 : 2;
|
||||
bool backward : 1;
|
||||
bool forward : 1;
|
||||
|
||||
uint8_t scroll : 8;
|
||||
|
||||
uint8_t _3 : 8;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
struct Volume {
|
||||
uint8_t _upper : 3;
|
||||
uint8_t volume : 5;
|
||||
|
||||
bool scrolled() {
|
||||
return _upper == 0b000;
|
||||
}
|
||||
};
|
||||
#pragma pack()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
|
||||
static esp_avrc_playback_stat_t playback_status = ESP_AVRC_PLAYBACK_STOPPED;
|
||||
|
||||
static uint8_t volume = 127;
|
||||
static _lock_t volume_lock;
|
||||
static bool volume_notify = false;
|
||||
|
||||
static void playback_changed() {
|
||||
if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap, ESP_AVRC_RN_PLAY_STATUS_CHANGE)) {
|
||||
esp_avrc_ct_send_register_notification_cmd(1, ESP_AVRC_RN_PLAY_STATUS_CHANGE, 0);
|
||||
|
@ -29,6 +33,13 @@ static void notify_handler(uint8_t event_id, esp_avrc_rn_param_t *event_paramete
|
|||
}
|
||||
}
|
||||
|
||||
static void set_volume_value(uint8_t v) {
|
||||
ESP_LOGI(AVRCP_TAG, "Setting internal volume value to %i", v);
|
||||
_lock_acquire(&volume_lock);
|
||||
volume = v;
|
||||
_lock_release(&volume_lock);
|
||||
}
|
||||
|
||||
static void rc_ct_callback(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) {
|
||||
ESP_LOGD(AVRCP_TAG, "%s event %d", __func__, event);
|
||||
|
||||
|
@ -71,6 +82,7 @@ static void rc_tg_callback(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t*
|
|||
case ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT:
|
||||
ESP_LOGI(AVRCP_TAG, "AVRC set absolute volume: %d%%", (int)param->set_abs_vol.volume * 100/ 0x7f);
|
||||
// The phone want to change the volume
|
||||
set_volume_value(param->set_abs_vol.volume);
|
||||
break;
|
||||
|
||||
case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT:
|
||||
|
@ -83,11 +95,14 @@ static void rc_tg_callback(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t*
|
|||
// However for now it is not really relevant as the volume control is doen by the car
|
||||
// In the future however it might be nice to sync the value on the phone, the esp and the car
|
||||
// This will require some sort of CAN bus access
|
||||
volume_notify = true;
|
||||
esp_avrc_rn_param_t rn_param;
|
||||
rn_param.volume = 127;
|
||||
rn_param.volume = volume;
|
||||
esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_INTERIM, &rn_param);
|
||||
} else if (param->reg_ntf.event_id == ESP_AVRC_RN_PLAY_POS_CHANGED) {
|
||||
ESP_LOGI(AVRCP_TAG, "We can change the play position?");
|
||||
} else {
|
||||
ESP_LOGW(AVRCP_TAG, "AVRC Volume Changes NOT Supported");
|
||||
ESP_LOGI(AVRCP_TAG, "Something else!");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -106,12 +121,23 @@ void avrcp::init() {
|
|||
|
||||
// Initialize AVRCP target
|
||||
if (esp_avrc_tg_init() == ESP_OK) {
|
||||
esp_avrc_tg_register_callback(rc_tg_callback);
|
||||
esp_avrc_rn_evt_cap_mask_t evt_set = {0};
|
||||
esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE);
|
||||
if (esp_avrc_tg_set_rn_evt_cap(&evt_set) != ESP_OK) {
|
||||
ESP_LOGE(AVRCP_TAG, "esp_avrc_tg_set_rn_evt_cap failed");
|
||||
{
|
||||
esp_avrc_tg_register_callback(rc_tg_callback);
|
||||
esp_avrc_rn_evt_cap_mask_t evt_set = {0};
|
||||
esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE);
|
||||
if (esp_avrc_tg_set_rn_evt_cap(&evt_set) != ESP_OK) {
|
||||
ESP_LOGE(AVRCP_TAG, "esp_avrc_tg_set_rn_evt_cap failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* { */
|
||||
/* esp_avrc_tg_register_callback(rc_tg_callback); */
|
||||
/* esp_avrc_rn_evt_cap_mask_t evt_set = {0}; */
|
||||
/* esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_PLAY_POS_CHANGED); */
|
||||
/* if (esp_avrc_tg_set_rn_evt_cap(&evt_set) != ESP_OK) { */
|
||||
/* ESP_LOGE(AVRCP_TAG, "esp_avrc_tg_set_rn_evt_cap failed"); */
|
||||
/* } */
|
||||
/* } */
|
||||
} else {
|
||||
ESP_LOGE(AVRCP_TAG, "esp_avrc_tg_init failed");
|
||||
}
|
||||
|
@ -150,3 +176,16 @@ void avrcp::backward() {
|
|||
|
||||
send_cmd(ESP_AVRC_PT_CMD_BACKWARD);
|
||||
}
|
||||
|
||||
void avrcp::set_volume(uint8_t v) {
|
||||
set_volume_value(v);
|
||||
|
||||
if (volume_notify) {
|
||||
ESP_LOGI(AVRCP_TAG, "Setting remote volume value to %i", v);
|
||||
esp_avrc_rn_param_t rn_param;
|
||||
rn_param.volume = volume;
|
||||
esp_avrc_tg_send_rn_rsp(ESP_AVRC_RN_VOLUME_CHANGE, ESP_AVRC_RN_RSP_CHANGED, &rn_param);
|
||||
volume_notify = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <cstdint>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
@ -364,32 +365,6 @@ static void read_can_msg(spi_device_handle_t spi, uint8_t buffer_load_addr, unsi
|
|||
ESP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
static void print_buttons(can::Buttons buttons) {
|
||||
/* ESP_LOGI(CAN_TAG, "BUTTONS"); */
|
||||
if (buttons.forward) {
|
||||
ESP_LOGI(CAN_TAG, "Button: F");
|
||||
}
|
||||
if (buttons.backward) {
|
||||
ESP_LOGI(CAN_TAG, "Button: B");
|
||||
}
|
||||
if (buttons.volume_up) {
|
||||
ESP_LOGI(CAN_TAG, "Button: U");
|
||||
}
|
||||
if (buttons.volume_down) {
|
||||
ESP_LOGI(CAN_TAG, "Button: D");
|
||||
}
|
||||
if (buttons.source) {
|
||||
ESP_LOGI(CAN_TAG, "Button: S");
|
||||
}
|
||||
|
||||
// Only print when scroll changes value
|
||||
static uint8_t scroll = 0;
|
||||
if (buttons.scroll != scroll) {
|
||||
scroll = buttons.scroll;
|
||||
ESP_LOGI(CAN_TAG, "Scroll: %i", buttons.scroll);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_radio(can::Radio radio) {
|
||||
ESP_LOGI(CAN_TAG, "RADIO");
|
||||
if (radio.enabled) {
|
||||
|
@ -444,33 +419,6 @@ static void print_radio(can::Radio radio) {
|
|||
}
|
||||
}
|
||||
|
||||
static void read_message(spi_device_handle_t spi) {
|
||||
uint8_t status = read_rx_tx_status(spi);
|
||||
|
||||
unsigned long id;
|
||||
uint8_t ext;
|
||||
uint8_t rtr_bit;
|
||||
uint8_t len;
|
||||
uint8_t buf[8];
|
||||
|
||||
if (status & MCP_RX0IF) {
|
||||
read_can_msg(spi, MCP_READ_RX0, &id, &ext, &rtr_bit, &len, buf);
|
||||
} else if (status & MCP_RX1IF) {
|
||||
read_can_msg(spi, MCP_READ_RX0, &id, &ext, &rtr_bit, &len, buf);
|
||||
}
|
||||
|
||||
// @TODO Only do this if we actually are on AUX2
|
||||
if (id == BUTTONS_ID) {
|
||||
static MultiPurposeButton button_forward(avrcp::play_pause, avrcp::forward);
|
||||
static MultiPurposeButton button_backward(nullptr, avrcp::backward);
|
||||
|
||||
can::Buttons buttons = *(can::Buttons*)buf;
|
||||
|
||||
button_forward.tick(buttons.forward);
|
||||
button_backward.tick(buttons.backward);
|
||||
}
|
||||
}
|
||||
|
||||
static void id_to_buf(const uint8_t ext, const unsigned long id, uint8_t* buf) {
|
||||
uint16_t canid = id & 0xFFFF;
|
||||
|
||||
|
@ -497,7 +445,39 @@ static void write_id(spi_device_handle_t spi, const uint8_t addr, const uint8_t
|
|||
set_registers(spi, addr, buf, 4);
|
||||
}
|
||||
|
||||
void can_task(void* params) {
|
||||
static void read_message(spi_device_handle_t spi) {
|
||||
uint8_t status = read_rx_tx_status(spi);
|
||||
|
||||
unsigned long id;
|
||||
uint8_t ext;
|
||||
uint8_t rtr_bit;
|
||||
uint8_t len;
|
||||
uint8_t buf[8];
|
||||
|
||||
if (status & MCP_RX0IF) {
|
||||
read_can_msg(spi, MCP_READ_RX0, &id, &ext, &rtr_bit, &len, buf);
|
||||
} else if (status & MCP_RX1IF) {
|
||||
read_can_msg(spi, MCP_READ_RX0, &id, &ext, &rtr_bit, &len, buf);
|
||||
}
|
||||
|
||||
// @TODO Only do this if we actually are on AUX2
|
||||
if (id == BUTTONS_ID) {
|
||||
static MultiPurposeButton button_forward(avrcp::play_pause, avrcp::forward);
|
||||
static MultiPurposeButton button_backward(nullptr, avrcp::backward);
|
||||
|
||||
can::Buttons buttons = *(can::Buttons*)buf;
|
||||
|
||||
button_forward.tick(buttons.forward);
|
||||
button_backward.tick(buttons.backward);
|
||||
} else if (id == VOLUME_ID) {
|
||||
can::Volume volume = *(can::Volume*)buf;
|
||||
if (volume.scrolled()) {
|
||||
avrcp::set_volume(ceil(volume.volume * 4.2f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void can_task(void* params) {
|
||||
spi_device_handle_t spi = *(spi_device_handle_t*)params;
|
||||
|
||||
for (;;) {
|
||||
|
@ -561,6 +541,7 @@ void can::init() {
|
|||
|
||||
ESP_LOGI(CAN_TAG, "Init filter");
|
||||
/* write_id(*spi, MCP_RXF0SIDH, 0, 0x165); */
|
||||
write_id(*spi, MCP_RXF1SIDH, 0, 0x1a5);
|
||||
write_id(*spi, MCP_RXF1SIDH, 0, 0x21f);
|
||||
|
||||
ESP_LOGI(CAN_TAG, "Enter normal mode");
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "esp_avrc_api.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
@ -18,21 +20,13 @@
|
|||
|
||||
void task(void*) {
|
||||
for (;;) {
|
||||
ESP_LOGI("TEST", "Pressing");
|
||||
|
||||
static uint8_t cmd = ESP_AVRC_PT_CMD_PLAY;
|
||||
esp_err_t ret = esp_avrc_ct_send_passthrough_cmd(0, cmd, ESP_AVRC_PT_CMD_STATE_PRESSED);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
ret = esp_avrc_ct_send_passthrough_cmd(1, cmd, ESP_AVRC_PT_CMD_STATE_RELEASED);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
|
||||
if (cmd == ESP_AVRC_PT_CMD_PLAY) {
|
||||
cmd = ESP_AVRC_PT_CMD_PAUSE;
|
||||
} else {
|
||||
cmd = ESP_AVRC_PT_CMD_PLAY;
|
||||
}
|
||||
static uint8_t volume = 0;
|
||||
volume = (volume + 1) % 31;
|
||||
|
||||
ESP_LOGI(APP_TAG, "Emulation radio with volume: %i", volume);
|
||||
avrcp::set_volume(ceil(volume * 4.2f));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +45,6 @@ extern "C" void app_main() {
|
|||
|
||||
/* xTaskCreate(task, "Task", 2048, nullptr, 0, nullptr); */
|
||||
|
||||
can::init();
|
||||
/* can::init(); */
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user