void analogout_write_u16(dac_t *obj, uint16_t value) { if (value > (uint16_t)RANGE_12BIT) { value = (uint16_t)RANGE_12BIT; // Max value } dac_write(obj, value); }
int main(void) { dac_open(); while (1) { /* keep DAC FIFO topped up */ dac_write((short*)aSine, SINE_SAMPLES); } }
/***************************************************************************//** * @brief dds_default_setup *******************************************************************************/ static int dds_default_setup(uint32_t chan, uint32_t phase, uint32_t freq, uint32_t scale) { uint64_t val64; uint32_t val; dds_st.cached_freq[chan] = freq; dds_st.cached_phase[chan] = phase; dds_st.cached_scale[chan] = scale; val64 = (u64) freq * 0xFFFFULL; do_div(val64, *dds_st.dac_clk); val = ADI_DDS_INCR(val64) | 1; val64 = (u64) phase * 0x10000ULL + (360000 / 2); do_div(val64, 360000); val |= ADI_DDS_INIT(val64); dac_write(ADI_REG_CHAN_CNTRL_1_IIOCHAN(chan), ADI_DDS_SCALE(scale)); dac_write(ADI_REG_CHAN_CNTRL_2_IIOCHAN(chan), val); return 0; }
/***************************************************************************//** * @brief dds_set_frequency *******************************************************************************/ int32_t dds_set_frequency(uint32_t chan, uint32_t freq) { uint32_t pcore_version; uint32_t val; uint64_t val64; uint32_t reg; uint64_t dac_clk; dac_read(DAC_REG_CLK_FREQ, &val); dac_clk = val; dac_read(DAC_REG_CLK_RATIO, &val); dac_clk *= val * 1525; dac_read(DAC_REG_VERSION, &pcore_version); if(DAC_PCORE_VERSION_MAJOR(pcore_version) < 8) { dac_write(DAC_REG_CNTRL_1, 0); } dac_read(DAC_REG_CHAN_CNTRL_2_IIOCHAN(chan), ®); reg &= ~DAC_DDS_INCR(~0); val64 = (uint64_t) freq * 0xFFFFULL; val64 = val64 / dac_clk; reg |= DAC_DDS_INCR(val64) | 1; dac_write(DAC_REG_CHAN_CNTRL_2_IIOCHAN(chan), reg); if(DAC_PCORE_VERSION_MAJOR(pcore_version) < 8) { dac_write(DAC_REG_CNTRL_1, DAC_ENABLE); } else { dac_write(DAC_REG_CNTRL_1, DAC_SYNC); } return 0; }
/***************************************************************************//** * @brief dds_set_frequency *******************************************************************************/ void dds_set_frequency(struct ad9361_rf_phy *phy, uint32_t chan, uint32_t freq) { uint64_t val64; uint32_t reg; dds_st[phy->id_no].cached_freq[chan] = freq; dac_stop(phy); dac_read(phy, DAC_REG_CHAN_CNTRL_2_IIOCHAN(chan), ®); reg &= ~DAC_DDS_INCR(~0); val64 = (uint64_t) freq * 0xFFFFULL; do_div(&val64, *dds_st[phy->id_no].dac_clk); reg |= DAC_DDS_INCR(val64) | 1; dac_write(phy, DAC_REG_CHAN_CNTRL_2_IIOCHAN(chan), reg); dac_start_sync(phy, 0); }
/***************************************************************************//** * @brief dds_set_phase *******************************************************************************/ void dds_set_phase(uint32_t chan, uint32_t phase) { uint64_t val64; uint32_t reg; dds_st.cached_phase[chan] = phase; dac_stop(); dac_read(ADI_REG_CHAN_CNTRL_2_IIOCHAN(chan), ®); reg &= ~ADI_DDS_INIT(~0); val64 = (uint64_t) phase * 0x10000ULL + (360000 / 2); do_div(&val64, 360000); reg |= ADI_DDS_INIT(val64); dac_write(ADI_REG_CHAN_CNTRL_2_IIOCHAN(chan), reg); dac_start_sync(0); }
/***************************************************************************//** * @brief dac_datasel *******************************************************************************/ int32_t dac_datasel(struct ad9361_rf_phy *phy, int32_t chan, enum dds_data_select sel) { int i; if (PCORE_VERSION_MAJOR(dds_st[phy->id_no].pcore_version) > 7) { if (chan < 0) { /* ALL */ for (i = 0; i < dds_st[phy->id_no].num_buf_channels; i++) { dac_write(phy, DAC_REG_CHAN_CNTRL_7(i), sel); dds_st[phy->id_no].cached_datasel[i] = sel; } } else { dac_write(phy, DAC_REG_CHAN_CNTRL_7(chan), sel); dds_st[phy->id_no].cached_datasel[chan] = sel; } } else { uint32_t reg; switch(sel) { case DATA_SEL_DDS: case DATA_SEL_SED: case DATA_SEL_DMA: dac_read(phy, DAC_REG_CNTRL_2, ®); reg &= ~DAC_DATA_SEL(~0); reg |= DAC_DATA_SEL(sel); dac_write(phy, DAC_REG_CNTRL_2, reg); break; default: return -EINVAL; } for (i = 0; i < dds_st[phy->id_no].num_buf_channels; i++) { dds_st[phy->id_no].cached_datasel[i] = sel; } } return 0; }
/***************************************************************************//** * @brief dds_set_frequency *******************************************************************************/ void dds_set_frequency(uint32_t chan, uint32_t freq) { uint64_t val64; uint32_t reg; dds_st.cached_freq[chan] = freq; dac_stop(); dac_read(ADI_REG_CHAN_CNTRL_2_IIOCHAN(chan), ®); reg &= ~ADI_DDS_INCR(~0); val64 = (uint64_t) freq * 0xFFFFULL; do_div(&val64, *dds_st.dac_clk); reg |= ADI_DDS_INCR(val64) | 1; dac_write(ADI_REG_CHAN_CNTRL_2_IIOCHAN(chan), reg); dac_start_sync(0); }
void motor_speed(int16_t speed){ if(speed > 0){ motor_direction(right); } else{ motor_direction(left); speed = abs(speed); } if(speed > max_speed){ speed = max_speed; } dac_write(0, speed); }
/***************************************************************************//** * @brief dds_set_phase *******************************************************************************/ void dds_set_phase(struct ad9361_rf_phy *phy, uint32_t chan, uint32_t phase) { uint64_t val64; uint32_t reg; dds_st[phy->id_no].cached_phase[chan] = phase; dac_stop(phy); dac_read(phy, DAC_REG_CHAN_CNTRL_2_IIOCHAN(chan), ®); reg &= ~DAC_DDS_INIT(~0); val64 = (uint64_t) phase * 0x10000ULL + (360000 / 2); do_div(&val64, 360000); reg |= DAC_DDS_INIT(val64); dac_write(phy, DAC_REG_CHAN_CNTRL_2_IIOCHAN(chan), reg); dac_start_sync(phy, 0); }
/***************************************************************************//** * @brief main *******************************************************************************/ int main(void) { adf4350_setup(SPI_DEVICE_ID, 0, default_adf4350_init_param); dac_setup(XPAR_AXI_AD9739A_BASEADDR); ad9739a_setup(SPI_DEVICE_ID, 1, default_ad9739a_init_param); dac_write(ADI_REG_CNTRL_2, ADI_DATA_FORMAT); dds_set_frequency(0, 300000000); dds_set_phase(0, 0); dds_set_scale(0, 250000); dds_set_frequency(1, 300000000); dds_set_phase(1, 0); dds_set_scale(1, 250000); return 0; }
int cmd_dac(t_hydra_console *con, t_tokenline_parsed *p) { int num_sources, t; int value; float volt; bsp_dev_dac_t dev_num; bsp_status_t status; if (p->tokens[1] == 0) return FALSE; dev_num = BSP_DEV_DAC1; t = 1; num_sources = 0; value = -1; volt = 0.0f; while (p->tokens[t]) { switch (p->tokens[t++]) { case T_DAC1: dev_num = BSP_DEV_DAC1; num_sources=1; break; case T_DAC2: dev_num = BSP_DEV_DAC2; num_sources=1; break; case T_RAW: value = -1; volt = 0.0f; t += 1; memcpy(&value, p->buf + p->tokens[t++], sizeof(int)); if (!num_sources) { cprintf(con, "Specify at least one source.\r\n"); return TRUE; } cprintf(con, "%s Raw\r\n", dac_channel_names[dev_num]); dac_write(con, dev_num, value, volt); break; case T_VOLT: value = -1; volt = 0.0f; t += 1; memcpy(&volt, p->buf + p->tokens[t++], sizeof(float)); if (!num_sources) { cprintf(con, "Specify at least one source.\r\n"); return TRUE; } cprintf(con, "%s Volt\r\n", dac_channel_names[dev_num]); dac_write(con, dev_num, value, volt); break; case T_TRIANGLE: if (!num_sources) { cprintf(con, "Specify at least one source.\r\n"); return TRUE; } cprintf(con, "%s (Triangle Out)\r\n", dac_channel_names[dev_num]); if ((status = bsp_dac_init(dev_num)) != BSP_OK) { cprintf(con, "bsp_dac_init error: %d\r\n", status); return FALSE; } bsp_dac_triangle(dev_num); break; case T_NOISE: if (!num_sources) { cprintf(con, "Specify at least one source.\r\n"); return TRUE; } cprintf(con, "%s (Noise Out)\r\n", dac_channel_names[dev_num]); if ((status = bsp_dac_init(dev_num)) != BSP_OK) { cprintf(con, "bsp_dac_init error: %d\r\n", status); return FALSE; } bsp_dac_noise(dev_num); break; case T_EXIT: if (num_sources == 0) { bsp_dac_deinit(BSP_DEV_DAC1); bsp_dac_deinit(BSP_DEV_DAC2); bsp_dac_disable(); } else { bsp_dac_deinit(dev_num); } return TRUE; } } return TRUE; }
/***************************************************************************//** * @brief dac_init *******************************************************************************/ void dac_init(struct ad9361_rf_phy *phy, uint8_t data_sel) { uint32_t tx_count; uint32_t index; uint32_t index_i1; uint32_t index_q1; uint32_t index_i2; uint32_t index_q2; uint32_t data_i1; uint32_t data_q1; uint32_t data_i2; uint32_t data_q2; dac_write(ADI_REG_RSTN, 0x0); dac_write(ADI_REG_RSTN, ADI_RSTN | ADI_MMCM_RSTN); dac_write(ADI_REG_RATECNTRL, ADI_RATE(3)); dds_st.dac_clk = &phy->clks[TX_SAMPL_CLK]->rate; dds_st.num_dds_channels = 8; // FIXME dac_read(ADI_REG_VERSION, &dds_st.pcore_version); dac_stop(); switch (data_sel) { case DATA_SEL_DDS: dds_default_setup(DDS_CHAN_TX1_I_F1, 90000, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX1_I_F2, 90000, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX1_Q_F1, 0, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX1_Q_F2, 0, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX2_I_F1, 90000, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX2_I_F2, 90000, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX2_Q_F1, 0, 1000000, 0.25); dds_default_setup(DDS_CHAN_TX2_Q_F2, 0, 1000000, 0.25); dac_write(ADI_REG_CNTRL_2, 0); dac_datasel(-1, DATA_SEL_DDS); break; case DATA_SEL_DMA: tx_count = sizeof(sine_lut) / sizeof(uint16_t); for(index = 0; index < (tx_count * 2); index += 2) { index_i1 = index; index_q1 = index + (tx_count / 2); if(index_q1 >= (tx_count * 2)) index_q1 -= (tx_count * 2); data_i1 = (sine_lut[index_i1 / 2] << 20); data_q1 = (sine_lut[index_q1 / 2] << 4); // FIXME index_i2 = index_i1; index_q2 = index_q1; if(index_i2 >= (tx_count * 2)) index_i2 -= (tx_count * 2); if(index_q2 >= (tx_count * 2)) index_q2 -= (tx_count * 2); data_i2 = (sine_lut[index_i2 / 2] << 20); data_q2 = (sine_lut[index_q2 / 2] << 4); // FIXME } dac_dma_write(AXI_DMAC_REG_CTRL, 0); dac_dma_write(AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); // FIXME dac_dma_write(AXI_DMAC_REG_SRC_ADDRESS, DAC_DDR_BASEADDR); dac_dma_write(AXI_DMAC_REG_SRC_STRIDE, 0x0); dac_dma_write(AXI_DMAC_REG_X_LENGTH, (tx_count * 8) - 1); dac_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0); dac_dma_write(AXI_DMAC_REG_START_TRANSFER, 0x1); dac_write(ADI_REG_CNTRL_2, 0); dac_datasel(-1, DATA_SEL_DMA); break; default: break; } dds_st.enable = true; dac_start_sync(0); }
/************************************************************************* * Function Name: Timer0IntrHandler * Parameters: none * * Return: none * * Description: Timer 0 interrupt handler * *************************************************************************/ void Timer0IntrHandler (void) { update_touch_coordinates(); // FIO0PIN_bit.P0_19 = 1; // ========== LCD - touch meassurement loop: START switch_touch_meassure_channel(); // ========== LCD - touch meassurement loop: STOP // if (Touch_data.state==(Y_ch || confirm)) // FIO0PIN_bit.P0_11 = 1; adc_start(); //Start the ADC, ADC will be done before next timer interrupt //it has higer priority and will therefore be handlet first httpd_tick_count++; if((httpd_tick_count)%(TIMER0_TICK_PER_SEC/HTTPD_TICK_PER_SEC) == 0) { httpd_tick(); httpd_tick_count = 0; } tick_count++; update_real_time(); //calculate_p_p_values(); //frequency calculation: START //frequency calculation: STOP if(detect_ZeroCrossing(ADdata.previous_filtered_measurement, ADdata.current_filtered_measurement)) { //Calculate RMS value V_RMS = calculate_X_RMS(V_RMS_2_accumulator); I_RMS = calculate_X_RMS(I_RMS_2_accumulator); P_RMS = ((P_RMS_2_accumulator)/(tick_count)); //CAlculate peak value from RMS value ADC_p_p.v_max = sqrt(2)*V_RMS; ADC_p_p.v_min = -sqrt(2)*V_RMS; //Clear RMS accumulator V_RMS_2_accumulator=0.0; I_RMS_2_accumulator=0.0; P_RMS_2_accumulator=0.0; calculate_frequency(tick_count); tick_count=0; } dac_timer++; if(dac_timer == DAC_MAXIMUM) { dac_timer = 0; blink_timer++; if(blink_timer == FREQUENCY/5) { toggle_led(1); // toggle_led(2); blink_timer = 0; f_out = frequency; if(Relay1_button_state==1) FIO0PIN_bit.P0_11 = 1; else{ if(frequency>=RELAY_ON_FREQUENCY && relays_status(bulb) != 1) { toggle_relays(bulb, 1); } else if(frequency<=RELAY_OFF_FREQUENCY && relays_status(bulb) != 0){ toggle_relays(bulb, 0); } } if(Relay2_button_state==1) FIO0PIN_bit.P0_19 = 1; else{ if(frequency>=RELAY_ON_FREQUENCY && relays_status(socket) != 1) { toggle_relays(socket, 1); } else if(frequency<=RELAY_OFF_FREQUENCY && relays_status(socket) != 0){ toggle_relays(socket, 0); } } } } // Write data to DAC dac_write(Data); // clear interrupt timer0_interrupt_reset(); // FIO0PIN_bit.P0_19 = 0; // FIO0PIN_bit.P0_11 = 0; VICADDRESS = 0; }
/***************************************************************************//** * @brief dac_init *******************************************************************************/ void dac_init(struct ad9361_rf_phy *phy, uint8_t data_sel, uint8_t config_dma) { #ifdef DMA_UIO uint32_t tx_count; uint32_t index, index_i1, index_q1, index_i2, index_q2; uint32_t index_mem; uint32_t data_i1, data_q1, data_i2, data_q2; uint32_t length; int dev_mem_fd; uint32_t mapping_length, page_mask, page_size; void *mapping_addr, *tx_buff_virt_addr; tx_dma_uio_fd = open(TX_DMA_UIO_DEV, O_RDWR); if(tx_dma_uio_fd < 1) { printf("%s: Can't open tx_dma_uio device\n\r", __func__); return; } tx_dma_uio_addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, tx_dma_uio_fd, 0); #endif dac_write(phy, DAC_REG_RSTN, 0x0); dac_write(phy, DAC_REG_RSTN, DAC_RSTN); dac_write(phy, DAC_REG_RATECNTRL, DAC_RATE(3)); dds_st[phy->id_no].dac_clk = &phy->clks[TX_SAMPL_CLK]->rate; dds_st[phy->id_no].rx2tx2 = phy->pdata->rx2tx2; if(dds_st[phy->id_no].rx2tx2) { dds_st[phy->id_no].num_dds_channels = 8; } else { dds_st[phy->id_no].num_dds_channels = 4; } dac_read(phy, DAC_REG_VERSION, &dds_st[phy->id_no].pcore_version); dac_write(phy, DAC_REG_CNTRL_1, 0); switch (data_sel) { case DATA_SEL_DDS: dds_default_setup(phy, DDS_CHAN_TX1_I_F1, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX1_I_F2, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX1_Q_F1, 0, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX1_Q_F2, 0, 1000000, 250000); if(dds_st[phy->id_no].rx2tx2) { dds_default_setup(phy, DDS_CHAN_TX2_I_F1, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX2_I_F2, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX2_Q_F1, 0, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX2_Q_F2, 0, 1000000, 250000); } dac_write(phy, DAC_REG_CNTRL_2, 0); dac_datasel(phy, -1, DATA_SEL_DDS); break; case DATA_SEL_DMA: if(config_dma) { #ifdef DMA_UIO get_file_info(TX_BUFF_MEM_SIZE, &tx_buff_mem_size); get_file_info(TX_BUFF_MEM_ADDR, &tx_buff_mem_addr); dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if(dev_mem_fd == -1) { printf("%s: Can't open /dev/mem device\n\r", __func__); return; } page_size = sysconf(_SC_PAGESIZE); mapping_length = (((tx_buff_mem_size / page_size) + 1) * page_size); page_mask = (page_size - 1); mapping_addr = mmap(NULL, mapping_length, PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, (tx_buff_mem_addr & ~page_mask)); if(mapping_addr == MAP_FAILED) { printf("%s: mmap error\n\r", __func__); return; } tx_buff_virt_addr = (mapping_addr + (tx_buff_mem_addr & page_mask)); tx_count = sizeof(sine_lut) / sizeof(uint16_t); if(dds_st[phy->id_no].rx2tx2) { #ifdef FMCOMMS5 for(index = 0, index_mem = 0; index < (tx_count * 2); index += 2, index_mem += 4) #else for(index = 0, index_mem = 0; index < (tx_count * 2); index += 2, index_mem += 2) #endif { index_i1 = index; index_q1 = index + (tx_count / 2); if(index_q1 >= (tx_count * 2)) index_q1 -= (tx_count * 2); data_i1 = (sine_lut[index_i1 / 2] << 20); data_q1 = (sine_lut[index_q1 / 2] << 4); *((unsigned *) (tx_buff_virt_addr + (index_mem* 4))) = data_i1 | data_q1; index_i2 = index_i1; index_q2 = index_q1; if(index_i2 >= (tx_count * 2)) index_i2 -= (tx_count * 2); if(index_q2 >= (tx_count * 2)) index_q2 -= (tx_count * 2); data_i2 = (sine_lut[index_i2 / 2] << 20); data_q2 = (sine_lut[index_q2 / 2] << 4); *((unsigned *) (tx_buff_virt_addr + ((index_mem+ 1) * 4))) = data_i2 | data_q2; #ifdef FMCOMMS5 *((unsigned *) (tx_buff_virt_addr + ((index_mem+ 2) * 4))) = data_i1 | data_q1; *((unsigned *) (tx_buff_virt_addr + ((index_mem+ 3) * 4))) = data_i2 | data_q2; #endif } } else { for(index = 0; index < tx_count; index += 1) { index_i1 = index; index_q1 = index + (tx_count / 4); if(index_q1 >= tx_count) index_q1 -= tx_count; data_i1 = (sine_lut[index_i1 / 2] << 20); data_q1 = (sine_lut[index_q1 / 2] << 4); *((unsigned *) (tx_buff_virt_addr + (index * 4))) = data_i1 | data_q1; } } munmap(mapping_addr, mapping_length); close(dev_mem_fd); if(dds_st[phy->id_no].rx2tx2) { length = (tx_count * 8); } else { length = (tx_count * 4); } #ifdef FMCOMMS5 length = (tx_count * 16); #endif dac_dma_write(AXI_DMAC_REG_CTRL, 0); dac_dma_write(AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); dac_dma_write(AXI_DMAC_REG_SRC_ADDRESS, tx_buff_mem_addr); dac_dma_write(AXI_DMAC_REG_SRC_STRIDE, 0x0); dac_dma_write(AXI_DMAC_REG_X_LENGTH, length - 1); dac_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0); dac_dma_write(AXI_DMAC_REG_START_TRANSFER, 0x1); #endif } dac_write(phy, DAC_REG_CNTRL_2, 0); dac_datasel(phy, -1, DATA_SEL_DMA); break; default: break; } dds_st[phy->id_no].enable = true; dac_start_sync(phy, 0); }
/***************************************************************************//** * @brief dds_set_phase *******************************************************************************/ void dds_set_scale(uint32_t chan, double scale) { uint32_t ctrl_reg; uint32_t scale_reg; uint32_t sign_part; uint32_t int_part; uint32_t fract_part; if (PCORE_VERSION_MAJOR(dds_st.pcore_version) > 6) { if(scale >= 1.0) { sign_part = 0; int_part = 1; fract_part = 0; dds_st.cached_scale[chan] = 1.0; goto set_scale_reg; } if(scale <= -1.0) { sign_part = 1; int_part = 1; fract_part = 0; dds_st.cached_scale[chan] = -1.0; goto set_scale_reg; } if(scale < 0) { sign_part = 1; int_part = 0; dds_st.cached_scale[chan] = scale; scale *= -1; goto set_scale_reg; } sign_part = 0; int_part = 0; dds_st.cached_scale[chan] = scale; fract_part = (uint32_t)(scale * 0x4000); set_scale_reg: scale_reg = (sign_part << 15) | (int_part << 14) | fract_part; } else { if(scale >= 1.0) { scale_reg = 0; scale = 1.0; } if(scale <= 0.0) { scale_reg = 0; scale = 0.0; } dds_st.cached_scale[chan] = scale; fract_part = (uint32_t)(scale * 1000000); scale_reg = 500000 / fract_part; } dac_read(ADI_REG_CNTRL_1, &ctrl_reg); dac_write(ADI_REG_CNTRL_1, 0); dac_write(ADI_REG_CHAN_CNTRL_1_IIOCHAN(chan), ADI_DDS_SCALE(scale_reg)); dac_write(ADI_REG_CNTRL_1, ctrl_reg); }
/***************************************************************************//** * @brief dds_set_scale *******************************************************************************/ int32_t dds_set_scale(uint32_t chan, int32_t scale_micro_units) { uint32_t pcore_version; uint32_t scale_reg; uint32_t sign_part; uint32_t int_part; uint32_t fract_part; dac_read(DAC_REG_VERSION, &pcore_version); if(DAC_PCORE_VERSION_MAJOR(pcore_version) > 6) { if(scale_micro_units >= 1000000) { sign_part = 0; int_part = 1; fract_part = 0; goto set_scale_reg; } if(scale_micro_units <= -1000000) { sign_part = 1; int_part = 1; fract_part = 0; goto set_scale_reg; } if(scale_micro_units < 0) { sign_part = 1; int_part = 0; scale_micro_units *= -1; } else { sign_part = 0; int_part = 0; } fract_part = (uint32_t)(((uint64_t)scale_micro_units * 0x4000) / 1000000); set_scale_reg: scale_reg = (sign_part << 15) | (int_part << 14) | fract_part; } else { if(scale_micro_units >= 1000000) { scale_reg = 0; scale_micro_units = 1000000; } if(scale_micro_units <= 0) { scale_reg = 0; scale_micro_units = 0; } fract_part = (uint32_t)(scale_micro_units); scale_reg = 500000 / fract_part; } if(DAC_PCORE_VERSION_MAJOR(pcore_version) < 8) { dac_write(DAC_REG_CNTRL_1, 0); } dac_write(DAC_REG_CHAN_CNTRL_1_IIOCHAN(chan), DAC_DDS_SCALE(scale_reg)); if(DAC_PCORE_VERSION_MAJOR(pcore_version) < 8) { dac_write(DAC_REG_CNTRL_1, DAC_ENABLE); } else { dac_write(DAC_REG_CNTRL_1, DAC_SYNC); } return 0; }
void analogout_write(dac_t *obj, float value) { /* We multiply the float value with 0xFFF because the DAC has 12-bit resolution. * Ie. accepts values between 0 and 0xFFF (4096). */ dac_write(obj, value*0xFFF); }
int main(int argc, char **argv) { if (nva_init()) { fprintf (stderr, "PCI init failure!\n"); return 1; } int c; int cnum =0; while ((c = getopt (argc, argv, "c:")) != -1) switch (c) { case 'c': sscanf(optarg, "%d", &cnum); break; } if (cnum >= nva_cardsnum) { if (nva_cardsnum) fprintf (stderr, "No such card.\n"); else fprintf (stderr, "No cards found.\n"); return 1; } /* ??? */ dac_write(cnum, 5, 0xff); /* PMC.ENABLE */ nva_wr32(cnum, 0x200, 0); nva_wr32(cnum, 0x200, 0x01011111); /* PFB scanout config */ nva_wr32(cnum, 0x600200, 0x130); nva_wr32(cnum, 0x600400, 0x0); nva_wr32(cnum, 0x600500, 0x18); nva_wr32(cnum, 0x600510, 0x88); nva_wr32(cnum, 0x600520, 0xa0); nva_wr32(cnum, 0x600530, 0x400); nva_wr32(cnum, 0x600540, 0x3); nva_wr32(cnum, 0x600550, 0x6); nva_wr32(cnum, 0x600560, 0x1d); nva_wr32(cnum, 0x600570, 0x300); /* DAC scanout config */ dac_write(cnum, 4, 0x39); dac_write(cnum, 5, 0x08); /* VPLL */ dac_write(cnum, 0x18, 0x0a); dac_write(cnum, 0x19, 0x35); dac_write(cnum, 0x1a, 0x01); dac_write(cnum, 0x1b, 0x01); /* ??? */ dac_write(cnum, 0x1c, 0x00); /* start it up */ nva_wr32(cnum, 0x6000c0, 0x00330000); /* ??? */ nva_wr32(cnum, 0x001400, 0x1000); nva_wr32(cnum, 0x001200, 0x1010); nva_wr32(cnum, 0x400084, 0x01110100); /* memory detection */ nva_wr32(cnum, 0x600000, 0x2); nva_wr32(cnum, 0x1000000, 0xabcd0000); nva_wr32(cnum, 0x1000004, 0xabcd0001); nva_wr32(cnum, 0x100000c, 0xabcd0002); nva_wr32(cnum, 0x1000010, 0xabcd0010); nva_wr32(cnum, 0x1000014, 0xabcd0011); nva_wr32(cnum, 0x100001c, 0xabcd0012); if (nva_rd32(cnum, 0x100000c) == 0xabcd0002) { printf("POSTing 4MB card\n"); nva_wr32(cnum, 0x600000, 0x10000202); nva_wr32(cnum, 0x600040, 0x00900011); nva_wr32(cnum, 0x600044, 0x00000003); nva_wr32(cnum, 0x600080, 0x00010000); dac_write(cnum, 4, 0x39); } else if (nva_rd32(cnum, 0x1000004) == 0xabcd0001) { printf("POSTing 2MB card\n"); nva_wr32(cnum, 0x600000, 0x10001201); nva_wr32(cnum, 0x600040, 0x00400011); nva_wr32(cnum, 0x600044, 0x00000002); nva_wr32(cnum, 0x600080, 0x00010000); dac_write(cnum, 4, 0x39); } else if (nva_rd32(cnum, 0x1000000) == 0xabcd0000) { printf("POSTing 1MB card\n"); nva_wr32(cnum, 0x600000, 0x10001100); nva_wr32(cnum, 0x600040, 0x00400011); nva_wr32(cnum, 0x600044, 0x00000002); nva_wr32(cnum, 0x600080, 0x00010000); dac_write(cnum, 4, 0x35); } else { printf("POST failure - memory didn't come up!\n"); return 1; } /* MPLL */ dac_write(cnum, 0x10, 0x0c); dac_write(cnum, 0x11, 0x60); dac_write(cnum, 0x12, 0x01); dac_write(cnum, 0x13, 0x01); /* AUDIO */ nva_wr32(cnum, 0x3000c0, 0x111); /* ??? */ nva_wr32(cnum, 0x6c1f20, 0x332); nva_wr32(cnum, 0x6c1f24, 0x3330333); nva_wr32(cnum, 0x6c1f00, 1); /* palette */ nva_wr32(cnum, 0x609000, 0); int i; for (i = 0; i < 256; i++) { nva_wr32(cnum, 0x609004, ((i >> 5) & 7) * 255/7); nva_wr32(cnum, 0x609004, ((i >> 2) & 7) * 255/7); nva_wr32(cnum, 0x609004, ((i >> 0) & 3) * 255/3); } for (i = 0; i < 0x400000; i+=4) nva_wr32(cnum, 0x1000000 + i, 0xcccccccc); /* framebuffer*/ for (i = 0; i < 0x300 * 0x400; i++) { int x = i & 0x3ff; int y = i >> 10; int col = 0; if (x+y <= 32) col = 3; if (x-y >= 0x400-32) col = 0x1c; if (x-y <= -0x300+32) col = 0xe0; if (x+y >= 0x700-32) col = 0xff; nva_wr8(cnum, 0x1000000 + i, col); } /* PGRAPH */ nva_wr32(cnum, 0x4006a4, 0x07000111); nva_wr32(cnum, 0x400080, 0x11111111); nva_wr32(cnum, 0x400084, 0x11111000); nva_wr32(cnum, 0x400088, 0x11111111); nva_wr32(cnum, 0x40008c, 0x11111111); nva_wr32(cnum, 0x400100, 0xffffffff); nva_wr32(cnum, 0x400104, 0xffffffff); nva_wr32(cnum, 0x400140, 0xffffffff); nva_wr32(cnum, 0x400144, 0xffffffff); nva_wr32(cnum, 0x400180, 0x00000010); nva_wr32(cnum, 0x400190, 0x10010000); for (i = 0; i < 18; i++) { nva_wr32(cnum, 0x400400 + i * 4, 0); nva_wr32(cnum, 0x400480 + i * 4, 0); } nva_wr32(cnum, 0x400450, 0); nva_wr32(cnum, 0x400454, 0); nva_wr32(cnum, 0x400460, 0x10); nva_wr32(cnum, 0x400464, 0x3f0); nva_wr32(cnum, 0x400468, 0x10); nva_wr32(cnum, 0x40046c, 0x2f0); nva_wr32(cnum, 0x400600, 0); nva_wr32(cnum, 0x400604, 0); nva_wr32(cnum, 0x400608, 0); nva_wr32(cnum, 0x40060c, 0); nva_wr32(cnum, 0x400610, 0); nva_wr32(cnum, 0x400614, 0); nva_wr32(cnum, 0x400618, 0); nva_wr32(cnum, 0x40061c, 0); nva_wr32(cnum, 0x400620, 0); nva_wr32(cnum, 0x400624, 0); nva_wr32(cnum, 0x400628, 0); nva_wr32(cnum, 0x40062c, 0); nva_wr32(cnum, 0x400630, 0); nva_wr32(cnum, 0x400634, 0); /* XXX */ nva_wr32(cnum, 0x400640, 0); nva_wr32(cnum, 0x400644, 0); nva_wr32(cnum, 0x400648, 0); nva_wr32(cnum, 0x40064c, 0); nva_wr32(cnum, 0x400650, 0); nva_wr32(cnum, 0x400654, 0); nva_wr32(cnum, 0x400658, 0); nva_wr32(cnum, 0x40065c, 0); nva_wr32(cnum, 0x400660, 0); nva_wr32(cnum, 0x400680, 0); nva_wr32(cnum, 0x400684, 0); nva_wr32(cnum, 0x400688, 0); nva_wr32(cnum, 0x40068c, 0x02ff03ff); nva_wr32(cnum, 0x400690, 0); nva_wr32(cnum, 0x400694, 0); nva_wr32(cnum, 0x400698, 0); nva_wr32(cnum, 0x40069c, 0); nva_wr32(cnum, 0x4006a0, 0); for (i = 0; i < 14; i++) nva_wr32(cnum, 0x400700 + i * 4, 0); return 0; }
/***************************************************************************//** * @brief dac_init *******************************************************************************/ void dac_init(uint8_t data_sel) { uint32_t status; uint32_t tx_count; uint32_t index; uint32_t index_i1; uint32_t index_q1; uint32_t index_i2; uint32_t index_q2; uint32_t data_i1; uint32_t data_q1; uint32_t data_i2; uint32_t data_q2; dac_write(ADI_REG_RSTN, 0x0); dac_write(ADI_REG_RSTN, ADI_RSTN); dac_write(ADI_REG_RATECNTRL, ADI_RATE(3)); dds_st.dac_clk = &ad9361_phy->clks[TX_SAMPL_CLK]->rate; dac_write(ADI_REG_CNTRL_1, 0); switch (data_sel) { case DATA_SEL_DDS: dds_default_setup(DDS_CHAN_TX1_I_F1, 90000, 1000000, 4); dds_default_setup(DDS_CHAN_TX1_I_F2, 90000, 1000000, 4); dds_default_setup(DDS_CHAN_TX1_Q_F1, 0, 1000000, 4); dds_default_setup(DDS_CHAN_TX1_Q_F2, 0, 1000000, 4); dds_default_setup(DDS_CHAN_TX2_I_F1, 90000, 1000000, 4); dds_default_setup(DDS_CHAN_TX2_I_F2, 90000, 1000000, 4); dds_default_setup(DDS_CHAN_TX2_Q_F1, 0, 1000000, 4); dds_default_setup(DDS_CHAN_TX2_Q_F2, 0, 1000000, 4); dac_write(ADI_REG_CNTRL_2, ADI_DATA_SEL(DATA_SEL_DDS)); break; case DATA_SEL_DMA: tx_count = sizeof(sine_lut) / sizeof(uint16_t); dac_write(ADI_REG_VDMA_FRMCNT, tx_count * 8); for(index = 0; index < (tx_count * 2); index+=2) { index_i1 = index; index_q1 = index + (tx_count / 4); if(index_q1 >= (tx_count * 2)) index_q1 -= (tx_count * 2); data_i1 = (sine_lut[index_i1 / 2] << 20); data_q1 = (sine_lut[index_q1 / 2] << 4); Xil_Out32(DAC_DDR_BASEADDR + index * 4, data_i1 | data_q1); index_i2 = index_i1 + (tx_count / 2); index_q2 = index_q1 + (tx_count / 2); if(index_i2 >= (tx_count * 2)) index_i2 -= (tx_count * 2); if(index_q2 >= (tx_count * 2)) index_q2 -= (tx_count * 2); data_i2 = (sine_lut[index_i2 / 2] << 20); data_q2 = (sine_lut[index_q2 / 2] << 4); Xil_Out32(DAC_DDR_BASEADDR + (index + 1) * 4, data_i2 | data_q2); } Xil_DCacheFlush(); vdma_write(XAXIVDMA_CR_OFFSET, 0x0); vdma_write(XAXIVDMA_CR_OFFSET, XAXIVDMA_CR_TAIL_EN_MASK | XAXIVDMA_CR_RUNSTOP_MASK); do { vdma_read(XAXIVDMA_SR_OFFSET, &status); } while((status & 0x01) == 0x01); vdma_write(XAXIVDMA_FRMSTORE_OFFSET, 0x01); vdma_write(XAXIVDMA_MM2S_ADDR_OFFSET | XAXIVDMA_START_ADDR_OFFSET, DAC_DDR_BASEADDR); vdma_write(XAXIVDMA_MM2S_ADDR_OFFSET | XAXIVDMA_STRD_FRMDLY_OFFSET, tx_count * 8); vdma_write(XAXIVDMA_MM2S_ADDR_OFFSET | XAXIVDMA_HSIZE_OFFSET, tx_count * 8); vdma_write(XAXIVDMA_MM2S_ADDR_OFFSET | XAXIVDMA_VSIZE_OFFSET, 1); dac_write(ADI_REG_CNTRL_2, ADI_DATA_SEL(DATA_SEL_DMA)); break; default: break; } dac_write(ADI_REG_CNTRL_1, ADI_ENABLE); }
static void updatePot(p600Pot_t pot) { int8_t i,lower; uint8_t mux,bitDepth,cdv; uint16_t estimate,badMask; uint16_t bit; BLOCK_INT { // successive approximations using DAC and comparator // select pot mux=(pot&0x0f)|(0x20>>(pot>>4)); io_write(0x0a,mux); CYCLE_WAIT(4); // init values estimate=UINT16_MAX; bit=0x8000; bitDepth=potBitDepth[pot]; badMask=16-bitDepth; badMask=(UINT16_MAX>>badMask)<<badMask; // main loop for(i=0;i<=bitDepth;++i) { dac_write(estimate); // let comparator get correct voltage (don't remove me!) CYCLE_WAIT(2); // is DAC value lower than pot value? lower=(io_read(0x09)&0x08)!=0; // adjust estimate if (lower) estimate+=bit; else estimate-=bit; // on to finer changes bit>>=1; } // unselect io_write(0x0a,0xff); CYCLE_WAIT(4); estimate&=badMask; potmux.pots[pot]=estimate; // change detector cdv=estimate>>8; if(abs(potmux.changeDetect[pot]-cdv)>CHANGE_DETECT_THRESHOLD) { potmux.changeDetect[pot]=cdv; potmux.potChanged|=(uint32_t)1<<pot; potmux.lastChanged=pot; } } }
/***************************************************************************//** * @brief dds_set_phase *******************************************************************************/ void dds_set_scale(struct ad9361_rf_phy *phy, uint32_t chan, int32_t scale_micro_units) { uint32_t scale_reg; uint32_t sign_part; uint32_t int_part; uint32_t fract_part; if (PCORE_VERSION_MAJOR(dds_st[phy->id_no].pcore_version) > 6) { if(scale_micro_units >= 1000000) { sign_part = 0; int_part = 1; fract_part = 0; dds_st[phy->id_no].cached_scale[chan] = 1000000; goto set_scale_reg; } if(scale_micro_units <= -1000000) { sign_part = 1; int_part = 1; fract_part = 0; dds_st[phy->id_no].cached_scale[chan] = -1000000; goto set_scale_reg; } dds_st[phy->id_no].cached_scale[chan] = scale_micro_units; if(scale_micro_units < 0) { sign_part = 1; int_part = 0; scale_micro_units *= -1; } else { sign_part = 0; int_part = 0; } fract_part = (uint32_t)(((uint64_t)scale_micro_units * 0x4000) / 1000000); set_scale_reg: scale_reg = (sign_part << 15) | (int_part << 14) | fract_part; } else { if(scale_micro_units >= 1000000) { scale_reg = 0; scale_micro_units = 1000000; } if(scale_micro_units <= 0) { scale_reg = 0; scale_micro_units = 0; } dds_st[phy->id_no].cached_scale[chan] = scale_micro_units; fract_part = (uint32_t)(scale_micro_units); scale_reg = 500000 / fract_part; } dac_stop(phy); dac_write(phy, DAC_REG_CHAN_CNTRL_1_IIOCHAN(chan), DAC_DDS_SCALE(scale_reg)); dac_start_sync(phy, 0); }
void analogout_write_u16(dac_t *obj, uint16_t value) { dac_write(value); }
/***************************************************************************//** * @brief dac_init *******************************************************************************/ void dac_init(struct ad9361_rf_phy *phy, uint8_t data_sel, uint8_t config_dma) { uint32_t tx_count; uint32_t index; uint32_t index_i1; uint32_t index_q1; uint32_t index_i2; uint32_t index_q2; uint32_t index_mem; uint32_t data_i1; uint32_t data_q1; uint32_t data_i2; uint32_t data_q2; uint32_t length; dac_write(phy, DAC_REG_RSTN, 0x0); dac_write(phy, DAC_REG_RSTN, DAC_RSTN | DAC_MMCM_RSTN); dds_st[phy->id_no].dac_clk = &phy->clks[TX_SAMPL_CLK]->rate; dds_st[phy->id_no].rx2tx2 = phy->pdata->rx2tx2; if(dds_st[phy->id_no].rx2tx2) { dds_st[phy->id_no].num_buf_channels = 4; dac_write(phy, DAC_REG_RATECNTRL, DAC_RATE(3)); } else { dds_st[phy->id_no].num_buf_channels = 2; dac_write(phy, DAC_REG_RATECNTRL, DAC_RATE(1)); } dac_read(phy, DAC_REG_VERSION, &dds_st[phy->id_no].pcore_version); dac_stop(phy); switch (data_sel) { case DATA_SEL_DDS: dds_default_setup(phy, DDS_CHAN_TX1_I_F1, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX1_I_F2, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX1_Q_F1, 0, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX1_Q_F2, 0, 1000000, 250000); if(dds_st[phy->id_no].rx2tx2) { dds_default_setup(phy, DDS_CHAN_TX2_I_F1, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX2_I_F2, 90000, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX2_Q_F1, 0, 1000000, 250000); dds_default_setup(phy, DDS_CHAN_TX2_Q_F2, 0, 1000000, 250000); } dac_write(phy, DAC_REG_CNTRL_2, 0); dac_datasel(phy, -1, DATA_SEL_DDS); break; case DATA_SEL_DMA: if(config_dma) { tx_count = sizeof(sine_lut) / sizeof(uint16_t); if(dds_st[phy->id_no].rx2tx2) { #ifdef FMCOMMS5 for(index = 0, index_mem = 0; index < (tx_count * 2); index += 2, index_mem += 4) #else for(index = 0, index_mem = 0; index < (tx_count * 2); index += 2, index_mem += 2) #endif { index_i1 = index; index_q1 = index + (tx_count / 2); if(index_q1 >= (tx_count * 2)) index_q1 -= (tx_count * 2); data_i1 = (sine_lut[index_i1 / 2] << 20); data_q1 = (sine_lut[index_q1 / 2] << 4); Xil_Out32(DAC_DDR_BASEADDR + index_mem * 4, data_i1 | data_q1); index_i2 = index_i1; index_q2 = index_q1; if(index_i2 >= (tx_count * 2)) index_i2 -= (tx_count * 2); if(index_q2 >= (tx_count * 2)) index_q2 -= (tx_count * 2); data_i2 = (sine_lut[index_i2 / 2] << 20); data_q2 = (sine_lut[index_q2 / 2] << 4); Xil_Out32(DAC_DDR_BASEADDR + (index_mem + 1) * 4, data_i2 | data_q2); #ifdef FMCOMMS5 Xil_Out32(DAC_DDR_BASEADDR + (index_mem + 2) * 4, data_i1 | data_q1); Xil_Out32(DAC_DDR_BASEADDR + (index_mem + 3) * 4, data_i2 | data_q2); #endif } } else { for(index = 0; index < tx_count; index += 1) { index_i1 = index; index_q1 = index + (tx_count / 4); if(index_q1 >= tx_count) index_q1 -= tx_count; data_i1 = (sine_lut[index_i1] << 20); data_q1 = (sine_lut[index_q1] << 4); Xil_Out32(DAC_DDR_BASEADDR + index * 4, data_i1 | data_q1); } } Xil_DCacheFlush(); if(dds_st[phy->id_no].rx2tx2) { length = (tx_count * 8); } else { length = (tx_count * 4); } #ifdef FMCOMMS5 length = (tx_count * 16); #endif dac_dma_write(AXI_DMAC_REG_CTRL, 0); dac_dma_write(AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); dac_dma_write(AXI_DMAC_REG_SRC_ADDRESS, DAC_DDR_BASEADDR); dac_dma_write(AXI_DMAC_REG_SRC_STRIDE, 0x0); dac_dma_write(AXI_DMAC_REG_X_LENGTH, length - 1); dac_dma_write(AXI_DMAC_REG_Y_LENGTH, 0x0); dac_dma_write(AXI_DMAC_REG_START_TRANSFER, 0x1); } dac_write(phy, DAC_REG_CNTRL_2, 0); dac_datasel(phy, -1, DATA_SEL_DMA); break; default: break; } dds_st[phy->id_no].enable = true; dac_start_sync(phy, 0); }