diff --git a/src/main/aciodrv/kfca.c b/src/main/aciodrv/kfca.c index 0149d11..000656f 100644 --- a/src/main/aciodrv/kfca.c +++ b/src/main/aciodrv/kfca.c @@ -37,7 +37,12 @@ static bool aciodrv_kfca_watchdog_start(uint8_t node_id) */ } -static bool aciodrv_kfca_amp(uint8_t node_id) +bool aciodrv_kfca_amp( + uint8_t node_id, + uint8_t primary, + uint8_t headphone, + uint8_t unused, + uint8_t subwoofer) { struct ac_io_message msg; @@ -45,12 +50,10 @@ static bool aciodrv_kfca_amp(uint8_t node_id) msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL); msg.cmd.nbytes = 4; - // yes this sets the amp to 100% volume - // TODO: expose this to sdvxio instead at some point - msg.cmd.raw[0] = 0; - msg.cmd.raw[1] = 0; - msg.cmd.raw[2] = 0; - msg.cmd.raw[3] = 0; + msg.cmd.raw[0] = primary; + msg.cmd.raw[1] = headphone; + msg.cmd.raw[2] = unused; + msg.cmd.raw[3] = subwoofer; if (!aciodrv_send_and_recv( &msg, offsetof(struct ac_io_message, cmd.raw) + 1)) { @@ -69,7 +72,7 @@ bool aciodrv_kfca_init(uint8_t node_id) return false; } - if (!aciodrv_kfca_amp(node_id)) { + if (!aciodrv_kfca_amp(node_id, 0, 0, 0, 0)) { return false; } diff --git a/src/main/aciodrv/kfca.h b/src/main/aciodrv/kfca.h index 7722f42..9f146bd 100644 --- a/src/main/aciodrv/kfca.h +++ b/src/main/aciodrv/kfca.h @@ -30,4 +30,22 @@ bool aciodrv_kfca_poll( const struct ac_io_kfca_poll_out *pout, struct ac_io_kfca_poll_in *pin); +/** + * Set the KFCA digital amp level + * + * @param node_id Id of the node to query (0 based). + * @param primary primary volume (96-0) + * @param headphone headphone volume (96-0) + * @param unused unknown volume (96-0) (unused) + * @param subwoofer subwoofer volume (96-0) + * @return True on success, false on error. + * @note Note 96 (or 100?) is lowest volume level, 0 is highest + */ +bool aciodrv_kfca_amp( + uint8_t node_id, + uint8_t primary, + uint8_t headphone, + uint8_t unused, + uint8_t subwoofer); + #endif diff --git a/src/main/bemanitools/sdvxio.h b/src/main/bemanitools/sdvxio.h index 5778e0d..c3dfa83 100644 --- a/src/main/bemanitools/sdvxio.h +++ b/src/main/bemanitools/sdvxio.h @@ -98,4 +98,8 @@ uint16_t sdvx_io_get_input_gpio(uint8_t gpio_bank); uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no); +/* Sets the volume of the digital amps if possible */ + +bool sdvx_io_set_amp_volume(uint8_t primary, uint8_t headphone, uint8_t subwoofer); + #endif diff --git a/src/main/sdvxhook/kfca.c b/src/main/sdvxhook/kfca.c index f4d8894..69780ce 100644 --- a/src/main/sdvxhook/kfca.c +++ b/src/main/sdvxhook/kfca.c @@ -15,7 +15,7 @@ static void kfca_send_version(const struct ac_io_message *req); static void kfca_report_status(const struct ac_io_message *req, uint8_t status); -static void kfca_report_0128(const struct ac_io_message *req); +static void kfca_amp_control(const struct ac_io_message *req); static void kfca_poll(const struct ac_io_message *req); static void kfca_poll_thunk(void *ctx_ptr, struct ac_io_message *resp); @@ -60,7 +60,7 @@ void kfca_dispatch_request(const struct ac_io_message *req) case AC_IO_CMD_KFCA_AMP_CONTROL: log_misc("AC_IO_CMD_KFCA_AMP_CONTROL(%d)", req->addr); - kfca_report_0128(req); + kfca_amp_control(req); break; @@ -110,7 +110,7 @@ static void kfca_report_status(const struct ac_io_message *req, uint8_t status) ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0); } -static void kfca_report_0128(const struct ac_io_message *req) +static void kfca_amp_control(const struct ac_io_message *req) { struct ac_io_message resp; @@ -120,6 +120,12 @@ static void kfca_report_0128(const struct ac_io_message *req) resp.cmd.nbytes = req->cmd.nbytes; memcpy(resp.cmd.raw, req->cmd.raw, req->cmd.nbytes); + // bytes 0-4: main, headphone, unused, subwoofer + + if (!sdvx_io_set_amp_volume(req->cmd.raw[0], req->cmd.raw[1], req->cmd.raw[3])) { + log_warning("Unable to set amp volume?"); + } + ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0); } diff --git a/src/main/sdvxhook2/bi2a.c b/src/main/sdvxhook2/bi2a.c index cab5916..2aca18d 100644 --- a/src/main/sdvxhook2/bi2a.c +++ b/src/main/sdvxhook2/bi2a.c @@ -104,8 +104,12 @@ kfca_amp_control(struct ac_io_emu *emu, const struct ac_io_message *req) resp.cmd.nbytes = req->cmd.nbytes; memcpy(resp.cmd.raw, req->cmd.raw, req->cmd.nbytes); - // log_misc("sz %d: %d, %d, %d, %d", req->cmd.nbytes, req->cmd.raw[0], - // req->cmd.raw[1], req->cmd.raw[2], req->cmd.raw[3]); + // so SDVX5 sets the amps to 0 aka ALL MAX and uses Windows instead + // let's leave it to the individual sdvxio to set on init instead + // this way if any sdvxio's want to use Windows APIs for SDVX1-4 comapt. + // they can do so without doubly affecting the volume + + // sdvx_io_set_amp_volume(0, 0, 0, 0); ac_io_emu_response_push(emu, &resp, 0); } diff --git a/src/main/sdvxio-kfca/sdvxio-kfca.def b/src/main/sdvxio-kfca/sdvxio-kfca.def index e4783a2..8d6e632 100644 --- a/src/main/sdvxio-kfca/sdvxio-kfca.def +++ b/src/main/sdvxio-kfca/sdvxio-kfca.def @@ -11,3 +11,4 @@ EXPORTS sdvx_io_set_loggers sdvx_io_set_pwm_light sdvx_io_write_output + sdvx_io_set_amp_volume diff --git a/src/main/sdvxio-kfca/sdvxio.c b/src/main/sdvxio-kfca/sdvxio.c index 8f1d6f3..7c7533e 100644 --- a/src/main/sdvxio-kfca/sdvxio.c +++ b/src/main/sdvxio-kfca/sdvxio.c @@ -31,6 +31,7 @@ static uint16_t sdvx_io_analog[2]; static bool running; static bool processing_io; +static int16_t kfca_node_id; struct ac_io_kfca_poll_out pout_staging; struct ac_io_kfca_poll_out pout_ready; @@ -86,7 +87,7 @@ bool sdvx_io_init( uint8_t node_count = aciodrv_device_get_node_count(); log_info("Enumerated %d nodes", node_count); - int16_t kfca_node_id = -1; + kfca_node_id = -1; for (uint8_t i = 0; i < node_count; i++) { char product[4]; @@ -109,7 +110,11 @@ bool sdvx_io_init( if (kfca_node_id != -1) { log_warning("Using KFCA on node: %d", kfca_node_id); - aciodrv_kfca_init(kfca_node_id); + + if (!aciodrv_kfca_init(kfca_node_id)) { + log_warning("Unable to start KFCA on node: %d", kfca_node_id); + return false; + } running = true; log_warning("sdvxio-kfca now running"); @@ -155,7 +160,7 @@ bool sdvx_io_read_input(void) } processing_io = true; - if (!aciodrv_kfca_poll(0, &pout_ready, &pin)) { + if (!aciodrv_kfca_poll(kfca_node_id, &pout_ready, &pin)) { return false; } @@ -199,3 +204,19 @@ uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) } return sdvx_io_analog[spinner_no]; } + +bool sdvx_io_set_amp_volume( + uint8_t primary, + uint8_t headphone, + uint8_t subwoofer) +{ + if (!running) { + return false; + } + + if (!aciodrv_kfca_amp(kfca_node_id, primary, 96, headphone, subwoofer)) { + return false; + } + + return true; +} diff --git a/src/main/sdvxio/sdvxio.c b/src/main/sdvxio/sdvxio.c index 7aae8fe..3bf59a6 100644 --- a/src/main/sdvxio/sdvxio.c +++ b/src/main/sdvxio/sdvxio.c @@ -88,3 +88,8 @@ uint16_t sdvx_io_get_spinner_pos(uint8_t spinner_no) { return mapper_read_analog(spinner_no) * 4; } + +bool sdvx_io_set_amp_volume(uint8_t primary, uint8_t headphone, uint8_t subwoofer) +{ + return true; +} diff --git a/src/main/sdvxio/sdvxio.def b/src/main/sdvxio/sdvxio.def index e4783a2..8d6e632 100644 --- a/src/main/sdvxio/sdvxio.def +++ b/src/main/sdvxio/sdvxio.def @@ -11,3 +11,4 @@ EXPORTS sdvx_io_set_loggers sdvx_io_set_pwm_light sdvx_io_write_output + sdvx_io_set_amp_volume