// copyright (C) 2006 Marcin Slonicki // copyright (C) 2007 Louis Frigon // Copyright (C) 2015 Allen Hill // SPDX-License-Identifier: GPL-3.0-or-later #include #include #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 0–99 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; }