Files
Toyota-AVC-LAN/src/avclan/cdchanger.c
T
Allen Hill 02b370dd06 Port Queue to C++
Some knock-on changes to keep a simple design:
- Bake the data array into AVCLAN_frame_t
- Bundle the response/reaction with AVCLAN_frame_t
    - (Needed to maintain correct/simple ownership semantics with the
      cache and outgoing/incoming queues)
- Switch status frame update ticks to use a regular
  cache-originating/owned frame
2026-06-25 14:28:19 -07:00

125 lines
3.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// copyright (C) 2006 Marcin Slonicki <marcin@softservice.com.pl>
// copyright (C) 2007 Louis Frigon
// Copyright (C) 2015 Allen Hill <allenofthehills@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <stdint.h>
#include <string.h>
#include "avclan_phy.h"
#include "cdchanger.h"
#include "mediacontrol.h"
#include "statustimer.h"
AVCLAN_CD_Status_t cd_status;
static cd_modes CD_Mode;
// Sets CD_mode to play and resets timer count (so that the next interrupt is in
// 1 sec)
void AVCLAN_startPlaying() {
static bool havePlayed = false;
if (havePlayed)
AVCLAN_mediaFunction(MEDIA_PLAY_PAUSE);
havePlayed |= true;
CD_Mode = stPlay;
statustimer_reset();
}
// Sets CD_mode to play and resets timer count (so that the next interrupt is in
// 1 sec)
void AVCLAN_stopPlaying() {
statustimer_disable();
CD_Mode = stStop;
AVCLAN_mediaFunction(MEDIA_PLAY_PAUSE);
}
/* Pack a 099 count into 2-digit BCD. Values >99 (sentinels such as 0xFF /
0x7F meaning "no time") pass through unchanged so they survive the wire
round-trip. */
static uint8_t toBCD(uint8_t x) {
if (x > 99)
return x;
return (uint8_t)(((x / 10) << 4) | (x % 10));
}
// Serialize cd_status into the wire format. The struct layout mirrors the wire
// format byte-for-byte, except for track/mins/secs, which need converted from
// decimal to BCD
void serializeCDStatus(uint8_t *dst) {
memcpy(dst, &cd_status, sizeof(cd_status));
dst[3] = toBCD(cd_status.track);
dst[4] = toBCD(cd_status.mins);
dst[5] = toBCD(cd_status.secs);
}
bool AVCLAN_isPlaying() { return (CD_Mode == stPlay); }
void AVCLAN_incrementTime() {
// Sentinel values (>99) mean "no time"; leave them alone until setTime()
// replaces them with a real count.
if (cd_status.secs > 99)
return;
if (cd_status.secs == 59) {
cd_status.secs = 0;
if (cd_status.mins == 99)
cd_status.mins = 0;
else
cd_status.mins++;
} else
cd_status.secs++;
}
void AVCLAN_setTime(uint8_t mins, uint8_t secs) {
cd_status.mins = mins;
cd_status.secs = secs;
}
// Used for changed status messages
void AVCLAN_generateStatus(AVCLAN_frame_t *status, bool is_unicast,
devices to) {
status->is_unicast = is_unicast;
status->controller_addr = DEVICE_ADDR;
status->peripheral_addr = (is_unicast) ? HU_ADDR : 0x1FF;
status->control = 0xF;
status->length = sizeof(AVCLAN_CD_Status_t) + ((is_unicast) ? 4 : 3);
uint8_t *data = status->data;
if (is_unicast)
*data++ = 0x00;
*data++ = dev_CD_CHANGER;
*data++ = to;
*data++ = Status_Report;
serializeCDStatus(data);
}
void AVCLAN_normalizeState() {
// if (cd_status.state != cd_PLAYBACK) {
if (cd_status.mins > 99)
cd_status.mins = 0;
if (cd_status.secs > 99)
cd_status.secs = 0;
cd_status.state = cd_PLAYBACK;
cd_status.flags &= (uint8_t)~(cd_DISK_SCAN | cd_SCAN);
cd_status.flags2 = 0x80;
// }
}
void AVCLAN_init() {
AVCLAN_busInit();
mediacontrol_init();
statustimer_init();
cd_status.cds = cd_CD1;
cd_status.disc = 1;
cd_status.state = cd_SEEKING | cd_SEEKING_TRACK;
cd_status.flags = 0;
cd_status.flags2 = 0xC0;
cd_status.track = 1;
cd_status.mins = 0xFF;
cd_status.secs = 0x7F;
CD_Mode = stStop;
}