From: Rostislav Lisovy Date: Wed, 13 Apr 2011 23:32:12 +0000 (+0200) Subject: ADCs reading (and setting via GUI interface) seems to work properly. X-Git-Url: http://rtime.felk.cvut.cz/gitweb/mf6xx.git/commitdiff_plain/b50b1fd09e5af74e8da9d36ef608ad06e9f0cb50 ADCs reading (and setting via GUI interface) seems to work properly. --- diff --git a/src/qemu/hw/mf624.c b/src/qemu/hw/mf624.c index 6c2d9d3..b75f69c 100755 --- a/src/qemu/hw/mf624.c +++ b/src/qemu/hw/mf624.c @@ -97,9 +97,16 @@ typedef struct { int port; int addr; - uint16_t real_world_AD[8]; /* The real voltage which is on inputs od A/D convertors. - Until new conversion is started, there is old value in - ADC registers*/ + /* The real voltage which is on inputs od A/D convertors. + Until new conversion is started, there is old value in ADC registers*/ + unsigned int real_world_AD0; + unsigned int real_world_AD1; + unsigned int real_world_AD2; + unsigned int real_world_AD3; + unsigned int real_world_AD4; + unsigned int real_world_AD5; + unsigned int real_world_AD6; + unsigned int real_world_AD7; // for cpu_register_physical_memory() function unsigned int BAR0_mem_table_index; @@ -110,34 +117,22 @@ typedef struct { BAR0_t BAR0; BAR2_t BAR2; BAR4_t BAR4; - + + int ADDATA_FIFO[8]; //this array tells us which ADCs are being converted unsigned int ADDATA_FIFO_POSITION; //ADDATA is FIFO register; //We need to know, position in this FIFO = //Which value will come next } mf624_state_t; -//FIXME all wrong -int volts_to_adinternal(int volt) +int16_t volts_to_adinternal(double volt) { - int tmp; - - tmp = ~volt; - tmp += 1; - - return tmp; + return ((int16_t) ((volt*0x8000)/10))>>2; } -//FIXME all wrong -int dacinternal_to_volts(int dacinternal) +double dacinternal_to_volts(int16_t dacinternal) { - if (dacinternal >= 0x2000) { - return -(~(dacinternal & ~(0x2000)))/1000; - } - else { - return (dacinternal - 0x2000)/1000; - } - + return ((((double)dacinternal)/0x4000)*20.0 - 10.0); } //----------------------------------------------------------------------------- void mf624_init_registers(mf624_state_t* s) @@ -274,34 +269,34 @@ void* init_socket(void* ptr) } // REG has "same size +1" as READ_BUFFER to avoid buffer overflow - status = sscanf(read_buffer, "%[A-Z0-9]=%u", reg, &val); + status = sscanf(read_buffer, "%[A-Z0-9]=%d", reg, &val); if (status == 2) { if(!strcmp(reg, "DIN")) { dev->BAR2.DIN = val; } else if(!strcmp(reg, "ADC0")) { - dev->real_world_AD[0] = volts_to_adinternal(val); + dev->real_world_AD0 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC1")) { - dev->real_world_AD[1] = volts_to_adinternal(val); + dev->real_world_AD1 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC2")) { - dev->real_world_AD[2] = volts_to_adinternal(val); + dev->real_world_AD2 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC3")) { - dev->real_world_AD[3] = volts_to_adinternal(val); + dev->real_world_AD3 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC4")) { - dev->real_world_AD[4] = volts_to_adinternal(val); + dev->real_world_AD4 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC5")) { - dev->real_world_AD[5] = volts_to_adinternal(val); + dev->real_world_AD5 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC6")) { - dev->real_world_AD[6] = volts_to_adinternal(val); + dev->real_world_AD6 = volts_to_adinternal(val); } else if(!strcmp(reg, "ADC7")) { - dev->real_world_AD[7] = volts_to_adinternal(val); + dev->real_world_AD7 = volts_to_adinternal(val); } else { printf("reg = %s; val = %d\n", reg, val); @@ -406,6 +401,13 @@ uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr) case ADDATA6_off: case ADDATA7_off: if (!(s->BAR0.GPIOC & GPIOC_EOLC_mask)) { //Has the conversion already ended? + #define ADC_CHANNELS 8 + for(i = s->ADDATA_FIFO_POSITION; i < ADC_CHANNELS; i ++) { + if (s->BAR2.ADCTRL & (1 << i)) { + s->ADDATA_FIFO_POSITION = i; // Move to next AD to be read + } + } + switch (s->ADDATA_FIFO_POSITION) { case 0: @@ -451,18 +453,21 @@ uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr) case ADSTART_off: s->BAR0.GPIOC |= GPIOC_EOLC_mask; // Conversion in progress s->ADDATA_FIFO_POSITION = 0; - for (i = 0; i < 500000; i++) + for (i = 0; i < 5000; i++) ; // Small delay simulating real conversion // Check before assignement, if particular ADC is enabled - s->BAR2.ADDATA = (s->BAR2.ADCTRL & (1 << 0)) ? s->real_world_AD[0] : s->BAR2.ADDATA; - s->BAR2.ADDATA1 = (s->BAR2.ADCTRL & (1 << 1)) ? s->real_world_AD[1] : s->BAR2.ADDATA1; - s->BAR2.ADDATA2 = (s->BAR2.ADCTRL & (1 << 2)) ? s->real_world_AD[2] : s->BAR2.ADDATA2; - s->BAR2.ADDATA3 = (s->BAR2.ADCTRL & (1 << 3)) ? s->real_world_AD[3] : s->BAR2.ADDATA3; - s->BAR2.ADDATA4 = (s->BAR2.ADCTRL & (1 << 4)) ? s->real_world_AD[4] : s->BAR2.ADDATA4; - s->BAR2.ADDATA5 = (s->BAR2.ADCTRL & (1 << 5)) ? s->real_world_AD[5] : s->BAR2.ADDATA5; - s->BAR2.ADDATA6 = (s->BAR2.ADCTRL & (1 << 6)) ? s->real_world_AD[6] : s->BAR2.ADDATA6; - s->BAR2.ADDATA7 = (s->BAR2.ADCTRL & (1 << 7)) ? s->real_world_AD[7] : s->BAR2.ADDATA7; + s->BAR2.ADDATA = (s->BAR2.ADCTRL & (1 << 0)) ? s->real_world_AD0 : s->BAR2.ADDATA; + s->BAR2.ADDATA1 = (s->BAR2.ADCTRL & (1 << 1)) ? s->real_world_AD1 : s->BAR2.ADDATA1; + s->BAR2.ADDATA2 = (s->BAR2.ADCTRL & (1 << 2)) ? s->real_world_AD2 : s->BAR2.ADDATA2; + s->BAR2.ADDATA3 = (s->BAR2.ADCTRL & (1 << 3)) ? s->real_world_AD3 : s->BAR2.ADDATA3; + s->BAR2.ADDATA4 = (s->BAR2.ADCTRL & (1 << 4)) ? s->real_world_AD4 : s->BAR2.ADDATA4; + s->BAR2.ADDATA5 = (s->BAR2.ADCTRL & (1 << 5)) ? s->real_world_AD5 : s->BAR2.ADDATA5; + s->BAR2.ADDATA6 = (s->BAR2.ADCTRL & (1 << 6)) ? s->real_world_AD6 : s->BAR2.ADDATA6; + s->BAR2.ADDATA7 = (s->BAR2.ADCTRL & (1 << 7)) ? s->real_world_AD7 : s->BAR2.ADDATA7; + + //All channels converted + s->BAR0.GPIOC &= ~ GPIOC_EOLC_mask; return 0xFFFF; // Semirandom value @@ -505,6 +510,54 @@ void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t value) } break; + case DA2_off: + s->BAR2.DA2 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write(s, "DA2", dacinternal_to_volts(s->BAR2.DA2)); + } + break; + + case DA3_off: + s->BAR2.DA3 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write(s, "DA3", dacinternal_to_volts(s->BAR2.DA3)); + } + break; + + case DA4_off: + s->BAR2.DA4 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write(s, "DA4", dacinternal_to_volts(s->BAR2.DA4)); + } + break; + + case DA5_off: + s->BAR2.DA5 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write(s, "DA5", dacinternal_to_volts(s->BAR2.DA5)); + } + break; + + case DA6_off: + s->BAR2.DA6 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write(s, "DA6", dacinternal_to_volts(s->BAR2.DA6)); + } + break; + + case DA7_off: + s->BAR2.DA7 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write(s, "DA7", dacinternal_to_volts(s->BAR2.DA7)); + } + break; + default: printf("mf624_BAR2_write16(): addr = %d; value = %d\n", addr, value); break;