Thanks Andy
Code: Select all
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <pio/pio.h>
#include <dbgu/dbgu.h>
#include <aic/aic.h>
#include <adc/adc.h>
#include <pmc/pmc.h>
#include <rtt/rtt.h>
#include <utility/trace.h>
#include <usb/device/cdc-serial/CDCDSerialDriver.h>
#include <usb/device/cdc-serial/CDCDSerialDriverDescriptors.h>
#include <string.h>
#include <stdio.h>
void ConfigureRtt(int timeS);
static void ISR_Adc(void);
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Device is in the main menu.
#define STATE_MAINMENU 0
/// User is setting an alarm time
#define STATE_SETALARM 1
/// Use for power management
#define STATE_IDLE 0
/// The USB device is in suspend state
#define STATE_SUSPEND 4
/// The USB device is in resume state
#define STATE_RESUME 5
/// Size in bytes of the buffer used for reading data from the USB & USART
#define DATABUFFERSIZE \
BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN)
/// State of USB, for suspend and resume
unsigned char USBState = STATE_IDLE;
/// Buffer for storing incoming USB data.
static unsigned char usbBuffer[DATABUFFERSIZE];
static int SendReady = 0;
/// Indicates that the conversion is finished.
static volatile unsigned char conversionDone;
static float Freq = 1;
/// Define AT91C_BASE_RTTC if not already done
#if !defined(AT91C_BASE_RTTC)
#define AT91C_BASE_RTTC AT91C_BASE_RTTC0
#endif
/// Pio pins to configure.
#ifdef PINS_ADC
static const Pin pinsADC[] = {PINS_ADC};
#endif
/// ADC
#define BOARD_ADC_FREQ 5000000
#define ADC_FREQ 10
#define ADC_VREF 3300 // 3.3 * 1000
#define ADC_NUM_1 ADC_CHANNEL_5
#define ADC_NUM_2 ADC_CHANNEL_6
#define ADC_NUM_3 ADC_CHANNEL_7
//#define ADC_NUM_4 ADC_CHANNEL_5
//////////////////////////////////////////////////////////////////////////////////////////
/* bits */
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
#define BIT3 0x00000008
#define BIT4 0x00000010
#define BIT5 0x00000020
#define BIT6 0x00000040
#define BIT7 0x00000080
#define BIT8 0x00000100
#define BIT9 0x00000200
#define BIT10 0x00000400
#define BIT11 0x00000800
#define BIT12 0x00001000
#define BIT13 0x00002000
#define BIT14 0x00004000
#define BIT15 0x00008000
#define BIT16 0x00010000
#define BIT17 0x00020000
#define BIT18 0x00040000
#define BIT19 0x00080000
#define BIT20 0x00100000
#define BIT21 0x00200000
#define BIT22 0x00400000
#define BIT23 0x00800000
#define BIT24 0x01000000
#define BIT25 0x02000000
#define BIT26 0x04000000
#define BIT27 0x08000000
#define BIT28 0x10000000
#define BIT29 0x20000000
#define BIT30 0x40000000
#define BIT31 0x80000000
// SPI
AT91PS_SPI s_pSpi = AT91C_BASE_SPI;
AT91PS_PIO s_pPio = AT91C_BASE_PIOA;
AT91PS_PMC s_pPMC = AT91C_BASE_PMC;
AT91PS_PDC s_pPDC = AT91C_BASE_PDC_SPI;
// ADC
AT91PS_ADC a_pADC = AT91C_BASE_ADC;
AT91PS_PMC a_pPMC = AT91C_BASE_PMC;
AT91PS_PIO a_pPio = AT91C_BASE_PIOA;
AT91PS_SYS a_pSys = AT91C_BASE_SYS;
// GPIO and other
AT91PS_PIO u_pPio = AT91C_BASE_PIOA;
AT91PS_PMC u_pPMC = AT91C_BASE_PMC;
AT91PS_USART u_pUSART0 = AT91C_BASE_US0;
AT91PS_USART u_pUSART1 = AT91C_BASE_US1;
AT91PS_PDC u_pPDC0 = AT91C_BASE_PDC_US0;
AT91PS_PDC u_pPDC1 = AT91C_BASE_PDC_US1;
AT91PS_MC u_pMC = AT91C_BASE_MC;
AT91PS_AIC u_pAic = AT91C_BASE_AIC;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// Current device state.
volatile unsigned char state;
/// New alarm time being currently entered.
volatile unsigned int newAlarm;
/// Indicates if an alarm has occured but has not been cleared.
volatile unsigned char alarmed;
#if defined (at91sam7s)
//------------------------------------------------------------------------------
/// Put the CPU in 32kHz, disable PLL, main oscillator
/// Put voltage regulator in standby mode
//------------------------------------------------------------------------------
void LowPowerMode(void)
{
// MCK=48MHz to MCK=32kHz
// MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
// MCK=SLCK : then change prescaler
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
// disable PLL
AT91C_BASE_PMC->PMC_PLLR = 0;
// Disable Main Oscillator
AT91C_BASE_PMC->PMC_MOR = 0;
// Voltage regulator in standby mode : Enable VREG Low Power Mode
AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY;
PMC_DisableProcessorClock();
}
//------------------------------------------------------------------------------
/// Put voltage regulator in normal mode
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
//------------------------------------------------------------------------------
void NormalPowerMode(void)
{
// Voltage regulator in normal mode : Disable VREG Low Power Mode
AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY;
// MCK=32kHz to MCK=48MHz
// enable Main Oscillator
AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) );
// enable PLL@96MHz
AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) |
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
(AT91C_CKGR_MUL & (0x48<<16)));
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) );
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
// MCK=SLCK/2 : change prescaler first
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
// MCK=PLLCK/2 : then change source
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
}
#endif
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
// Simple delay
void Delay (unsigned long a) {
while (--a!=0);
}
//------------------------------------------------------------------------------
/// Callback invoked when data has been received on the USB.
//------------------------------------------------------------------------------
static void UsbDataReceived(unsigned int unused,
unsigned char status,
unsigned int received,
unsigned int remaining)
{
int freq;
// Check that data has been received successfully
if (status == USBD_STATUS_SUCCESS) {
// decode the string
// Decode the data recieved
if (received == sizeof(int)){
// flash the led so that we know data received
// Configure RTT
if ((freq >= 1) && freq <= 100)
ConfigureRtt(freq);
}
// Check if bytes have been discarded
if ((received == DATABUFFERSIZE) && (remaining > 0)) {
TRACE_WARNING(
"UsbDataReceived: %u bytes discarded\n\r",
remaining);
}
}
else {
TRACE_WARNING( "UsbDataReceived: Transfer error\n\r");
}
}
void ADCInit (void)
{
ADC_Initialize( AT91C_BASE_ADC,
AT91C_ID_ADC,
AT91C_ADC_TRGEN_DIS,
0,
AT91C_ADC_SLEEP_NORMAL_MODE,
AT91C_ADC_LOWRES_10_BIT,
BOARD_MCK,
BOARD_ADC_FREQ,
10,
1200);
ADC_EnableChannel(AT91C_BASE_ADC, ADC_NUM_1);
ADC_EnableChannel(AT91C_BASE_ADC, ADC_NUM_2);
ADC_EnableChannel(AT91C_BASE_ADC, ADC_NUM_3);
// ADC_EnableChannel(AT91C_BASE_ADC, ADC_NUM_4);
AIC_ConfigureIT(AT91C_ID_ADC, 0, ISR_Adc);
AIC_EnableIT(AT91C_ID_ADC);
}
void InitMMA(void) {
//enable the clock of the PIO
a_pPMC->PMC_PCER = 1 << AT91C_ID_PIOA;
// Config
// Configure all ports as Input
// a_pPio->PIO_ODR = 0xffffffff; Delay(100);
// Enable all ports
//a_pPio->PIO_PER = 0xffffffff; Delay(100);
// Disable Pull-up resistor
//a_pSys->PIOA_PPUDR = 0xffffffff; Delay(100);
// Set G_SEL1, G_SEL2 to low and SM to high
a_pPio->PIO_SODR = 0x20000000; // Set SM to HIGH
a_pPio->PIO_SODR = 0x10000000; // Set G_SEL1 to HIGH
// a_pPio->PIO_CODR = 0x18000000; // Set G_SEL1, G_SEL2 to LOW
a_pPio->PIO_CODR = 0x08000000; // Set G_SEL2 to LOW
// Set G_SEL1, G_SEL2 and SM as output
a_pPio->PIO_OER = 0x38000000;
}
//-----------------------------------------------------------------------------
/// Convert a digital value in milivolt
/// /param valueToconvert Value to convert in milivolt
//-----------------------------------------------------------------------------
static unsigned int ConvHex2mV( unsigned int valueToConvert )
{
return( (ADC_VREF * valueToConvert)/0x3FF);
}
//------------------------------------------------------------------------------
/// Interrupt handler for the ADC. Signals that the conversion is finished by
/// setting a flag variable.
//------------------------------------------------------------------------------
static void ISR_Adc(void)
{
unsigned int status;
unsigned int id_channel;
status = ADC_GetStatus(AT91C_BASE_ADC);
//TRACE_DEBUG("status =0x%X\n\r", status);
//TRACE_DEBUG("adc_imr=0x%X\n\r", ADC_GetInterruptMaskStatus());
for(id_channel=ADC_NUM_1;id_channel<=ADC_NUM_3;id_channel++) {
if (ADC_IsChannelInterruptStatusSet(status, id_channel)) {
//TRACE_DEBUG("channel %d\n\r", id_channel);
ADC_DisableIt(AT91C_BASE_ADC, id_channel);
conversionDone |= 1<<id_channel;
}
}
}
//------------------------------------------------------------------------------
/// Interrupt handler for the RTT. Displays the current time on the DBGU.
//------------------------------------------------------------------------------
void ISR_Rtt(void)
{
unsigned int status;
char text[200];
int i;
float timeInc = 0.1 / Freq;
static int numConv = 1;
unsigned int id_channel;
static double volt[8] = {0};
// Get RTT status
status = RTT_GetStatus(AT91C_BASE_RTTC);
// Time has changed, refresh display
if ((status & AT91C_RTTC_RTTINC) == AT91C_RTTC_RTTINC) {
// RefreshDisplay();
}
// Alarm
if ((status & AT91C_RTTC_ALMS) == AT91C_RTTC_ALMS) {
alarmed = 1;
//RefreshDisplay();
}
if (SendReady){
conversionDone = 0;
// Start measurement
ADC_EnableIt(AT91C_BASE_ADC, ADC_NUM_1);
ADC_EnableIt(AT91C_BASE_ADC, ADC_NUM_2);
ADC_EnableIt(AT91C_BASE_ADC, ADC_NUM_3);
// ADC_EnableIt(AT91C_BASE_ADC, ADC_NUM_4);
// Start measurement
ADC_StartConversion(AT91C_BASE_ADC);
while( conversionDone != ((1<<ADC_NUM_1)|(1<<ADC_NUM_2)|(1<<ADC_NUM_3)) );
for(id_channel=ADC_NUM_1;id_channel<=ADC_NUM_3;id_channel++) {
Volt[id_channel] += ConvHex2mV(ADC_GetConvertedData(AT91C_BASE_ADC, id_channel));
}
if (numConv == ADC_FREQ){
// update the information before sending
// average out the voltage
// Send current buffer through the USB
// here i'm averaging the voltage over ten measurements then printing to string
sprintf(text, "-- Count %d num %d --\n\r", count,numConv);
while (CDCDSerialDriver_Write(text, (unsigned int)strlen(text), 0, 0) != USBD_STATUS_SUCCESS);
numConv = 0;
// clear the voltages for next time
for (i = 0; i < 8; i++){
Volt[i] = 0;
}
}
numConv++;
}
}
//------------------------------------------------------------------------------
/// Configures the RTT to generate a one second tick, which triggers the RTTINC
/// interrupt.
//------------------------------------------------------------------------------
void ConfigureRtt(int timeS)
{
unsigned int previousTime;
unsigned int timeStep = 32768;
// if timeStep is zero the update 1s intervals
if (timeS == 0){ timeStep = 32768;
// else update the frequency
} else {
timeStep = 32768/timeS;
}
// Configure RTT for a 1 second tick interrupt,
RTT_SetPrescaler(AT91C_BASE_RTTC, timeStep);
previousTime = RTT_GetTime(AT91C_BASE_RTTC);
while (previousTime == RTT_GetTime(AT91C_BASE_RTTC));
// Enable RTT interrupt
AIC_ConfigureIT(AT91C_ID_SYS, 0, ISR_Rtt);
AIC_EnableIT(AT91C_ID_SYS);
RTT_EnableIT(AT91C_BASE_RTTC, AT91C_RTTC_RTTINCIEN);
}
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the RTT, displays the current time and allows the user to
/// perform several actions: clear the timer, set an alarm, etc.
//------------------------------------------------------------------------------
int main(void)
{
int i;
// Enable DBGU
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
#ifdef PINS_ADC
PIO_Configure(pinsADC, PIO_LISTSIZE(pinsADC));
#endif
// Configure RTT
ConfigureRtt(1);
// BOT driver initialization
CDCDSerialDriver_Initialize();
// InitMAM
InitMMA();
// InitADC
ADCInit();
// Initialize state machine
state = STATE_MAINMENU;
alarmed = 0;
// User input loop
while (1) {
// Device is not configured
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
// Connect pull-up, wait for configuration
USBD_Connect();
while (USBD_GetState() < USBD_STATE_CONFIGURED);
// Start receiving data on the USB
CDCDSerialDriver_Read(usbBuffer, DATABUFFERSIZE, (TransferCallback) UsbDataReceived, 0);
}
SendReady = 1;
if( USBState == STATE_SUSPEND ) {
//TRACE_DEBUG("suspend !\n\r");
LowPowerMode();
USBState = STATE_IDLE;
}
if( USBState == STATE_RESUME ) {
// Return in normal MODE
// TRACE_DEBUG("resume !\n\r");
NormalPowerMode();
USBState = STATE_IDLE;
}
}
}