adc_clock_speed_t adc_clock_speed_kHz_set (adc_t adc, adc_clock_speed_t clock_speed_kHz) { uint32_t clock_speed; uint16_t settle_clocks; uint16_t sample_clocks; static const uint8_t adc_settle_table[] = {3, 5, 9, 17}; static const uint16_t adc_sample_table[] = {0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, 768, 832, 896, 960}; /* For the SAM7 the max clock speed is 5 MHz for 10 bit and 8 MHz for 8 bit. */ clock_speed = clock_speed_kHz * 1000; adc_clock_divisor_set (adc, ((F_CPU / 2) + clock_speed - 1) / clock_speed); clock_speed = (F_CPU / 2) / adc->clock_divisor; /* With 24 MHz clock need 4.8 clocks to settle on SAM4S. This is only needed when switching gain or offset, say when converting a sequence of channels. Let's play safe and allocate the maximum 17 clocks. */ BITS_INSERT (adc->MR, 3, 20, 21); /* With 24 MHz clock need 288 clocks to start up on SAM4S. Let's allocate 512. TODO, scan through table to find appropriate value. */ BITS_INSERT (adc->MR, 8, 16, 19); /* With 24 MHz clock need 3.4 clocks to sample on SAM4S. Let's allocate 4. */ BITS_INSERT (adc->MR, 3, 24, 27); return clock_speed / 1000; }
/** * @details No details. */ int mcpwm_set_deadtime(mcpwm_module_t *module, enum mcpwm_deadtime_unit_e unit, unsigned int value) { // Check for valid module if( module == NULL || module->base_address == NULL ) {// Invalid module return MCPWM_E_MODULE; } if( unit == MCPWM_DEADTIME_UNITA ) {// Set DTA to supplied value *(module->base_address + MCPWM_OFFSET_PxDTCON1) = BITS_INSERT(*(module->base_address + MCPWM_OFFSET_PxDTCON1),MCPWM_BITMASK_DTA,value); } else if( unit == MCPWM_DEADTIME_UNITB ) {// Set DTB to supplied value *(module->base_address + MCPWM_OFFSET_PxDTCON1) = BITS_INSERT(*(module->base_address + MCPWM_OFFSET_PxDTCON1),MCPWM_BITMASK_DTB,value); } else {// Unknown unit return MCPWM_E_INPUT; } return MCPWM_E_NONE; }
/** Initialise flash memory controller. */ static void mcu_flash_init (void) { #if 0 /* TODO */ switch (MCU_FLASH_READ_CYCLES) { case 1: /* Set 0 flash wait states for reading, 1 for writing. */ EEFC->MC_FMR = MC_FWS_0FWS; break; case 2: /* Set 1 flash wait state for reading, 2 for writing. */ EEFC->MC_FMR = MC_FWS_1FWS; break; case 3: /* Set 2 flash wait states for reading, 3 for writing. */ EEFC->MC_FMR = MC_FWS_2FWS; break; default: /* Set 3 flash wait states for reading, 4 for writing. */ EEFC->MC_FMR = MC_FWS_3FWS; break; } /* Set number of MCK cycles per microsecond for the Flash microsecond cycle number (FMCN) field of the Flash mode register (FMR). */ BITS_INSERT (EEFC->MC_FMR, (uint16_t) (F_CPU / 1e6), 16, 23); #endif }
/* Set the ADC triggering. */ void adc_trigger_set (adc_t adc, adc_trigger_t trigger) { adc->trigger = trigger; /* Could also handle FREERUN here where no triggering is required. */ if (trigger == ADC_TRIGGER_SW) { BITS_INSERT (adc->MR, 0, 0, 0); } else { /* Select trigger. */ BITS_INSERT (adc->MR, trigger - ADC_TRIGGER_EXT, 1, 3); /* Enable trigger. */ BITS_INSERT (adc->MR, 1, 0, 0); } }
/** * @details No details. */ int mcpwm_enable_pins(mcpwm_module_t *module, unsigned int pins) { // Check for valid module if( module == NULL || module->base_address == NULL ) {// Invalid module return MCPWM_E_MODULE; } *(module->base_address + MCPWM_OFFSET_PWMxCON1) = BITS_INSERT(*(module->base_address + MCPWM_OFFSET_PWMxCON1),0x00FF,pins); return MCPWM_E_NONE; }
/* Set the clock divider (prescaler). */ static void adc_clock_divisor_set (adc_t adc, adc_clock_divisor_t clock_divisor) { /* The SAM4S requires 20 clocks per sample. ADC_CLOCK = (F_CPU / 2) / clock_divisor. */ if (clock_divisor >= 256) clock_divisor = 256; BITS_INSERT (adc->MR, clock_divisor - 1, 8, 15); adc->clock_divisor = clock_divisor; }
/** Initalises the ADC registers for polling operation. */ adc_t adc_init (const adc_cfg_t *cfg) { adc_sample_t dummy; adc_dev_t *adc; const adc_cfg_t adc_default_cfg = { .bits = 10, .channel = 0, .clock_speed_kHz = 1000 }; if (adc_devices_num >= ADC_DEVICES_NUM) return 0; if (adc_devices_num == 0) { /* The clock only needs to be enabled when sampling. The clock is automatically started for the SAM7. */ mcu_pmc_enable (ID_ADC); adc_reset (); } adc = adc_devices + adc_devices_num; adc_devices_num++; adc->MR = 0; /* The transfer field must have a value of 2. */ BITS_INSERT (adc->MR, 2, 28, 29); if (!cfg) cfg = &adc_default_cfg; adc_config_set (adc, cfg); /* Note, the ADC is not configured until adc_config is called. */ adc_config (adc); #if 0 /* I'm not sure why a dummy read is required; it is probably a quirk of the SAM7. This will require a software trigger... */ adc_read (adc, &dummy, sizeof (dummy)); #endif return adc; } /** Returns true if a conversion has finished. */ bool adc_ready_p (adc_t adc) { return (ADC->ADC_ISR & ADC_ISR_DRDY) != 0; } /** Blocking read. This will hang if a trigger is not supplied (except for software triggering mode). */ int8_t adc_read (adc_t adc, void *buffer, uint16_t size) { uint16_t i; uint16_t samples; adc_sample_t *data; adc_config (adc); samples = size / sizeof (adc_sample_t); data = buffer; for (i = 0; i < samples; i++) { /* When the ADC peripheral gets a trigger, it converts all the enabled channels consecutively in numerical order. */ if (adc->trigger == ADC_TRIGGER_SW) adc_conversion_start (adc); /* Should have timeout, especially for external trigger. */ while (!adc_ready_p (adc)) continue; data[i] = ADC->ADC_LCDR; } /* Disable channel. */ ADC->ADC_CHDR = ~0; return samples * sizeof (adc_sample_t); }