]> rtime.felk.cvut.cz Git - mf6xx.git/commitdiff
ADCs reading (and setting via GUI interface) seems to work properly.
authorRostislav Lisovy <lisovy@gmail.com>
Wed, 13 Apr 2011 23:32:12 +0000 (01:32 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Wed, 13 Apr 2011 23:32:12 +0000 (01:32 +0200)
src/qemu/hw/mf624.c

index 6c2d9d36e0c67781776ce7881e099f7ea296d695..b75f69c5b76cb3e201e89d9bb551d5043ae7f03b 100755 (executable)
@@ -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;