2 FUJITSU FM Towns Emulator 'eFMTowns'
4 Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
16 #define EVENT_ADC_CLOCK 1
17 #define EVENT_ADPCM_CLOCK 2
19 void ADPCM::initialize()
21 adc_fifo = new FIFO(64); // OK?
22 for(int i = 0; i < 8; i++) {
23 dac_int_mask[i] = true; // true = enable intrrupt.
28 initialize_adc_clock(-1);
29 event_adpcm_clock = -1;
42 initialize_adc_clock(-1);
43 if(event_adpcm_clock >= 0) {
44 cancel_event(this, event_adpcm_clock);
46 register_event(this, EVENT_ADPCM_CLOCK, 16.0e6 / (384.0 * 2.0), true, &event_adpcm_clock); // Is this true?
49 void ADPCM::initialize_adc_clock(int freq)
52 freq = (int)d_adc->read_signal(SIG_AD7820_SAMPLE_RATE);
54 if(event_adc_clock >= 0) {
55 cancel_event(this, event_adc_clock);
57 d_adc->write_signal(SIG_AD7820_DATA_REG, 0x00, 0x00);
58 d_adc->write_signal(SIG_AD7820_CS, 0xffffffff, 0xffffffff);
59 d_adc->write_signal(SIG_AD7820_WR_CONVERSION_MODE, 0, 0xffffffff); // READ MODE..
60 register_event(this, EVENT_ADC_CLOCK, 1.0e6 / (double)freq, true, &event_adc_clock);
63 void ADPCM::event_callback(int id, int err)
67 d_adc->write_signal(SIG_AD7820_WR_CONVERSION_MODE, 0, 0xffffffff); // READ MODE
68 d_adc->write_signal(SIG_AD7820_CS, 0xffffffff, 0xffffffff);
69 d_adc->read_data8(SIG_AD7820_DATA_REG); // Dummy read, start to sample.
71 case EVENT_ADPCM_CLOCK:
72 d_rf5c68->write_signal(SIG_RF5C68_DAC_PERIOD, 1, 1);
77 uint32_t ADPCM::read_io8(uint32_t addr)
85 case 0x07: // ADC data register
86 if(!(adc_fifo->empty())) {
87 val = (uint8_t)(adc_fifo->read() & 0xff);
92 case 0x08: // ADC flags
93 val = (!(adc_fifo->empty())) ? 0x01 : 0x00;
95 case 0x09: // Int13 reason
97 bool intr_pcm = false;
98 for(int i = 0; i < 8; i++) {
104 val = 0xf6 | ((intr_pcm) ? 0x08 : 0x00) | ((intr_opx) ? 0x01 : 0x00);
107 case 0x0a: // PCM Interrupt mask
109 for(int i = 0; i < 8; i++) {
110 val = val | ((dac_int_mask[i]) ? (0x01 << i) : 0);
113 case 0x0b: // PCM Interrupt status
117 for(int i = 0; i < 8; i++) {
118 val = val | ((dac_intr[i]) ? (0x01 << i) : 0);
120 for(int i = 0; i < 8; i++) {
127 d_pic->write_signal(SIG_I8259_IR5 | SIG_I8259_CHIP1, 0x00000000, 0xffffffff);
132 if((addr & 0x1f) >= 0x10) val = d_rf5c68->read_io8(addr & 0x0f); // AROUND DAC
138 void ADPCM::write_io8(uint32_t addr, uint32_t data)
140 uint32_t naddr = addr & 0x1f;
143 } else if(naddr == 0x0a) {
144 uint32_t mask = 0x01;
145 for(int i = 0; i < 8; i++) {
146 if((data & mask) != 0) {
147 dac_int_mask[i] = true;
149 dac_int_mask[i] = false;
153 } else if(naddr >= 0x10) {
154 d_rf5c68->write_io8(naddr & 0x0f, data);
158 uint32_t ADPCM::read_data8(uint32_t addr)
160 if((addr >= 0xc2200000) && (addr < 0xc2201000)) {
161 return d_rf5c68->read_data8(addr & 0x0fff);
166 void ADPCM::write_data8(uint32_t addr, uint32_t data)
168 if((addr >= 0xc2200000) && (addr < 0xc2201000)) {
169 d_rf5c68->write_data8(addr & 0x0fff, data);
173 void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
175 if(ch == SIG_ADPCM_WRITE_INTERRUPT) {
176 uint32_t n_ch = data & 0x07;
177 bool n_onoff = (((data & mask) & 0x00000008) != 0) ? true : false;
178 bool n_allset =(((data & mask) & 0x80000000) != 0) ? true : false;
180 n_onoff = n_onoff & dac_int_mask[n_ch];
181 if(n_onoff != dac_intr[n_ch]) { // SET/RESET INT13
182 write_signals(&output_intr, (n_onoff) ? 0xffffffff : 0x00000000);
184 dac_intr[n_ch] = n_onoff;
189 for(int i = 0; i < 8; i++) { // SET/RESET INT13
190 n_backup = dac_intr[i];
191 dac_intr[i] = n_onoff & dac_int_mask[i];
192 if(n_backup != dac_intr[i]) _s = true;
195 write_signals(&output_intr, (n_onoff) ? 0xffffffff : 0x00000000);
198 } else if(ch == SIG_ADPCM_OPX_INTR) { // SET/RESET INT13
199 intr_opx = ((data & mask) != 0);
200 write_signals(&output_intr, (intr_opx) ? 0xffffffff : 0x00000000);
201 } else if(ch == SIG_ADPCM_ADC_INTR) { // Push data to FIFO from ADC.
202 if((data & mask) != 0) {
203 uint32_t n_data = d_adc->read_signal(SIG_AD7820_DATA_REG);
204 d_adc->write_signal(SIG_AD7820_CS, 0, 0xffffffff);
205 if(!(adc_fifo->full())) {
206 adc_fifo->write((int)(n_data & 0xff));
212 #define STATE_VERSION 1
214 bool ADPCM::process_state(FILEIO* state_fio, bool loading)
216 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
219 if(!state_fio->StateCheckInt32(this_device_id)) {
222 if(!(adc_fifo->process_state((void *)state_fio, loading))) {
225 state_fio->StateValue(intr_opx);
226 state_fio->StateArray(dac_intr, sizeof(dac_intr), 1);
227 state_fio->StateArray(dac_int_mask, sizeof(dac_int_mask), 1);