comparison pico_pcm.c @ 2436:f50b9ed42ebd

Fix polarity of pico ADPCM busy flag
author Michael Pavone <pavone@retrodev.com>
date Sat, 10 Feb 2024 17:28:05 -0800
parents b8d894f7f9dc
children e8eba0cd5444
comparison
equal deleted inserted replaced
2435:b8d894f7f9dc 2436:f50b9ed42ebd
1 #include "pico_pcm.h" 1 #include "pico_pcm.h"
2 #include "backend.h" 2 #include "backend.h"
3 3
4 #define PCM_RESET 0x8000 4 #define PCM_RESET 0x8000
5 #define PCM_BUSY PCM_RESET
5 #define PCM_INT_EN 0x4000 6 #define PCM_INT_EN 0x4000
6 #define PCM_ENABLED 0x0800 7 #define PCM_ENABLED 0x0800
7 #define PCM_FILTER 0x00C0 8 #define PCM_FILTER 0x00C0
8 #define PCM_VOLUME 0x0007 9 #define PCM_VOLUME 0x0007
9 10
15 pcm->output = 0; 16 pcm->output = 0;
16 pcm->nibble_store = 0; 17 pcm->nibble_store = 0;
17 pcm->counter = 0; 18 pcm->counter = 0;
18 pcm->samples = 0; 19 pcm->samples = 0;
19 pcm->rate = 0; 20 pcm->rate = 0;
20 pcm->ctrl &= 0x7FFF; 21 pcm->ctrl |= PCM_BUSY;
21 } 22 }
22 23
23 void pico_pcm_init(pico_pcm *pcm, uint32_t master_clock, uint32_t divider) 24 void pico_pcm_init(pico_pcm *pcm, uint32_t master_clock, uint32_t divider)
24 { 25 {
25 pcm->audio = render_audio_source("PICO ADPCM", master_clock, divider * 4, 1); 26 pcm->audio = render_audio_source("PICO ADPCM", master_clock, divider * 4, 1);
99 if (pcm->scope) { 100 if (pcm->scope) {
100 scope_add_sample(pcm->scope, pcm->scope_channel, (pcm->output >> shift) * 32, 0); 101 scope_add_sample(pcm->scope, pcm->scope_channel, (pcm->output >> shift) * 32, 0);
101 } 102 }
102 #endif 103 #endif
103 render_put_mono_sample(pcm->audio, (pcm->output >> shift) * 32); 104 render_put_mono_sample(pcm->audio, (pcm->output >> shift) * 32);
104 if (pcm->ctrl & PCM_RESET) {
105 //Anpanman Pico: Waku Waku Pan Koujou seems to expect the BUSY/RESET flag
106 //to be set for a while after reset
107 if (pcm->counter) {
108 pcm->counter--;
109 continue;
110 } else {
111 pcm->ctrl &= ~PCM_RESET;
112 }
113 }
114 /* 105 /*
115 Unclear what this bit is actually supposed to do 106 Unclear what this bit is actually supposed to do
116 But some games expect ADPCM to work with it cleared 107 But some games expect ADPCM to work with it cleared
117 Anpanman Pico: Waku Waku Pan Koujou sets the ctrl reg to $6040 108 Anpanman Pico: Waku Waku Pan Koujou sets the ctrl reg to $6040
118 if (!(pcm->ctrl & PCM_ENABLED)) { 109 if (!(pcm->ctrl & PCM_ENABLED)) {
141 //printf("Sample %d, old_state %d, new_state %d, output %d\n", sample, old_state, pcm->adpcm_state, pcm->output); 132 //printf("Sample %d, old_state %d, new_state %d, output %d\n", sample, old_state, pcm->adpcm_state, pcm->output);
142 pcm->counter = pcm->rate; 133 pcm->counter = pcm->rate;
143 } else { 134 } else {
144 uint8_t cmd = pcm_fifo_read(pcm); 135 uint8_t cmd = pcm_fifo_read(pcm);
145 if (cmd) { 136 if (cmd) {
146 pcm->ctrl |= 0x8000; 137 pcm->ctrl &= ~PCM_BUSY;
147 } else { 138 } else {
148 pcm->ctrl &= 0x7FFF; 139 pcm->ctrl |= PCM_BUSY;
149 } 140 }
150 switch (cmd & 0xC0) 141 switch (cmd & 0xC0)
151 { 142 {
152 case 0: 143 case 0:
153 pcm->output = 0; 144 pcm->output = 0;
187 // V: volume, probably attenuation value since converter defaults to "0" 178 // V: volume, probably attenuation value since converter defaults to "0"
188 void pico_pcm_ctrl_write(pico_pcm *pcm, uint16_t value) 179 void pico_pcm_ctrl_write(pico_pcm *pcm, uint16_t value)
189 { 180 {
190 if (value & PCM_RESET) { 181 if (value & PCM_RESET) {
191 pico_pcm_reset(pcm); 182 pico_pcm_reset(pcm);
192 pcm->counter = 2; 183 }
193 } 184 pcm->ctrl &= PCM_BUSY;
194 pcm->ctrl = value; 185 pcm->ctrl |= value & ~(PCM_BUSY);
195 //TODO: update low-pass filter 186 //TODO: update low-pass filter
196 } 187 }
197 188
198 void pico_pcm_data_write(pico_pcm *pcm, uint16_t value) 189 void pico_pcm_data_write(pico_pcm *pcm, uint16_t value)
199 { 190 {