|
@@ -140,6 +140,12 @@ static uint32_t fleft;
|
|
|
// historical playback status information
|
|
// historical playback status information
|
|
|
static audio_status_code audio_last_status[8] = {ASC_NO_STATUS};
|
|
static audio_status_code audio_last_status[8] = {ASC_NO_STATUS};
|
|
|
|
|
|
|
|
|
|
+// volume information for targets
|
|
|
|
|
+static volatile uint8_t volumes[8] = {
|
|
|
|
|
+ DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL,
|
|
|
|
|
+ DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// mechanism for cleanly stopping DMA units
|
|
// mechanism for cleanly stopping DMA units
|
|
|
static volatile bool audio_stopping = false;
|
|
static volatile bool audio_stopping = false;
|
|
|
|
|
|
|
@@ -158,31 +164,34 @@ static uint8_t invert = 0; // biphase encode help: set if last wire bit was '1'
|
|
|
* output.
|
|
* output.
|
|
|
*/
|
|
*/
|
|
|
static void snd_encode(uint8_t* samples, uint16_t* wire_patterns, uint16_t len, uint8_t swap) {
|
|
static void snd_encode(uint8_t* samples, uint16_t* wire_patterns, uint16_t len, uint8_t swap) {
|
|
|
|
|
+ uint8_t vol = volumes[audio_owner & 7];
|
|
|
|
|
+ // limit maximum volume; with my DACs I've had persistent issues
|
|
|
|
|
+ // with signal clipping when sending data in the highest bit position
|
|
|
|
|
+ vol = vol >> 2;
|
|
|
|
|
+
|
|
|
uint16_t widx = 0;
|
|
uint16_t widx = 0;
|
|
|
for (uint16_t i = 0; i < len; i += 2) {
|
|
for (uint16_t i = 0; i < len; i += 2) {
|
|
|
uint32_t sample = 0;
|
|
uint32_t sample = 0;
|
|
|
uint8_t parity = 0;
|
|
uint8_t parity = 0;
|
|
|
if (samples != NULL) {
|
|
if (samples != NULL) {
|
|
|
|
|
+ int32_t rsamp;
|
|
|
if (swap) {
|
|
if (swap) {
|
|
|
- sample = samples[i + 1] + (samples[i] << 8);
|
|
|
|
|
|
|
+ rsamp = (int16_t)(samples[i + 1] + (samples[i] << 8));
|
|
|
} else {
|
|
} else {
|
|
|
- sample = samples[i] + (samples[i + 1] << 8);
|
|
|
|
|
|
|
+ rsamp = (int16_t)(samples[i] + (samples[i + 1] << 8));
|
|
|
}
|
|
}
|
|
|
- // determine parity, simplified to one lookup via an XOR
|
|
|
|
|
- parity = (sample >> 8) ^ sample;
|
|
|
|
|
|
|
+ // linear scale to requested audio value
|
|
|
|
|
+ rsamp *= vol;
|
|
|
|
|
+ // use 20 bits of value only, which allows ignoring the lowest 8
|
|
|
|
|
+ // bits during biphase conversion (after including sample shift)
|
|
|
|
|
+ sample = ((uint32_t)rsamp) & 0xFFFFF0;
|
|
|
|
|
+
|
|
|
|
|
+ // determine parity, simplified to one lookup via XOR
|
|
|
|
|
+ parity = ((sample >> 16) ^ (sample >> 8)) ^ sample;
|
|
|
parity = snd_parity[parity];
|
|
parity = snd_parity[parity];
|
|
|
|
|
|
|
|
- /*
|
|
|
|
|
- * Shift sample into the correct bit positions of the sub-frame. This
|
|
|
|
|
- * would normally be << 12, but with my DACs I've had persistent issues
|
|
|
|
|
- * with signal clipping when sending data in the highest bit position.
|
|
|
|
|
- */
|
|
|
|
|
- sample = sample << 11;
|
|
|
|
|
- if (sample & 0x04000000) {
|
|
|
|
|
- // handle two's complement
|
|
|
|
|
- sample |= 0x08000000;
|
|
|
|
|
- parity++;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // shift sample into the correct bit positions of the sub-frame.
|
|
|
|
|
+ sample = sample << 4;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// if needed, establish even parity with P bit
|
|
// if needed, establish even parity with P bit
|
|
@@ -202,7 +211,7 @@ static void snd_encode(uint8_t* samples, uint16_t* wire_patterns, uint16_t len,
|
|
|
if (invert) wp = ~wp;
|
|
if (invert) wp = ~wp;
|
|
|
invert = wp & 1;
|
|
invert = wp & 1;
|
|
|
wire_patterns[widx++] = wp;
|
|
wire_patterns[widx++] = wp;
|
|
|
- // next 8 bits (only high 4 have data)
|
|
|
|
|
|
|
+ // next 8 bits
|
|
|
wp = biphase[(uint8_t) (sample >> 8)];
|
|
wp = biphase[(uint8_t) (sample >> 8)];
|
|
|
if (invert) wp = ~wp;
|
|
if (invert) wp = ~wp;
|
|
|
invert = wp & 1;
|
|
invert = wp & 1;
|
|
@@ -544,4 +553,12 @@ audio_status_code audio_get_status_code(uint8_t id) {
|
|
|
return tmp;
|
|
return tmp;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+uint8_t audio_get_volume(uint8_t id) {
|
|
|
|
|
+ return volumes[id & 7];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void audio_set_volume(uint8_t id, uint8_t vol) {
|
|
|
|
|
+ volumes[id & 7] = vol;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#endif // ENABLE_AUDIO_OUTPUT
|
|
#endif // ENABLE_AUDIO_OUTPUT
|