mirror of
https://github.com/halleysfifthinc/AVCLAN-Mockingboard.git
synced 2026-08-11 16:32:52 +00:00
02b370dd06
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
125 lines
3.2 KiB
C
125 lines
3.2 KiB
C
// 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 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;
|
||
}
|