commiting examples

This commit is contained in:
Nicolas Trimborn
2021-07-26 10:32:22 +02:00
parent 76cd702edc
commit 312768d2cf
589 changed files with 464854 additions and 446 deletions

View File

@@ -0,0 +1,53 @@
#include <samd21g18a.h>
#include "ADC.h"
volatile uint16_t adc_value;
void ADC_init(void)
{
/* enable peripheral clock */
PM->APBCMASK.bit.ADC_ = 1;
/* enable generic clock */
GCLK->CLKCTRL.bit.ID = GCLK_CLKCTRL_ID_ADC_Val; // configure generic clock for ADC
GCLK->CLKCTRL.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val; // source is generic clock generator 0
GCLK->CLKCTRL.bit.CLKEN = 1; // enable generic clock
/* select GPIO pins alternative function */
PORT->Group[1].PINCFG[8].bit.PMUXEN = 1; // enable alternative function for pin PB08
PORT->Group[1].PINCFG[3].bit.PMUXEN = 1; // enable alternative function for pin PA03 (analog function AREF)
PORT->Group[1].PMUX[4].bit.PMUXE = MUX_PB08B_ADC_AIN2; // PB08 alternative function B (ADC in 2)
/* configure peripheral */
ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV256_Val; // prescaler
ADC->CTRLB.bit.DIFFMODE = 0x00; // single-ended mode
ADC->CTRLB.bit.LEFTADJ = 0x00; // right adjusted result
ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_16BIT_Val; // conversion resolution is 16 bit (for accumulation)
ADC->CTRLB.bit.FREERUN = 1; // fee run mode
ADC->AVGCTRL.bit.SAMPLENUM = ADC_AVGCTRL_SAMPLENUM_16_Val; // result is the accumulation of 16 samples
ADC->AVGCTRL.bit.ADJRES = 0x04; // result is averaged over 16 samples
ADC->INPUTCTRL.bit.MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val; // negative input is internal ground
ADC->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_PIN2_Val; // positive input on ADC in 2 (pin PB08)
/* enable result ready interrupt */
ADC->INTENSET.reg = ADC_INTENSET_RESRDY;
NVIC_EnableIRQ(ADC_IRQn);
/* enable peripheral */
ADC->CTRLA.reg |= ADC_CTRLA_ENABLE;
}
void ADC_deinit(void)
{
/* disable result ready interrupt */
ADC->INTENCLR.reg = ADC_INTENCLR_RESRDY;
NVIC_DisableIRQ(ADC_IRQn);
}
void ADC_Handler(void)
{
adc_value = (ADC->RESULT.reg);
}

View File

@@ -0,0 +1,9 @@
#ifndef ADC_H_
#define ADC_H_
extern volatile uint16_t adc_value;
void ADC_init(void);
void ADC_deinit(void);
#endif /* ADC_H_ */

View File

@@ -0,0 +1,84 @@
#include <samd21g18a.h>
#include <string.h>
#include "DMA.h"
#define MAX_DESCRIPTORS 2
__attribute__((__aligned__(16))) static DmacDescriptor descriptor_section[MAX_DESCRIPTORS];
__attribute__((__aligned__(16))) static DmacDescriptor write_back_section[MAX_DESCRIPTORS];
static int used_channels = 0;
int volatile dma_frame = 0;
void DMA_init(void)
{
static int initialized = 0;
if (!initialized)
{
/* enable peripheral clock */
PM->APBBMASK.bit.DMAC_ = 1;
/* enable AHB master clock */
PM->AHBMASK.bit.DMAC_ = 1;
/* configure DMA controller */
DMAC->BASEADDR.reg = (uint32_t)descriptor_section; // descriptor memory section start
DMAC->WRBADDR.reg = (uint32_t)write_back_section; // descriptor write-back memory section start
DMAC->CTRL.bit.LVLEN0 = 1; // enable level 0 priority
DMAC->CTRL.bit.LVLEN1 = 1; // enable level 1 priority
DMAC->CTRL.bit.LVLEN2 = 1; // enable level 2 priority
DMAC->CTRL.bit.LVLEN3 = 1; // enable level 3 priority
/* DMA is initialized */
initialized = 1;
}
}
/* add the first least significant free channel with its descriptor (TODO: implement linked descriptors) */
void DMA_add_channel(int source, DmacDescriptor *descriptor)
{
/* disable DMA if enabled */
if (DMAC->CTRL.bit.DMAENABLE)
DMAC->CTRL.bit.DMAENABLE = 0;
while (DMAC->CTRL.bit.DMAENABLE)
;
/* add transfer descriptor to transfer descriptor section (before enabling channel!) */
memcpy(descriptor_section + used_channels * sizeof(DmacDescriptor), descriptor, sizeof(DmacDescriptor));
/* configure and enable first least significant free channel */
DMAC->CHID.bit.ID = used_channels++; // use first free channel
DMAC->CHCTRLB.bit.LVL = 0x00; // channel priority level 0
DMAC->CHCTRLB.bit.TRIGACT = 0x02; // one trigger each beat transfer
DMAC->CHCTRLB.bit.TRIGSRC = source; // select trigger source
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; // enable channel
/* enable DMA block transfer complete interrupt */
DMAC->CHINTENSET.bit.TCMPL = 1; // enable DMA block transfer complete interrupt
NVIC_EnableIRQ(DMAC_IRQn); // enable DMA interrupt in NVIC
}
void DMA_enable(void)
{
/* enable DMA controller */
DMAC->CTRL.bit.DMAENABLE = 1;
}
void DMAC_Handler(void)
{
//static int count;
for (int channel = 0 ; channel < used_channels ; channel++) // check interrupt for every registered channel
{
DMAC->CHID.bit.ID = channel;
if (DMAC->CHINTFLAG.bit.TCMPL && DMAC->CHINTENSET.bit.TCMPL)
{
if (DMAC->CHID.bit.ID == 0x00) // handle SPI transfer complete interrupt
{
DMAC->CHINTFLAG.bit.TCMPL = 1; // acknowledge interrupt
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; // re-enable DMA channel
}
}
}
}

View File

@@ -0,0 +1,13 @@
#ifndef DMA_H_
#define DMA_H_
#define DMA_SOURCE_SERCOM0 0x02
#define DMA_SOURCE_ADC 0x27
extern volatile int dma_frame;
void DMA_init(void);
void DMA_add_channel(int source, DmacDescriptor *descriptor);
void DMA_enable(void);
#endif /* DMA_H_ */

View File

@@ -0,0 +1,89 @@
#include <stdint.h>
#include "FIFO.h"
#define FIFO_SUCCESS 1
#define FIFO_FAIL 0
#define SIZE 1024
static uint8_t RX_buffer[SIZE];
static uint8_t *RX_head, *RX_tail;
static uint8_t TX_buffer[SIZE];
static uint8_t *TX_head, *TX_tail;
void FIFO_init(void)
{
RX_head = RX_tail = &RX_buffer[0];
TX_head = TX_tail = &TX_buffer[0];
}
int RX_FIFO_empty(void)
{
return RX_head == RX_tail;
}
int RX_FIFO_full(void)
{
uint8_t *ptr = RX_tail + 1;
if (ptr == &RX_buffer[SIZE])
ptr = &RX_buffer[0];
return ptr == RX_head;
}
int RX_FIFO_count(void)
{
return RX_tail >= RX_head ? RX_tail - RX_head : SIZE - (RX_head - RX_tail);
}
int RX_FIFO_put(uint8_t data)
{
if (RX_FIFO_full())
return FIFO_FAIL;
*RX_tail++ = data;
if (RX_tail == &RX_buffer[SIZE])
RX_tail = &RX_buffer[0];
return FIFO_SUCCESS;
}
int RX_FIFO_get(uint8_t *data)
{
if (RX_FIFO_empty())
return FIFO_FAIL;
*data = *RX_head++;
if (RX_head == &RX_buffer[SIZE])
RX_head = &RX_buffer[0];
return FIFO_SUCCESS;
}
int TX_FIFO_empty(void)
{
return TX_head == TX_tail;
}
int TX_FIFO_full(void)
{
uint8_t *ptr = TX_tail + 1;
if (ptr == &TX_buffer[SIZE])
ptr = &TX_buffer[0];
return ptr == TX_head;
}
int TX_FIFO_put(uint8_t data)
{
if (TX_FIFO_full())
return FIFO_FAIL;
*TX_tail++ = data;
if (TX_tail == &TX_buffer[SIZE])
TX_tail = &TX_buffer[0];
return FIFO_SUCCESS;
}
int TX_FIFO_get(uint8_t *data)
{
if (TX_FIFO_empty())
return FIFO_FAIL;
*data = *TX_head++;
if (TX_head == &TX_buffer[SIZE])
TX_head = &TX_buffer[0];
return FIFO_SUCCESS;
}

View File

@@ -0,0 +1,15 @@
#ifndef FIFO_H_
#define FIFO_H_
void FIFO_init(void);
int RX_FIFO_empty(void);
int RX_FIFO_full(void);
int RX_FIFO_count(void);
int RX_FIFO_put(uint8_t data);
int RX_FIFO_get(uint8_t *data);
int TX_FIFO_empty(void);
int TX_FIFO_full(void);
int TX_FIFO_put(uint8_t data);
int TX_FIFO_get(uint8_t *data);
#endif /* FIFO_H_ */

View File

@@ -0,0 +1,415 @@
#include <samd21g18a.h>
#include "NeoPixel.h"
#include "Timer.h"
#include "DMA.h"
#include "SPI.h"
#include "ADC.h"
static uint8_t pixel_buffer[NUM_PIXELS * 3]; // 3 bytes per pixel (G-R-B)
static uint8_t dma_buffer[NUM_PIXELS * 3 * 3 + 90]; // each byte is expanded to 3 bytes + 90 bytes (zero) for latching
static const uint32_t bit_expand[256]; // lookup table for bit expansion
static Animation current_animation;
static int frame;
void NeoPixel_init(void)
{
/* initialize pixel buffer */
NeoPixel_clear_pixels();
/* initialize DMA buffer */
for (int i = 0 ; i < sizeof dma_buffer ; i++)
dma_buffer[i] = 0x00;
/* configure and enable DMA controller */
/* set up transfer descriptor */
DmacDescriptor descriptor;
descriptor.DSTADDR.reg = (uint32_t)&SERCOM0->SPI.DATA; // destination address is SPI DATA register
descriptor.SRCADDR.reg = (uint32_t)(dma_buffer + sizeof dma_buffer); // source address is the DMA buffer
descriptor.DESCADDR.reg = 0; // only one transfer descriptor
descriptor.BTCTRL.bit.BEATSIZE = DMAC_BTCTRL_BEATSIZE_BYTE_Val; // beat size is one byte
descriptor.BTCTRL.bit.DSTINC = 0; // destination address increment disabled
descriptor.BTCTRL.bit.SRCINC = 1; // source address increment enabled
descriptor.BTCTRL.bit.STEPSEL = DMAC_BTCTRL_STEPSEL_SRC_Val; // flexible source address increment size
descriptor.BTCTRL.bit.STEPSIZE = DMAC_BTCTRL_STEPSIZE_X1_Val; // source address increment is one byte
descriptor.BTCTRL.bit.BLOCKACT = DMAC_BTCTRL_BLOCKACT_NOACT_Val; // request interrupt at end of block transfer
descriptor.BTCNT.reg = sizeof dma_buffer; // beat count
descriptor.BTCTRL.bit.VALID = 1; // descriptor is valid
/* initialize DMA controller */
DMA_init();
/* add and enable SERCOM0 (SPI) channel */
DMA_add_channel(DMA_SOURCE_SERCOM0, &descriptor);
/* enable DMA */
DMA_enable();
/* initialize timer */
Timer_init();
/* initialize SPI */
SPI_init();
}
/* set pixel color (pixel are numbered from 0 to NUM_PIXELS - 1) */
void NeoPixel_set_pixel(int pixel, uint8_t red, uint8_t green, uint8_t blue)
{
if (pixel < 0 || pixel >= NUM_PIXELS)
return;
int n = pixel * 3;
pixel_buffer[n] = green;
pixel_buffer[n + 1] = red;
pixel_buffer[n + 2] = blue;
}
/* all pixels off */
void NeoPixel_clear_pixels(void)
{
for (int i = 0 ; i < NUM_PIXELS * 3 ; i++)
pixel_buffer[i] = 0;
}
/* update DMA buffer */
void NeoPixel_update(void)
{
for (int i = 0, j = 0 ; i < sizeof pixel_buffer ; i++, j += 3)
{
uint32_t expanded = bit_expand[pixel_buffer[i]];
dma_buffer[j] = expanded >> 16;
dma_buffer[j + 1] = expanded >> 8;
dma_buffer[j + 2] = expanded;
}
}
void NeoPixel_update_animation(void)
{
static int v = 1;
static int on = 0;
int sound_value = 0;
if (frame_time) // if all DMA transfers for a frame has occurred
{
frame_time = 0; // acknowledge/clear flag from timer
/* update pixel buffer */
switch (current_animation)
{
case KITT:
NeoPixel_clear_pixels();
NeoPixel_set_pixel(frame, 255, 0, 0);
NeoPixel_set_pixel(frame - v, 255, 0, 0);
NeoPixel_set_pixel(frame - 2*v, 200, 0, 0);
NeoPixel_set_pixel(frame - 3*v, 100, 0, 0);
NeoPixel_set_pixel(frame - 4*v, 50, 0, 0);
if (frame == NUM_PIXELS - 1 || frame == 0)
v = -v;
frame += v;
break;
case BREATHING:
for (int i = 0 ; i < NUM_PIXELS ; i++)
NeoPixel_set_pixel(i, 0 , 0, frame*4);
if (frame == 63 || frame == 0)
v = -v;
frame += v;
break;
case BLINK:
if (!(frame++ % 20))
if (!on)
{
on = 1;
for (int i = 0 ; i < NUM_PIXELS ; i++)
NeoPixel_set_pixel(i, 0, 255, 0);
}
else
{
on = 0;
NeoPixel_clear_pixels();
}
break;
case SOUND:
#define THRESHOLD 200
if (adc_value < THRESHOLD) // threshold
sound_value = 0;
else
sound_value = (adc_value - THRESHOLD) * ((255.0 - 0.0)/(400.0 - THRESHOLD)); // linear map: y = (x - x1) * (y2 - y1)/(x2 - x1)
if (sound_value >= 255)
sound_value = 255;
for (int i = 0 ; i < NUM_PIXELS ; i++)
NeoPixel_set_pixel(i, sound_value, sound_value, 0);
break;
default:
break;
}
/* send frame to DMA buffer */
NeoPixel_update();
}
}
void NeoPixel_set_animation(Animation animation)
{
current_animation = animation;
if (animation == SOUND)
ADC_init();
else
ADC_deinit();
frame = 1;
NeoPixel_clear_pixels();
}
/* bit expansion lookup table */
static const uint32_t bit_expand[256] = {
0b100100100100100100100100,
0b100100100100100100100110,
0b100100100100100100110100,
0b100100100100100100110110,
0b100100100100100110100100,
0b100100100100100110100110,
0b100100100100100110110100,
0b100100100100100110110110,
0b100100100100110100100100,
0b100100100100110100100110,
0b100100100100110100110100,
0b100100100100110100110110,
0b100100100100110110100100,
0b100100100100110110100110,
0b100100100100110110110100,
0b100100100100110110110110,
0b100100100110100100100100,
0b100100100110100100100110,
0b100100100110100100110100,
0b100100100110100100110110,
0b100100100110100110100100,
0b100100100110100110100110,
0b100100100110100110110100,
0b100100100110100110110110,
0b100100100110110100100100,
0b100100100110110100100110,
0b100100100110110100110100,
0b100100100110110100110110,
0b100100100110110110100100,
0b100100100110110110100110,
0b100100100110110110110100,
0b100100100110110110110110,
0b100100110100100100100100,
0b100100110100100100100110,
0b100100110100100100110100,
0b100100110100100100110110,
0b100100110100100110100100,
0b100100110100100110100110,
0b100100110100100110110100,
0b100100110100100110110110,
0b100100110100110100100100,
0b100100110100110100100110,
0b100100110100110100110100,
0b100100110100110100110110,
0b100100110100110110100100,
0b100100110100110110100110,
0b100100110100110110110100,
0b100100110100110110110110,
0b100100110110100100100100,
0b100100110110100100100110,
0b100100110110100100110100,
0b100100110110100100110110,
0b100100110110100110100100,
0b100100110110100110100110,
0b100100110110100110110100,
0b100100110110100110110110,
0b100100110110110100100100,
0b100100110110110100100110,
0b100100110110110100110100,
0b100100110110110100110110,
0b100100110110110110100100,
0b100100110110110110100110,
0b100100110110110110110100,
0b100100110110110110110110,
0b100110100100100100100100,
0b100110100100100100100110,
0b100110100100100100110100,
0b100110100100100100110110,
0b100110100100100110100100,
0b100110100100100110100110,
0b100110100100100110110100,
0b100110100100100110110110,
0b100110100100110100100100,
0b100110100100110100100110,
0b100110100100110100110100,
0b100110100100110100110110,
0b100110100100110110100100,
0b100110100100110110100110,
0b100110100100110110110100,
0b100110100100110110110110,
0b100110100110100100100100,
0b100110100110100100100110,
0b100110100110100100110100,
0b100110100110100100110110,
0b100110100110100110100100,
0b100110100110100110100110,
0b100110100110100110110100,
0b100110100110100110110110,
0b100110100110110100100100,
0b100110100110110100100110,
0b100110100110110100110100,
0b100110100110110100110110,
0b100110100110110110100100,
0b100110100110110110100110,
0b100110100110110110110100,
0b100110100110110110110110,
0b100110110100100100100100,
0b100110110100100100100110,
0b100110110100100100110100,
0b100110110100100100110110,
0b100110110100100110100100,
0b100110110100100110100110,
0b100110110100100110110100,
0b100110110100100110110110,
0b100110110100110100100100,
0b100110110100110100100110,
0b100110110100110100110100,
0b100110110100110100110110,
0b100110110100110110100100,
0b100110110100110110100110,
0b100110110100110110110100,
0b100110110100110110110110,
0b100110110110100100100100,
0b100110110110100100100110,
0b100110110110100100110100,
0b100110110110100100110110,
0b100110110110100110100100,
0b100110110110100110100110,
0b100110110110100110110100,
0b100110110110100110110110,
0b100110110110110100100100,
0b100110110110110100100110,
0b100110110110110100110100,
0b100110110110110100110110,
0b100110110110110110100100,
0b100110110110110110100110,
0b100110110110110110110100,
0b100110110110110110110110,
0b110100100100100100100100,
0b110100100100100100100110,
0b110100100100100100110100,
0b110100100100100100110110,
0b110100100100100110100100,
0b110100100100100110100110,
0b110100100100100110110100,
0b110100100100100110110110,
0b110100100100110100100100,
0b110100100100110100100110,
0b110100100100110100110100,
0b110100100100110100110110,
0b110100100100110110100100,
0b110100100100110110100110,
0b110100100100110110110100,
0b110100100100110110110110,
0b110100100110100100100100,
0b110100100110100100100110,
0b110100100110100100110100,
0b110100100110100100110110,
0b110100100110100110100100,
0b110100100110100110100110,
0b110100100110100110110100,
0b110100100110100110110110,
0b110100100110110100100100,
0b110100100110110100100110,
0b110100100110110100110100,
0b110100100110110100110110,
0b110100100110110110100100,
0b110100100110110110100110,
0b110100100110110110110100,
0b110100100110110110110110,
0b110100110100100100100100,
0b110100110100100100100110,
0b110100110100100100110100,
0b110100110100100100110110,
0b110100110100100110100100,
0b110100110100100110100110,
0b110100110100100110110100,
0b110100110100100110110110,
0b110100110100110100100100,
0b110100110100110100100110,
0b110100110100110100110100,
0b110100110100110100110110,
0b110100110100110110100100,
0b110100110100110110100110,
0b110100110100110110110100,
0b110100110100110110110110,
0b110100110110100100100100,
0b110100110110100100100110,
0b110100110110100100110100,
0b110100110110100100110110,
0b110100110110100110100100,
0b110100110110100110100110,
0b110100110110100110110100,
0b110100110110100110110110,
0b110100110110110100100100,
0b110100110110110100100110,
0b110100110110110100110100,
0b110100110110110100110110,
0b110100110110110110100100,
0b110100110110110110100110,
0b110100110110110110110100,
0b110100110110110110110110,
0b110110100100100100100100,
0b110110100100100100100110,
0b110110100100100100110100,
0b110110100100100100110110,
0b110110100100100110100100,
0b110110100100100110100110,
0b110110100100100110110100,
0b110110100100100110110110,
0b110110100100110100100100,
0b110110100100110100100110,
0b110110100100110100110100,
0b110110100100110100110110,
0b110110100100110110100100,
0b110110100100110110100110,
0b110110100100110110110100,
0b110110100100110110110110,
0b110110100110100100100100,
0b110110100110100100100110,
0b110110100110100100110100,
0b110110100110100100110110,
0b110110100110100110100100,
0b110110100110100110100110,
0b110110100110100110110100,
0b110110100110100110110110,
0b110110100110110100100100,
0b110110100110110100100110,
0b110110100110110100110100,
0b110110100110110100110110,
0b110110100110110110100100,
0b110110100110110110100110,
0b110110100110110110110100,
0b110110100110110110110110,
0b110110110100100100100100,
0b110110110100100100100110,
0b110110110100100100110100,
0b110110110100100100110110,
0b110110110100100110100100,
0b110110110100100110100110,
0b110110110100100110110100,
0b110110110100100110110110,
0b110110110100110100100100,
0b110110110100110100100110,
0b110110110100110100110100,
0b110110110100110100110110,
0b110110110100110110100100,
0b110110110100110110100110,
0b110110110100110110110100,
0b110110110100110110110110,
0b110110110110100100100100,
0b110110110110100100100110,
0b110110110110100100110100,
0b110110110110100100110110,
0b110110110110100110100100,
0b110110110110100110100110,
0b110110110110100110110100,
0b110110110110100110110110,
0b110110110110110100100100,
0b110110110110110100100110,
0b110110110110110100110100,
0b110110110110110100110110,
0b110110110110110110100100,
0b110110110110110110100110,
0b110110110110110110110100,
0b110110110110110110110110
};

View File

@@ -0,0 +1,18 @@
#ifndef NEOPIXEL_H_
#define NEOPIXEL_H_
#define NUM_PIXELS 24
typedef enum
{
KITT, BREATHING, BLINK, SOUND,
} Animation;
void NeoPixel_init(void);
void NeoPixel_set_pixel(int pixel, uint8_t red, uint8_t green, uint8_t blue);
void NeoPixel_clear_pixels(void);
void NeoPixel_update(void);
void NeoPixel_set_animation(Animation animation);
void NeoPixel_update_animation(void);
#endif /* NEOPIXEL_H_ */

View File

@@ -0,0 +1,31 @@
#include <samd21g18a.h>
#include "SPI.h"
/* initialize SPI on SERCOM0 with MOSI on pad 0 (pin PA08) */
void SPI_init(void)
{
/* enable peripheral clock */
PM->APBCMASK.bit.SERCOM0_ = 1;
/* enable generic clock */
GCLK->CLKCTRL.bit.ID = GCLK_CLKCTRL_ID_SERCOM0_CORE_Val; // configure generic clock for SERCOM0
GCLK->CLKCTRL.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val; // source is generic clock generator 0
GCLK->CLKCTRL.bit.CLKEN = 1; // enable generic clock
/* select GPIO pins alternative function */
PORT->Group[0].PINCFG[8].bit.PMUXEN = 1; // enable alternative function for pin PA08
PORT->Group[0].PMUX[4].bit.PMUXE = MUX_PA08C_SERCOM0_PAD0; // PA08 alternative function C (SERCOM0 pad 0)
/* configure peripheral */
SERCOM0->SPI.CTRLA.bit.DOPO = 0x00; // MOSI on pad 0 (pin PA08)
SERCOM0->SPI.CTRLA.bit.CPHA = 0x00;
SERCOM0->SPI.CTRLA.bit.CPOL = 0x00; // transfer mode 0
SERCOM0->SPI.CTRLA.bit.DORD = 0x00; // MSB first
SERCOM0->SPI.CTRLA.bit.MODE = 0x03; // SPI master operation
SERCOM0->SPI.CTRLB.bit.CHSIZE = 0x00; // 8 bit character size
SERCOM0->SPI.BAUD.reg = 9; // SPI frequency 2.4 MHz (BAUD = gclk/(2*f_baud) - 1)
/* enable peripheral */
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
}

View File

@@ -0,0 +1,6 @@
#ifndef SPI_H_
#define SPI_H_
void SPI_init(void);
#endif /* SPI_H_ */

View File

@@ -0,0 +1,200 @@
#include <asf.h>
#include "Serial.h"
#include "FIFO.h"
/* initialize USART on SERCOM2 with TX on pad 2 (pin PA10) and RX on pad 3 (pin PA11) */
void Serial_init(void)
{
/* initialize FIFO buffers */
FIFO_init();
/* enable peripheral clock */
PM->APBCMASK.bit.SERCOM2_ = 1;
/* enable generic clock */
GCLK->CLKCTRL.bit.ID = GCLK_CLKCTRL_ID_SERCOM2_CORE_Val; // configure generic clock for SERCOM2
GCLK->CLKCTRL.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val; // source is generic clock generator 0
GCLK->CLKCTRL.bit.CLKEN = 1; // enable generic clock
/* enable GPIO pins alternative function */
PORT->Group[0].PINCFG[10].bit.PMUXEN = 1; // enable alternative function for pins PA10 and PA11
PORT->Group[0].PINCFG[11].bit.PMUXEN = 1;
PORT->Group[0].DIRCLR.reg = PORT_PA11;
PORT->Group[0].PINCFG[11].bit.INEN = 1;
PORT->Group[0].PMUX[5].bit.PMUXE = MUX_PA10D_SERCOM2_PAD2; // PA10 alternative function D (SERCOM2 pad 2)
PORT->Group[0].PMUX[5].bit.PMUXO = MUX_PA11D_SERCOM2_PAD3; // PA11 alternative function D (SERCOM2 pad 3)
/* configure peripheral */
SERCOM2->USART.CTRLA.bit.MODE = SERCOM_USART_CTRLA_MODE_USART_INT_CLK_Val; // USART internal clock operation
SERCOM2->USART.CTRLA.bit.RXPO = 0x03; // RX on pad 3 (pin PA11)
SERCOM2->USART.CTRLA.bit.TXPO = 0x01; // TX on pad 2 (pin PA10)
SERCOM2->USART.CTRLA.bit.DORD = 1; // LSB first
SERCOM2->USART.CTRLA.bit.CMODE = 0x00; // asynchronous communication (UART)
SERCOM2->USART.CTRLA.bit.FORM = 0x00; // no parity
SERCOM2->USART.CTRLA.bit.SAMPR = 0x00; // 16 bit oversampling with arithmetic baud rate generation
SERCOM2->USART.CTRLB.bit.CHSIZE = 0x00; // 8 bit data
SERCOM2->USART.CTRLB.bit.SBMODE = 0x00; // one stop bit
SERCOM2->USART.BAUD.reg = 63018; // BAUD = 65535 * (1 - num_samples * f_baud/f_clck)
SERCOM2->USART.CTRLB.bit.RXEN = 1; // enable receiver
SERCOM2->USART.CTRLB.bit.TXEN = 1; // enable transmitter
/* enable interrupt */
SERCOM2->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC; // enable Reception Complete interrupt
NVIC_EnableIRQ(SERCOM2_IRQn); // enable interrupts in NVIC
/* enable peripheral */
SERCOM2->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
/* avoid corrupted bytes at start */
delay_ms(100);
}
/* blocking implementation */
void Serial_transmit(uint8_t data)
{
while (!TX_FIFO_put(data))
;
/* TX buffer has new data: re enable DRE interrupt */
if (!(SERCOM2->USART.INTENSET.reg & SERCOM_USART_INTENSET_DRE))
SERCOM2->USART.INTENSET.reg = SERCOM_USART_INTENSET_DRE;
SERCOM2->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC;
}
/* blocking implementation */
uint8_t Serial_receive(void)
{
uint8_t data;
while (!RX_FIFO_get(&data))
;
/* RX buffer has space: re enable RXC interrupt */
if (!(SERCOM2->USART.INTENSET.reg & SERCOM_USART_INTENSET_RXC))
SERCOM2->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC;
return data;
}
int Serial_receive_timeout(uint8_t *data, int timeout)
{
int count = 0;
while (!RX_FIFO_get(data))
{
count++;
if (count == timeout)
return 0;
}
return 1;
}
void Serial_write(const char *string)
{
while (*string)
Serial_transmit(*string++);
}
void Serial_writeln(const char *string)
{
Serial_write(string);
Serial_write("\r\n");
}
void Serial_read(char *string, int length)
{
while (length--)
*string++ = Serial_receive();
*string = '\0';
}
void Serial_read_string(char *string)
{
while ((*string++ = Serial_receive()) != '\n')
;
*string = '\0';
}
int Serial_available(void)
{
return RX_FIFO_count();
}
/* find a string in RX buffer (blocking until found) */
void Serial_find(const char *string)
{
const char *p = string;
char c;
while (*p != '\0')
if ((c = Serial_receive()) == *p)
p++;
else if (p != string)
{
const char *q = p;
while (p > string)
{
p--;
if (*p == c)
{
int diff = q - p;
const char *i;
for (i = string ; i < p ; i++)
if (*i != *(i + diff))
break; // for loop
if (i == p)
{
p++;
break; // while loop
}
}
}
}
}
/* find a string in RX buffer (returns 0 if timed out) */
int Serial_find_timeout(const char *string, int timeout)
{
const char *p = string;
char c;
while (*p != '\0')
{
if (!Serial_receive_timeout(&c, timeout))
return 0;
else if (c == *p)
p++;
else if (p != string)
{
const char *q = p;
while (p > string)
{
p--;
if (*p == c)
{
int diff = q - p;
const char *i;
for (i = string ; i < p ; i++)
if (*i != *(i + diff))
break; // for loop
if (i == p)
{
p++;
break; // while loop
}
}
}
}
}
return 1;
}
void SERCOM2_Handler(void)
{
/* handle RX interrupt */
if (SERCOM2->USART.INTFLAG.bit.RXC && SERCOM2->USART.INTENSET.bit.RXC) // if RXC interrupt is triggered and enabled
if (!RX_FIFO_put(SERCOM2->USART.DATA.reg))
SERCOM2->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_RXC; // if RX buffer is full disable RXC interrupt
/* handle TX interrupt */
if (SERCOM2->USART.INTFLAG.bit.DRE && SERCOM2->USART.INTENSET.bit.DRE) // if DRE interrupt is triggered and enabled
{
uint8_t data;
if (!TX_FIFO_get(&data))
SERCOM2->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE; // if TX buffer is empty disable DRE interrupt
else
SERCOM2->USART.DATA.reg = data;
}
}

View File

@@ -0,0 +1,16 @@
#ifndef SERIAL_H_
#define SERIAL_H_
void Serial_init(void);
void Serial_transmit(uint8_t data);
uint8_t Serial_receive(void);
int Serial_receive_timeout(uint8_t *data, int timeout);
void Serial_write(const char *string);
void Serial_writeln(const char *string);
void Serial_read(char *string, int length);
void Serial_read_string(char *string);
int Serial_available(void);
void Serial_find(const char *string);
int Serial_find_timeout(const char *string, int timeout);
#endif /* SERIAL_H_ */

View File

@@ -0,0 +1,45 @@
/*
* Timer.c
*
* Created: 08/03/2018 10.49.38
* Author: Luca
*/
#include <samd21g18a.h>
#include "Timer.h"
volatile int frame_time = 0;
void Timer_init(void)
{
/* enable peripheral clock */
PM->APBCMASK.bit.TC3_ = 1;
/* enable generic clock */
GCLK->CLKCTRL.bit.ID = GCLK_CLKCTRL_ID_TCC2_TC3_Val; // configure generic clock for Timer/Counter 3
GCLK->CLKCTRL.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val; // source is generic clock generator 0 (48 MHz)
GCLK->CLKCTRL.bit.CLKEN = 1; // enable generic clock
/* configure peripheral */
TC3->COUNT16.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT16_Val;
TC3->COUNT16.CTRLA.bit.PRESCSYNC = TC_CTRLA_PRESCSYNC_PRESC_Val;
TC3->COUNT16.CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_MFRQ_Val;
TC3->COUNT16.CTRLA.bit.PRESCALER = TC_CTRLA_PRESCALER_DIV256_Val;
TC3->COUNT16.CC[0].reg = 6250; // with a GCLK @ 48 MHz and a prescaler of 256 the top value yields a frequency of 30 Hz
/* enable timer overflow interrupt */
TC3->COUNT16.INTENSET.bit.OVF = 1;
NVIC_EnableIRQ(TC3_IRQn);
/* enable Timer/Counter 3 */
TC3->COUNT16.CTRLA.bit.ENABLE = 1;
}
void TC3_Handler(void)
{
if (TC3->COUNT16.INTFLAG.bit.OVF && TC3->COUNT16.INTENSET.bit.OVF)
{
TC3->COUNT16.INTFLAG.bit.OVF = 1; // acknowledge interrupt
frame_time = 1; // set frame flag
}
}

View File

@@ -0,0 +1,16 @@
/*
* Timer.h
*
* Created: 08/03/2018 10.50.09
* Author: Luca
*/
#ifndef TIMER_H_
#define TIMER_H_
extern volatile int frame_time;
void Timer_init(void);
#endif /* TIMER_H_ */

View File

@@ -0,0 +1,321 @@
#include <asf.h>
#include <ctype.h>
#include "WiFi.h"
#include "Serial.h"
#include "string_func.h"
#include "utility.h"
//#define SSID // insert your wifi SSID
//#define PASSWORD // insert here your wifi network password
#ifndef SSID
#error network not defined
#endif
#ifndef PASSWORD
#error password not defined
#endif
static int cipmux = 0;
static enum State
{
STATION = 1,AP = 2,AP_STATION = 3,
} wifi_state;
void WiFi_init(void)
{
Serial_init();
WiFi_restart();
/* initialize AP mode and start TCP server */
//WiFi_set_wifi_mode(2);
//WiFi_set_IP_address("192.168.5.1");
//WiFi_set_softAP_options("HI Pedini", "",5, 0);
//WiFi_enable_multiple_connections(1);
//WiFi_create_server(3301);
/* initialize station mode, connect to router and open UDP socket */
WiFi_set_wifi_mode(1);
WiFi_join_access_point(SSID, PASSWORD);
WiFi_enable_multiple_connections(0);
WiFi_register_UDP_port(0,"0",0,1000,2);
}
/***** basic AT commands *****/
void WiFi_restart(void)
{
Serial_write("AT+RST\r\n");
Serial_find("ready\r\n");
}
void WiFi_set_baud_rate(int baud,int data_bits,int stop_bits,int parity,int flow_ctl)
{
char buf[10];
Serial_write("AT+UART_CUR=");
Serial_write(inttoa(baud,buf));
Serial_transmit(',');
Serial_write(inttoa(data_bits,buf));
Serial_transmit(',');
Serial_write(inttoa(stop_bits,buf));
Serial_transmit(',');
Serial_write(inttoa(parity,buf));
Serial_transmit(',');
Serial_write(inttoa(flow_ctl,buf));
Serial_write("\r\n");
Serial_find("OK\r\n");
}
/***** WiFi related commands ******/
/* set WiFi mode:
* 1 -> station mode
* 2 -> softAP mode
* 3 -> softAP + station mode
*/
void WiFi_set_wifi_mode(int mode)
{
switch (mode)
{
case 1: Serial_write("AT+CWMODE_CUR=1\r\n");
wifi_state = STATION;
break;
case 2: Serial_write("AT+CWMODE_CUR=2\r\n");
wifi_state = AP;
break;
case 3: Serial_write("AT+CWMODE_CUR=3\r\n");
wifi_state = AP_STATION;
break;
}
Serial_find("OK\r\n");
}
void WiFi_list_access_points(char *list)
{
//TODO with getline (gets/fgets) like function
}
/* join access point */
void WiFi_join_access_point(const char *ssid,const char *password)
{
if (wifi_state != STATION && wifi_state != AP_STATION)
return;
Serial_write("AT+CWJAP_CUR=\"");
Serial_write(ssid);
Serial_write("\",\"");
Serial_write(password);
Serial_write("\"\r\n");
Serial_find("OK\r\n");
}
/* quit access point */
void WiFi_quit_access_point(void)
{
Serial_write("AT+CWQAP\r\n");
Serial_find("OK\r\n");
}
/* set options as soft access point */
void WiFi_set_softAP_options(const char *ssid,const char *password,int channel_id,int encription)
{
if (wifi_state != AP && wifi_state != AP_STATION)
return;
char buf[10];
Serial_write("AT+CWSAP_CUR=\"");
Serial_write(ssid);
Serial_write("\",\"");
Serial_write(password);
Serial_write("\",");
Serial_write(inttoa(channel_id,buf));
Serial_transmit(',');
Serial_write(inttoa(encription,buf));
Serial_write("\r\n");
Serial_find("OK\r\n");
}
void WiFi_list_stations(char *list)
{
//TODO
}
/***** TCP/IP related commands *****/
/* set transfer mode
* 0 : normal mode
* 1 : transparent mode
*/
void WiFi_set_IP_mode(int mode)
{
switch (mode)
{
case 0: Serial_write("AT+CIPMODE=0\r\n");
break;
case 1: Serial_write("AT+CIPMODE=1\r\n");
break;
}
Serial_find("OK\r\n");
}
void WiFi_set_IP_address(const char *ip)
{
Serial_write("AT+CIPAP_CUR=\"");
Serial_write(ip);
Serial_write("\"");
Serial_write("\r\n");
Serial_find("OK\r\n");
}
/* enable multiple connections (must be 1 before starting TCP server) */
void WiFi_enable_multiple_connections(int enable)
{
if (enable)
{
Serial_write("AT+CIPMUX=1\r\n");
cipmux = 1;
}
else
{
Serial_write("AT+CIPMUX=0\r\n");
cipmux = 0;
}
Serial_find("OK\r\n");
}
void WiFi_establish_TCP_connection(int connection_id,const char *ip,int port)
{
if (cipmux == 0)
{
Serial_write("AT+CIPSTART=\"");
Serial_write("TCP");
Serial_write("\",\"");
Serial_write(ip);
Serial_write("\",");
char buf[10];
Serial_write(inttoa(port,buf));
}
else
{
Serial_write("AT+CIPSTART=");
Serial_transmit(connection_id + '0');
Serial_write(",\"");
Serial_write("TCP");
Serial_write("\",\"");
Serial_write(ip);
Serial_write("\",");
char buf[10];
Serial_write(inttoa(port,buf));
}
Serial_write("\r\n");
Serial_find("OK\r\n");
}
void WiFi_register_UDP_port(int connection_id,const char *remote_ip,int remote_port,int local_port,int mode)
{
if (cipmux == 0)
{
Serial_write("AT+CIPSTART=\"");
Serial_write("UDP");
Serial_write("\",\"");
Serial_write(remote_ip);
Serial_write("\",");
char buf[10];
Serial_write(inttoa(remote_port,buf));
Serial_write(",");
Serial_write(inttoa(local_port,buf));
Serial_write(",");
Serial_write(inttoa(mode,buf));
}
else
{
Serial_write("AT+CIPSTART=");
Serial_transmit(connection_id + '0');
Serial_write(",\"UDP\",\"");
Serial_write(remote_ip);
Serial_write("\",");
char buf[10];
Serial_write(inttoa(remote_port,buf));
Serial_write(",");
Serial_write(inttoa(local_port,buf));
Serial_write(",");
Serial_write(inttoa(mode,buf));
}
Serial_write("\r\n");
Serial_find("OK\r\n");
}
void WiFi_close_connection(int connection_id)
{
Serial_write("AT+CIPCLOSE=");
Serial_transmit(connection_id + '0');
Serial_write("\r\n");
Serial_find("OK\r\n");
}
/* start TCP server on port "port" (CIPMUX must be 1) */
int WiFi_create_TCP_server(int port)
{
if (cipmux == 0)
return WIFI_FAIL;
Serial_write("AT+CIPSERVER=1,");
char port_string[10];
Serial_write(inttoa(port,port_string));
Serial_write("\r\n");
Serial_find("OK\r\n");
return WIFI_SUCCESS;
}
/* stop TCP server */
void WiFi_delete_server(void)
{
Serial_write("AT+CIPSERVER=0\r\n");
Serial_find("OK\r\n");
}
void WiFi_send_data(int connection_id,const char data[])
{
Serial_write("AT+CIPSEND=");
Serial_transmit(connection_id + '0');
Serial_transmit(',');
int length = strlength(data);
char buf[10];
Serial_write(inttoa(length,buf));
Serial_write("\r\n");
Serial_find(">");
Serial_write(data);
Serial_find("SEND OK\r\n");
}
int WiFi_receive_data(char data[],int limit)
{
if (cipmux == 0)
{
if (!Serial_find_timeout("+IPD,", 100))
return 0;
int bytes_received = 0;
char c;
while (isdigit(c = Serial_receive()))
bytes_received = c - '0' + bytes_received * 10;
int i = 0;
while (--limit > 0 && i < bytes_received)
data[i++] = Serial_receive();
data[i] = '\0';
}
else
{
if (!Serial_find_timeout("+IPD,", 100))
return 0;
int connection_id = Serial_receive() - '0';
(void)Serial_receive();
int bytes_received = 0;
char c;
while (isdigit(c = Serial_receive()))
bytes_received = c - '0' + bytes_received * 10;
int i = 0;
while (--limit > 0 && i < bytes_received)
data[i++] = Serial_receive();
data[i] = '\0';
}
return 1; // return if received AND connection?
}

View File

@@ -0,0 +1,25 @@
#ifndef WIFI_H_
#define WIFI_H_
#define WIFI_SUCCESS 1
#define WIFI_FAIL 0
void WiFi_init(void);
void WiFi_restart(void);
void WiFi_set_baud_rate(int baud,int data_bits,int stop_bits,int parity,int flow_ctl);
void WiFi_set_wifi_mode(int mode);
void WiFi_join_access_point(const char ssid[],const char password[]);
void WiFi_quit_access_point(void);
void WiFi_set_IP_mode(int mode);
void WiFi_set_IP_address(const char *ip);
void WiFi_set_softAP_options(const char *ssid,const char *password,int channel_id,int encription);
void WiFi_enable_multiple_connections(int enable);
void WiFi_establish_TCP_connection(int connection_id, const char *ip,int port);
void WiFi_register_UDP_port(int connection_id,const char *remote_ip, int remote_port, int local_port, int mode);
void WiFi_close_connection(int connection_id);
int WiFi_create_TCP_server(int port);
void WiFi_delete_server(void);
void WiFi_send_data(int connection_id,const char data[]);
int WiFi_receive_data(char data[],int limit);
#endif /* WIFI_H_ */

View File

@@ -0,0 +1,93 @@
/**
* \file
*
* \brief Autogenerated API include file for the Atmel Software Framework (ASF)
*
* Copyright (c) 2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
#ifndef ASF_H
#define ASF_H
/*
* This file includes all API header files for the selected drivers from ASF.
* Note: There might be duplicate includes required by more than one driver.
*
* The file is automatically generated and will be re-written when
* running the ASF driver selector tool. Any changes will be discarded.
*/
// From module: Common SAM0 compiler driver
#include <compiler.h>
#include <status_codes.h>
// From module: Common build items for user board support templates
#include <user_board.h>
// From module: Delay routines
#include <delay.h>
// From module: Generic board support
#include <board.h>
// From module: Interrupt management - SAM implementation
#include <interrupt.h>
// From module: Part identification macros
#include <parts.h>
// From module: SYSTEM - Clock Management for SAMD21/R21/DA/HA
#include <clock.h>
#include <gclk.h>
// From module: SYSTEM - Core System Driver
#include <system.h>
// From module: SYSTEM - I/O Pin Multiplexer
#include <pinmux.h>
// From module: SYSTEM - Interrupt Driver
#include <system_interrupt.h>
// From module: SYSTEM - Power Management for SAM D20/D21/R21/D09/D10/D11/DA/HA
#include <power.h>
// From module: SYSTEM - Reset Management for SAM D20/D21/R21/D09/D10/D11/DA/HA
#include <reset.h>
#endif // ASF_H

View File

@@ -0,0 +1,50 @@
/**
* \file
*
* \brief User board configuration template
*
* Copyright (C) 2013-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef CONF_BOARD_H
#define CONF_BOARD_H
#endif // CONF_BOARD_H

View File

@@ -0,0 +1,200 @@
/**
* \file
*
* \brief SAM D21 Clock configuration
*
* Copyright (C) 2013-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#include <clock.h>
/****************** GCLK_GEN0 @ 48 MHz configuration *************************/
#ifndef CONF_CLOCKS_H_INCLUDED
# define CONF_CLOCKS_H_INCLUDED
/* System clock bus configuration */
# define CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT false
# define CONF_CLOCK_FLASH_WAIT_STATES 1
# define CONF_CLOCK_CPU_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
# define CONF_CLOCK_APBA_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
# define CONF_CLOCK_APBB_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
# define CONF_CLOCK_APBC_DIVIDER SYSTEM_MAIN_CLOCK_DIV_1
/* SYSTEM_CLOCK_SOURCE_OSC8M configuration - Internal 8MHz oscillator */
# define CONF_CLOCK_OSC8M_PRESCALER SYSTEM_OSC8M_DIV_1
# define CONF_CLOCK_OSC8M_ON_DEMAND true
# define CONF_CLOCK_OSC8M_RUN_IN_STANDBY false
/* SYSTEM_CLOCK_SOURCE_XOSC configuration - External clock/oscillator */
# define CONF_CLOCK_XOSC_ENABLE false
# define CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL
# define CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY 12000000UL
# define CONF_CLOCK_XOSC_STARTUP_TIME SYSTEM_XOSC_STARTUP_32768
# define CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL true
# define CONF_CLOCK_XOSC_ON_DEMAND true
# define CONF_CLOCK_XOSC_RUN_IN_STANDBY false
/* SYSTEM_CLOCK_SOURCE_XOSC32K configuration - External 32KHz crystal/clock oscillator */
# define CONF_CLOCK_XOSC32K_ENABLE false
# define CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL SYSTEM_CLOCK_EXTERNAL_CRYSTAL
# define CONF_CLOCK_XOSC32K_STARTUP_TIME SYSTEM_XOSC32K_STARTUP_65536
# define CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL false
# define CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT false
# define CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT true
# define CONF_CLOCK_XOSC32K_ON_DEMAND true
# define CONF_CLOCK_XOSC32K_RUN_IN_STANDBY false
/* SYSTEM_CLOCK_SOURCE_OSC32K configuration - Internal 32KHz oscillator */
# define CONF_CLOCK_OSC32K_ENABLE true
# define CONF_CLOCK_OSC32K_STARTUP_TIME SYSTEM_OSC32K_STARTUP_130
# define CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT true
# define CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT true
# define CONF_CLOCK_OSC32K_ON_DEMAND true
# define CONF_CLOCK_OSC32K_RUN_IN_STANDBY false
/* SYSTEM_CLOCK_SOURCE_DFLL configuration - Digital Frequency Locked Loop */
# define CONF_CLOCK_DFLL_ENABLE false
# define CONF_CLOCK_DFLL_LOOP_MODE SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED
# define CONF_CLOCK_DFLL_ON_DEMAND false
/* DFLL open loop mode configuration */
# define CONF_CLOCK_DFLL_FINE_VALUE (512)
/* DFLL closed loop mode configuration */
# define CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR GCLK_GENERATOR_1
# define CONF_CLOCK_DFLL_MULTIPLY_FACTOR (48000000 / 32768)
# define CONF_CLOCK_DFLL_QUICK_LOCK true
# define CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK true
# define CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP true
# define CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE true
# define CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE (0x1f / 4)
# define CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE (0xff / 4)
/* SYSTEM_CLOCK_SOURCE_DPLL configuration - Digital Phase-Locked Loop */
# define CONF_CLOCK_DPLL_ENABLE true
# define CONF_CLOCK_DPLL_ON_DEMAND true
# define CONF_CLOCK_DPLL_RUN_IN_STANDBY false
# define CONF_CLOCK_DPLL_LOCK_BYPASS false
# define CONF_CLOCK_DPLL_WAKE_UP_FAST false
# define CONF_CLOCK_DPLL_LOW_POWER_ENABLE false
# define CONF_CLOCK_DPLL_LOCK_TIME SYSTEM_CLOCK_SOURCE_DPLL_LOCK_TIME_DEFAULT
# define CONF_CLOCK_DPLL_REFERENCE_CLOCK SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_GCLK
# define CONF_CLOCK_DPLL_FILTER SYSTEM_CLOCK_SOURCE_DPLL_FILTER_DEFAULT
# define CONF_CLOCK_DPLL_REFERENCE_FREQUENCY 32768
# define CONF_CLOCK_DPLL_REFERENCE_DIVIDER 1
# define CONF_CLOCK_DPLL_OUTPUT_FREQUENCY 48000000
/* DPLL GCLK reference configuration */
# define CONF_CLOCK_DPLL_REFERENCE_GCLK_GENERATOR GCLK_GENERATOR_1
/* DPLL GCLK lock timer configuration */
# define CONF_CLOCK_DPLL_LOCK_GCLK_GENERATOR GCLK_GENERATOR_1
/* Set this to true to configure the GCLK when running clocks_init. If set to
* false, none of the GCLK generators will be configured in clocks_init(). */
# define CONF_CLOCK_CONFIGURE_GCLK true
/* Configure GCLK generator 0 (Main Clock) */
# define CONF_CLOCK_GCLK_0_ENABLE true
# define CONF_CLOCK_GCLK_0_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_0_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_DPLL
# define CONF_CLOCK_GCLK_0_PRESCALER 1
# define CONF_CLOCK_GCLK_0_OUTPUT_ENABLE false
/* Configure GCLK generator 1 */
# define CONF_CLOCK_GCLK_1_ENABLE true
# define CONF_CLOCK_GCLK_1_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_1_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC32K
# define CONF_CLOCK_GCLK_1_PRESCALER 1
# define CONF_CLOCK_GCLK_1_OUTPUT_ENABLE false
/* Configure GCLK generator 2 (RTC) */
# define CONF_CLOCK_GCLK_2_ENABLE false
# define CONF_CLOCK_GCLK_2_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_2_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_2_PRESCALER 32
# define CONF_CLOCK_GCLK_2_OUTPUT_ENABLE false
/* Configure GCLK generator 3 */
# define CONF_CLOCK_GCLK_3_ENABLE false
# define CONF_CLOCK_GCLK_3_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_3_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_3_PRESCALER 1
# define CONF_CLOCK_GCLK_3_OUTPUT_ENABLE false
/* Configure GCLK generator 4 */
# define CONF_CLOCK_GCLK_4_ENABLE false
# define CONF_CLOCK_GCLK_4_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_4_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_4_PRESCALER 1
# define CONF_CLOCK_GCLK_4_OUTPUT_ENABLE false
/* Configure GCLK generator 5 */
# define CONF_CLOCK_GCLK_5_ENABLE false
# define CONF_CLOCK_GCLK_5_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_5_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_5_PRESCALER 1
# define CONF_CLOCK_GCLK_5_OUTPUT_ENABLE false
/* Configure GCLK generator 6 */
# define CONF_CLOCK_GCLK_6_ENABLE false
# define CONF_CLOCK_GCLK_6_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_6_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_6_PRESCALER 1
# define CONF_CLOCK_GCLK_6_OUTPUT_ENABLE false
/* Configure GCLK generator 7 */
# define CONF_CLOCK_GCLK_7_ENABLE false
# define CONF_CLOCK_GCLK_7_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_7_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_7_PRESCALER 1
# define CONF_CLOCK_GCLK_7_OUTPUT_ENABLE false
/* Configure GCLK generator 8 */
# define CONF_CLOCK_GCLK_8_ENABLE false
# define CONF_CLOCK_GCLK_8_RUN_IN_STANDBY false
# define CONF_CLOCK_GCLK_8_CLOCK_SOURCE SYSTEM_CLOCK_SOURCE_OSC8M
# define CONF_CLOCK_GCLK_8_PRESCALER 1
# define CONF_CLOCK_GCLK_8_OUTPUT_ENABLE false
#endif /* CONF_CLOCKS_H_INCLUDED */

View File

@@ -0,0 +1,45 @@
#include <asf.h>
#include "NeoPixel.h"
#include "WiFi.h"
#include "string_func.h"
uint8_t buffer[24 * 3 * 3 + 90];
int main (void)
{
/* initialize clock system (conf_clocks.h) */
system_init();
delay_init();
/* initialize NeoPixel strip */
NeoPixel_init();
/* initialize WiFi */
WiFi_init();
/* set default animation */
NeoPixel_set_animation(KITT);
char data[100];
while(1)
{
/* update animation */
NeoPixel_update_animation();
/* do other things */
if (WiFi_receive_data(data, sizeof data))
{
if (strcomp(data, "BREATHING") == 0)
NeoPixel_set_animation(BREATHING);
else if (strcomp(data, "KITT") == 0)
NeoPixel_set_animation(KITT);
else if (strcomp(data, "BLINK") == 0)
NeoPixel_set_animation(BLINK);
else if (strcomp(data, "SOUND") == 0)
NeoPixel_set_animation(SOUND);
}
}
}

View File

@@ -0,0 +1,76 @@
#include "string_func.h"
#define NULL (void*)0
int strlength(const char *string)
{
const char *p = string;
while (*p != '\0')
p++;
return p - string;
}
int strcomp(const char *s1,const char *s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return *s1 - *s2;
}
char *strstring(const char *haystack,const char *needle)
{
const char *p;
const char *q;
while (*haystack != '\0')
{
p = haystack;
q = needle;
while (*q == *p)
{
if (*q == '\0')
return (char*)haystack;
q++;
p++;
}
if (*q == '\0')
return (char*)haystack;
haystack++;
}
return NULL;
}
char *strcharacter(const char *string,char c)
{
while (*string != c)
string++;
return (char*)string;
}
char *parse_until(const char *src,char *dest,char until)
{
char *p = dest;
while ((*dest = *src) != until)
{
src++;
dest++;
}
*dest = '\0';
return p;
}
char *reverse(char string[])
{
for (int i = 0 , j = strlength(string) - 1 ; i < j ; i++ , j--)
{
char temp = string[i];
string[i] = string[j];
string[j] = temp;
}
return &string[0];
}

View File

@@ -0,0 +1,11 @@
int strlength(const char *string);
int strcomp(const char *s1,const char *s2);
char *strstring(const char *haystack,const char *needle);
char *strcharacter(const char *string,char c);
char *parse_until(const char *src,char *dest,char until);
char *reverse(char string[]);

View File

@@ -0,0 +1,68 @@
#include <ctype.h>
#include "string_func.h"
#include "utility.h"
int atoint(const char *a)
{
while (isspace(*a))
a++;
int sign = 1;
if (*a == '-')
sign = -1;
if (*a == '+' || *a == '-')
a++;
int i = 0;
while (isdigit(*a))
i = *a++ - '0' + i*10;
return sign*i;
}
char *inttoa(int i,char *a)
{
char *p = a;
do
{
*a++ = i % 10 + '0';
} while ((i /= 10) > 0);
*a = '\0';
return reverse(p);
}
double atofloat(const char *a)
{
while (isspace(*a))
a++;
int sign = *a == '-' ? -1 : 1;
if (*a == '+' || *a == '-')
a++;
double val = 0.0;
while (isdigit(*a))
val = *a++ - '0' + val * 10.0;
if (*a == '.')
a++;
double power = 1.0;
while (isdigit(*a))
{
val = *a++ - '0' + val * 10.0;
power *= 10.0;
}
val = sign*val/power;
if (*a == 'e' || *a == 'E')
a++;
sign = *a == '-' ? -1 : 1;
if (*a == '+' || *a == '-')
a++;
int n = 0;
while (isdigit(*a))
n = *a++ - '0' + n * 10;
if (sign == 1)
while (n-- > 0)
val *= 10.0;
else
while (n-- > 0)
val /= 10.0;
return val;
}

View File

@@ -0,0 +1,5 @@
int atoint(const char *a);
char *inttoa(int i,char *a);
double atofloat(const char *a);