#define min(a, b) ((a) > (b) ? (b) : (a))
/* Hardware specific */
+/* BAR0 */
#define GPIOC_reg 0x54
+
+/* BAR2 */
+#define ADCTRL_reg 0x00
+#define ADDATA0_reg 0x00
+#define ADDATA1_reg 0x02
+#define ADDATA2_reg 0x04
+#define ADDATA3_reg 0x06
+#define ADDATA4_reg 0x08
+#define ADDATA5_reg 0x0a
+#define ADDATA6_reg 0x0c
+#define ADDATA7_reg 0x0e
+#define ADSTART_reg 0x20
+
#define DOUT_reg 0x10
+#define DIN_reg 0x10
#define DA0_reg 0x20
#define DA1_reg 0x22
#define DA2_reg 0x24
#define DA6_reg 0x2C
#define DA7_reg 0x2E
+
+
#define GPIOC_DACEN_mask (1 << 26)
#define GPIOC_LDAC_mask (1 << 23)
+#define GPIOC_EOLC_mask (1 << 17)
#define BAR0_offset (0 * sysconf(_SC_PAGESIZE))
#define BAR2_offset (1 * sysconf(_SC_PAGESIZE))
#define BAR4_offset (2 * sysconf(_SC_PAGESIZE))
-typedef enum {DA0, DA1} dac_channel_t;
+
+typedef enum {DA0, DA1, DA2, DA3, DA4, DA5, DA6, DA7} dac_channel_t;
+typedef enum {AD0, AD1, AD2, AD3, AD4, AD5, AD6, AD7} adc_channel_t;
+
int status;
void* mf624_BAR0 = NULL;
int BAR0_phys_addr;
int BAR2_phys_addr;
int BAR4_phys_addr;
+int ADC_enabled; // Which ADCs are enabled
+
+/* Print one byte as binary number */
void print_8bin(int nr)
{
int i;
uint16_t DIO_read()
{
- return mf624_read16(mf624_BAR2 + DOUT_reg) & 0xF;
+ return mf624_read16(mf624_BAR2 + DIN_reg) & 0xF;
}
void DAC_enable()
{
- mf624_write16(mf624_read16(mf624_BAR2 + GPIOC_reg)
- | GPIOC_DACEN_mask
- & ~GPIOC_LDAC_mask,
- mf624_BAR2 + GPIOC_reg);
+ // Setting DACEN and LDAC bits in GPIO register influences all DACs
+ mf624_write32((mf624_read32(mf624_BAR0 + GPIOC_reg)
+ | GPIOC_DACEN_mask) // enable output
+ & ~GPIOC_LDAC_mask, // enable conversion
+ mf624_BAR0 + GPIOC_reg);
}
void DAC_write(dac_channel_t channel, int val) {
case DA1:
mf624_write16(val, mf624_BAR2 + DA1_reg);
break;
+ case DA2:
+ mf624_write16(val, mf624_BAR2 + DA2_reg);
+ break;
+ case DA3:
+ mf624_write16(val, mf624_BAR2 + DA3_reg);
+ break;
+ case DA4:
+ mf624_write16(val, mf624_BAR2 + DA4_reg);
+ break;
+ case DA5:
+ mf624_write16(val, mf624_BAR2 + DA5_reg);
+ break;
+ case DA6:
+ mf624_write16(val, mf624_BAR2 + DA6_reg);
+ break;
+ case DA7:
+ mf624_write16(val, mf624_BAR2 + DA7_reg);
+ break;
default:
printf("FFFUUU!\n");
}
+}
+
+void ADC_enable(adc_channel_t channel)
+{
+ ADC_enabled = 0;
+ switch (channel) {
+ case AD0:
+ ADC_enabled = (1 << 0);
+ break;
+ case AD1:
+ ADC_enabled = (1 << 1);
+ break;
+ case AD2:
+ ADC_enabled = (1 << 2);
+ break;
+ case AD3:
+ ADC_enabled = (1 << 3);
+ break;
+ case AD4:
+ ADC_enabled = (1 << 4);
+ break;
+ case AD5:
+ ADC_enabled = (1 << 5);
+ break;
+ case AD6:
+ ADC_enabled = (1 << 6);
+ break;
+ case AD7:
+ ADC_enabled = (1 << 7);
+ break;
+ default:
+ printf("FFFUUU!\n");
+ }
+ ADC_enabled &= 0xFF;
+ mf624_write16(ADC_enabled, mf624_BAR2 + ADCTRL_reg);
+ //print_8bin(ADC_enabled);
+}
+
+/* This function blocks until conversion is finished */
+double ADC_read(adc_channel_t channel)
+{
+ int i;
+ int result;
+
+ // Activate trigger to start conversion
+ mf624_read16(mf624_BAR2 + ADSTART_reg);
+
+ // Check if conversion has finished
+ while((mf624_read32(mf624_BAR0 + GPIOC_reg) & GPIOC_EOLC_mask)) {
+ for (i = 0; i < 1000; i++) {} // small wait
+ }
+
+ ADC_enable(channel);
+ result = mf624_read16(mf624_BAR2 + ADDATA0_reg);
+ return 10.0 * ((int16_t) (result << 2)) / (double) 0x8000;
}
+
int open_device(char* path) {
status = open(path, O_RDWR);
if (status == -1) {
fclose(file);
- //FIXME size of memory must be in multiples of memory pages
- // size = (size + PAGE_SIZE -1) / PAGE_SIZE * PAGE_SIZE; ?
mf624_BAR0 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR0_offset);
if (mf624_BAR2 == MAP_FAILED) {
perror("mmap()");
if (device_fd != -1) {
DAC_enable();
-
while (1){
- printf("Reading DIO = ");
+ printf("Reading DIO: ");
print_8bin(DIO_read());
sleep(1);
-
- printf("Setting DA0 to 10 V\n");
- DAC_write(DA0, 0x3FFF);
+
+ printf("Setting DA1 to 10 V\n");
+ DAC_write(DA1, 0x3FFF);
sleep(1);
+ printf("Reading ADC0: ");
+ printf("%f V\n", ADC_read(AD0));
+ sleep(1);
+
+ printf("Reading ADC1: ");
+ printf("%f V\n", ADC_read(AD1));
+ sleep(1);
+
printf("Setting DIO to 0xff\n");
DIO_write(0xff);
sleep(1);
DIO_write(0x00);
sleep(1);
- printf("Setting DA0 to 5 V\n");
- DAC_write(DA0, 0x3000);
+ printf("Setting DA1 to 5 V\n");
+ DAC_write(DA1, 0x3000);
sleep(1);
+ printf("Reading ADC0: ");
+ printf("%f V\n", ADC_read(AD0));
+ sleep(1);
+
+ printf("Reading ADC1: ");
+ printf("%f V\n", ADC_read(AD1));
+ sleep(1);
printf("----------------------\n\n");
}
}