static void StartConversion(Afec *afec) { // Clear out any existing conversion complete bits in the status register for (uint32_t chan = 0; chan < 16; ++chan) { if ((afec_get_interrupt_status(afec) & (1 << chan)) != 0) { (void)afec_channel_get_value(afec, static_cast<afec_channel_num>(chan)); } } afec_start_software_conversion(afec); }
/* * Coverts the temp sensor volatge to temp * */ static void afec_temp_sensor_end_conversion(void) { volatile uint32_t g_ul_value = 0; int32_t ul_vol; g_ul_value = afec_channel_get_value(AFEC0, AFEC_TEMPERATURE_SENSOR); ul_vol = g_ul_value * VOLT_REF / MAX_DIGITAL; /* * According to datasheet, The output voltage VT = 1.44V at 27C * and the temperature slope dVT/dT = 4.7 mV/C */ ul_temp = (ul_vol - 1440) * 100 / 470 + 27; }
// Read the most recent 12-bit result from a channel uint16_t AnalogInReadChannel(AnalogChannelNumber channel) { if ((unsigned int)channel < numChannels) { #if SAM3XA || SAM4S return adc_get_channel_value(ADC, GetAdcChannel(channel)); #elif SAM4E || SAME70 return afec_channel_get_value(GetAfec(channel), GetAfecChannel(channel)); #endif } return 0; }
uint32_t getAnalog(int channel) { uint32_t result; if (channel == 0){ afec_channel_enable(AFEC0, AFEC_CHANNEL_0); afec_start_software_conversion(AFEC0); while (!(afec_get_interrupt_status(AFEC0) & (1 << AFEC_CHANNEL_0))); //delay_ms(10); result = afec_channel_get_value(AFEC0, AFEC_CHANNEL_0); //afec_channel_disable(AFEC0, AFEC_CHANNEL_0); } else{ afec_channel_enable(AFEC0, AFEC_CHANNEL_1); afec_start_software_conversion(AFEC0); while (!(afec_get_interrupt_status(AFEC0) & (1 << AFEC_CHANNEL_1))); //delay_ms(10); result = afec_channel_get_value(AFEC0, AFEC_CHANNEL_1); //afec_channel_disable(AFEC0, AFEC_CHANNEL_1); } return result; }
/** * \brief Send a JSON string representing the board status. * * \param name Not used. * \param recv_buf Receive buffer. * \param recv_len Receive buffer length. * * \return 0. */ static int cgi_status(const char *name, char *recv_buf, size_t recv_len) { UNUSED(recv_buf); UNUSED(recv_len); UNUSED(name); volatile uint16_t volt; uint32_t length = 0; uint32_t i; status.tot_req++; volt = afec_channel_get_value(AFEC0, AFEC_CHANNEL_5); status.up_time = xTaskGetTickCount() / 1000; /* Update board status. */ sprintf(status.last_connected_ip, "%d.%d.%d.%d", IP_ADDR_TO_INT_TUPLE(g_pcb->remote_ip.addr)); sprintf(status.local_ip, "%d.%d.%d.%d", IP_ADDR_TO_INT_TUPLE(g_pcb->local_ip.addr)); length += sprintf((char *)tx_buf, "{\"local_ip\":\"%s\",\"last_connected_ip\":\"%s\", \"temp\":%d.%d, \"mag\":\"", status.local_ip, status.last_connected_ip, status.internal_temp / 100, status.internal_temp % 100); /* Update magnitude graph (98 + 1). */ for (i = 0; i < 98; ++i) { length += sprintf((char *)tx_buf + length, "%d|", mag_in_buffer_int[i]); } length += sprintf((char *)tx_buf + length, "%d\"", mag_in_buffer_int[i]); /* Remaining board status. */ length += sprintf((char *)tx_buf + length, ",\"volt\":%d,\"up_time\":%ld,\"tot_req\":%d, \"leds\":{ \"0\":\"%d\", \"1\":\"%d\", \"2\":\"%d\"}}", volt, status.up_time, status.tot_req, GET_LED_STATUS(status.led_status, 0), GET_LED_STATUS(status.led_status, 1), GET_LED_STATUS(status.led_status, 2)); /* Send answer. */ http_sendOk(HTTP_CONTENT_JSON); http_write((char const *)tx_buf, strlen((char *)tx_buf)); return 0; }
/** * \brief Send the potentiometer voltage. * * \param name Not used. * \param recv_buf Receive buffer. * \param recv_len Receive buffer length. * * \return 0. */ static int cgi_resistor(const char *name, char *recv_buf, size_t recv_len) { UNUSED(recv_buf); UNUSED(recv_len); UNUSED(name); u16_t volt; volt = afec_channel_get_value(AFEC0, AFEC_CHANNEL_5) * 10000 / 4096; sprintf((char *)tx_buf, "[ \"%d.%dV\" ]", volt / 1000, volt % 1000); http_sendOk(HTTP_CONTENT_JSON); http_write((const char *)tx_buf, strlen((char *)tx_buf)); return 0; }
/** * \brief ACC example application entry point. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint32_t uc_key; int16_t s_volt = 0; uint32_t ul_value = 0; volatile uint32_t ul_status = 0x0; int32_t l_volt_dac0 = 0; /* Initialize the system */ sysclk_init(); board_init(); /* Initialize debug console */ configure_console(); /* Output example information */ puts(STRING_HEADER); /* Initialize DACC */ /* Enable clock for DACC */ pmc_enable_periph_clk(ID_DACC); /* Reset DACC registers */ dacc_reset(DACC); /* External trigger mode disabled. DACC in free running mode. */ dacc_disable_trigger(DACC, DACC_CHANNEL_0); /* Half word transfer mode */ dacc_set_transfer_mode(DACC, 0); #if (SAM3S) || (SAM3XA) /* Power save: * sleep mode - 0 (disabled) * fast wakeup - 0 (disabled) */ dacc_set_power_save(DACC, 0, 0); #endif /* Enable output channel DACC_CHANNEL */ dacc_enable_channel(DACC, DACC_CHANNEL_0); /* Setup analog current */ dacc_set_analog_control(DACC, DACC_ANALOG_CONTROL); /* Set DAC0 output at ADVREF/2. The DAC formula is: * * (5/6 * VOLT_REF) - (1/6 * VOLT_REF) volt - (1/6 * VOLT_REF) * ----------------------------------- = -------------------------- * MAX_DIGITAL digit * * Here, digit = MAX_DIGITAL/2 */ dacc_write_conversion_data(DACC, MAX_DIGITAL / 2, DACC_CHANNEL_0); l_volt_dac0 = (MAX_DIGITAL / 2) * (2 * VOLT_REF / 3) / MAX_DIGITAL + VOLT_REF / 6; /* Enable clock for AFEC */ afec_enable(AFEC0); struct afec_config afec_cfg; afec_get_config_defaults(&afec_cfg); /* Initialize AFEC */ afec_init(AFEC0, &afec_cfg); struct afec_ch_config afec_ch_cfg; afec_ch_get_config_defaults(&afec_ch_cfg); afec_ch_cfg.gain = AFEC_GAINVALUE_0; afec_ch_set_config(AFEC0, AFEC_CHANNEL_POTENTIOMETER, &afec_ch_cfg); /* * Because the internal ADC offset is 0x200, it should cancel it and shift * down to 0. */ afec_channel_set_analog_offset(AFEC0, AFEC_CHANNEL_POTENTIOMETER, 0x200); afec_set_trigger(AFEC0, AFEC_TRIG_SW); /* Enable channel for potentiometer. */ afec_channel_enable(AFEC0, AFEC_CHANNEL_POTENTIOMETER); /* Enable clock for ACC */ pmc_enable_periph_clk(ID_ACC); /* Initialize ACC */ acc_init(ACC, ACC_MR_SELPLUS_AFE0_AD0, ACC_MR_SELMINUS_DAC0, ACC_MR_EDGETYP_ANY, ACC_MR_INV_DIS); /* Enable ACC interrupt */ NVIC_EnableIRQ(ACC_IRQn); /* Enable */ acc_enable_interrupt(ACC); dsplay_menu(); while (1) { while (usart_read(CONSOLE_UART, &uc_key)) { } printf("input: %c\r\n", uc_key); switch (uc_key) { case 's': case 'S': printf("Input DAC0 output voltage (%d~%d mv): ", (VOLT_REF / 6), (VOLT_REF * 5 / 6)); s_volt = get_input_voltage(); puts("\r"); if (s_volt > 0) { l_volt_dac0 = s_volt; /* The DAC formula is: * * (5/6 * VOLT_REF) - (1/6 * VOLT_REF) volt - (1/6 * VOLT_REF) * ----------------------------------- = -------------------------- * MAX_DIGITAL digit * */ ul_value = ((s_volt - (VOLT_REF / 6)) * (MAX_DIGITAL * 6) / 4) / VOLT_REF; dacc_write_conversion_data(DACC, ul_value, DACC_CHANNEL_0); puts("-I- Set ok\r"); } else { puts("-I- Input voltage is invalid\r"); } break; case 'v': case 'V': /* Start conversion */ afec_start_software_conversion(AFEC0); ul_status = afec_get_interrupt_status(AFEC0); while ((ul_status & AFEC_ISR_EOC0) != AFEC_ISR_EOC0) { ul_status = afec_get_interrupt_status(AFEC0); } /* Conversion is done */ ul_value = afec_channel_get_value(AFEC0, AFEC_CHANNEL_POTENTIOMETER); /* * Convert AFEC sample data to voltage value: * voltage value = (sample data / max. resolution) * reference voltage */ s_volt = (ul_value * VOLT_REF) / MAX_DIGITAL; printf("-I- Voltage on potentiometer(AD0) is %d mv\n\r", s_volt); printf("-I- Voltage on DAC0 is %ld mv \n\r", (long)l_volt_dac0); break; case 'm': case 'M': dsplay_menu(); break; } } }
/** * \brief DSP task core function. * * \param pvParameters Junk parameter. */ static void dsp_task(void *pvParameters) { uint32_t i, j; uint32_t adc_potentiometer = 0; const float32_t display_factor = 700; float32_t bin; float32_t tmp; /* Just to avoid compiler warnings. */ UNUSED(pvParameters); /* Wait for user to read instructions. */ WAIT_FOR_TOUCH_EVENT; dsp_configure_button2(); dsp_configure_tc(); dsp_configure_adc(); dsp_configure_dacc(); dsp_sin_init(); /* Enable PDC transfer. */ dsp_clean_buffer(dacc_out_buffer[0], SAMPLE_BLOCK_SIZE); dsp_clean_buffer(dacc_out_buffer[1], SAMPLE_BLOCK_SIZE); dsp_clean_buffer(dacc_out_buffer[2], SAMPLE_BLOCK_SIZE); g_pdc_packet.ul_addr = (uint32_t) dacc_out_buffer[0]; g_pdc_packet.ul_size = SAMPLE_BLOCK_SIZE; g_pdc_nextpacket.ul_addr = (uint32_t) dacc_out_buffer[1]; g_pdc_nextpacket.ul_size = SAMPLE_BLOCK_SIZE; pdc_tx_init(dacc_pdc, &g_pdc_packet, &g_pdc_nextpacket); pdc_enable_transfer(dacc_pdc, PERIPH_PTCR_TXTEN); /* Start Timer counter 0 channel 0 for ADC-DACC trigger. */ tc_start(TC0, 1); /** DSP task loop. */ while (1) { /* Using input wave signal. */ if (g_mode_select == 1) { if (xSemaphoreTake(dacc_notification_semaphore, max_block_time_ticks)) { /* Copy dsp_sfx into wav_in_buffer and prepare Q15 format. */ for (i = 0, j = 0; i < 512; ++j) { tmp = (((dsp_sfx[offset] - (float) 128)) / 100); /* Store Audio sample real part in memory. */ wav_in_buffer[i++] = tmp; /* Store Audio sample imaginary part in memory. */ wav_in_buffer[i++] = 0; /* Prepare buffer for DACC. */ dacc_out_buffer[cur_dac_buffer][j] = (uint16_t)((tmp * 100 * sin_buffer[slider_pos][j]) + 128); /* Update the wave file offset pointer. */ if (offset < dsp_sfx_size - 1) { offset++; } else { offset = WAVE_OFFSET; } } } else { /* Ensure we take the semaphore. */ continue; } } else { /* Using generated input sinus signal. */ if (xSemaphoreTake(dacc_notification_semaphore, max_block_time_ticks)) { /* * Read potentiometer value and generate * sinus signal accordingly. */ adc_potentiometer_old = adc_potentiometer; adc_potentiometer = (afec_channel_get_value(AFEC0, ADC_CHANNEL_POTENTIOMETER)); adc_potentiometer = adc_potentiometer * 10000 / 4096; if (adc_potentiometer > adc_potentiometer_old && adc_potentiometer - adc_potentiometer_old < ADC_POTENTIOMETER_NOISE) { adc_potentiometer = adc_potentiometer_old; } else if (adc_potentiometer_old > adc_potentiometer && adc_potentiometer_old - adc_potentiometer < ADC_POTENTIOMETER_NOISE) { adc_potentiometer = adc_potentiometer_old; } /* Generate the sinus signal. */ dsp_sin_input(adc_potentiometer); /* Prepare buffer for DACC. */ for (i = 0, j = 0; i < 512; ++j, i += 2) { /* * 2048 is the 0 position for DACC. * 50 is an amplification factor. */ dacc_out_buffer[cur_dac_buffer][j] = (uint16_t)((wav_in_buffer[i] * sin_buffer[slider_pos][j]) * 50 + 2048); } } } afec_start_software_conversion(AFEC0); /* Perform FFT and bin Magnitude calculation */ arm_float_to_q15(wav_in_buffer, cfft_q15, SAMPLE_BLOCK_SIZE * 2); arm_cfft_radix4_init_q15(&cfft_instance, SAMPLE_BLOCK_SIZE, 0, 1); arm_cfft_radix4_q15(&cfft_instance, cfft_q15); arm_cmplx_mag_q15(cfft_q15, mag_in_buffer_q15, SAMPLE_BLOCK_SIZE); arm_q15_to_float(mag_in_buffer_q15, mag_in_buffer, 128); /* * Prepare bins rendering for web page and display. * Limit to 99, even if we got 128 magnitudes to display. * Bins are printed using col, incremented by mean of 2 to keep * a clean rendering. Hence we cannot render all the magnitudes, * because of the screen width. It would require a 128*2 space. */ for (i = 0; i < 99; ++i) { bin = (mag_in_buffer[i] * display_factor); if (bin > 0) { if (bin > 98) { bin = 98; } mag_in_buffer_int[i] = (uint32_t)bin; } else { mag_in_buffer_int[i] = 0; } } /* Notify GFX task to start refreshing screen (if necessary). */ if (g_mode_select == 1 || (g_mode_select == 0 && adc_potentiometer != adc_potentiometer_old)) { xSemaphoreGive(gfx_notification_semaphore); } } }
static void afec1_temp_adcRead_ch2(void) { afec0_data = afec_channel_get_value(AFEC1, AFEC_CHANNEL_2); TempAdcRaw.signal[7].adcRaw = afec0_data; TempAdcRaw.signal[7].timestamp = getSystemTimeMilliseconds(); }
static void afec0_temp_adcRead_tempSensor(void) { afec0_data = afec_channel_get_value(AFEC0, AFEC_TEMPERATURE_SENSOR); TempAdcRaw.signal[8].adcRaw = afec0_data; TempAdcRaw.signal[8].timestamp = getSystemTimeMilliseconds(); }
/** * \brief AFEC0 EOC1 interrupt callback function. */ static void afec_eoc_1(void) { g_afec1_sample_data = afec_channel_get_value(AFEC0, AFEC_CHANNEL_1); puts("AFEC0 Channel 1 Voltage:"); print_float(g_afec1_sample_data * VOLT_REF / g_max_digital); }
/** * \brief AFEC interrupt callback function. */ static void afec_temp_sensor_end_conversion(void) { g_ul_value = afec_channel_get_value(AFEC0, AFEC_TEMPERATURE_SENSOR); is_conversion_done = true; }