Commit 1fa3d9fc authored by Sam Calisch's avatar Sam Calisch
Browse files

moved xmega from web to a gitlab project

parents
//
// watt.8e5.c
//
// open and closed loop current measurement with xmega 8e5 and drv5053 hall effect sensor
//
#include <stdio.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include "serial.h"
#include "adc.h"
#define output(directions,pin) (directions |= pin) // set port direction for output
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define serial_port PORTD.OUT
#define serial_direction PORTD.DIR
#define serial_pins PORTD.IN
#define serial_pin_in PIN6_bm
#define serial_pin_out PIN7_bm
#define sec_port PORTD.OUT
#define sec_direction PORTD.DIR
#define sec_pin PIN0_bm
#define lc_port PORTA.OUT
#define lc_direction PORTA.DIR
#define lc_pos_pin PIN5_bm
#define lc_gnd_pin PIN4_bm
volatile int64_t ADC_result, last_ADC_result, d_result;
int16_t offset;
static char buffer[50] = {0};
int main(void) {
// set up clock
//
OSC.CTRL = OSC_RC32MEN_bm; // enable 32MHz clock
while (!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for clock to be ready
CCP = CCP_IOREG_gc; // enable protected register change
CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // switch to 32MHz clock
//set up sleep
set_sleep_mode(SLEEP_MODE_IDLE);
//set up serial
set(serial_port, serial_pin_out);
output(serial_direction, serial_pin_out);
//set up load cell
//output(lc_direction, lc_pos_pin);
//output(lc_direction, lc_gnd_pin);
//set(lc_port,lc_pos_pin);
//clear(lc_port,lc_gnd_pin);
//_delay_ms(100);
//calibrate ADC to reduce nonlinearity
ADCA.CALL = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL0_offset );
ADCA.CALH = SP_ReadCalibrationByte( PROD_SIGNATURES_START + ADCACAL1_offset );
ADC_ConvMode_and_Resolution_Config(&ADCA, 1, ADC_RESOLUTION_12BIT_gc);
//ADC_BandgapReference_Enable(&ADCA);
ADC_Reference_Config(&ADCA, ADC_REFSEL_INTVCC_gc);
//_delay_ms(200);
ADC_Prescaler_Config(&ADCA, ADC_PRESCALER_DIV32_gc);
ADC_Ch_InputMode_and_Gain_Config(&ADCA.CH0,
ADC_CH_INPUTMODE_DIFFWGAINL_gc,
ADC_CH_GAIN_16X_gc);
//ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN6_gc, ADC_CH_MUXNEGL_PIN3_gc);
ADC_Ch_InputMux_Config(&ADCA.CH0, ADC_CH_MUXPOS_PIN1_gc, ADC_CH_MUXNEGL_PIN2_gc);
ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_HI_gc;
ADC_Enable(&ADCA);
ADC_Wait_8MHz(&ADCA);
offset = ADC_Offset_Get_Signed(&ADCA, &(ADCA.CH0), 100);
last_ADC_result = 0;
int n_samples = 100; //oversampling number
int alpha = 1; //low pass filter constant. larger -> slower
sleep_enable();
int sleep=0;
while (1) {
ADC_result = 0;
for(int i=0; i<n_samples; i++){
ADC_Ch_Conversion_Start(&ADCA.CH0);
if (sleep){
PMIC.CTRL = PMIC_HILVLEN_bm;
sei();
sleep_cpu();
} else{
while(!ADC_Ch_Conversion_Complete(&ADCA.CH0)){};
ADC_result += ADC_ResultCh_GetWord_Signed(&ADCA.CH0, offset);
}
}
ADC_result = ADC_result/n_samples;
last_ADC_result += (ADC_result-last_ADC_result)/alpha;
sprintf(buffer,"1234,%ld", last_ADC_result);
put_string(&serial_port, serial_pin_out, buffer);
put_char(&serial_port, serial_pin_out, 10); // new line
_delay_ms(5);
}
return 0;
}
ISR(ADCA_CH0_vect)
{
ADC_result += ADC_ResultCh_GetWord_Signed(&ADCA.CH0, offset);
ADCA.CH0.INTFLAGS = ADC_CH_CHIF_bm;
}
PROJECT=adc.8e5
SOURCES=$(PROJECT).c
MMCU=atxmega8e5
F_CPU = 32000000
TARGET = x8e5
PROGRAMMER= atmelice_pdi
CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)
$(PROJECT).hex: $(PROJECT).out
avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out
$(PROJECT).out: $(SOURCES)
avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program: $(PROJECT).hex
avrdude -p $(TARGET) -c $(PROGRAMMER) -U flash:w:$(PROJECT).c.hex
#define ADCACAL0_offset 0x20
#define ADCACAL1_offset 0x21
#define ADCBCAL0_offset 0x24
#define ADCBCAL1_offset 0x25
#define ADC_CH_CHIF_bm 0x01 /* Channel Interrupt Flag bit mask. */
#define ADC_ConvMode_and_Resolution_Config(_adc, _signedMode, _resolution) \
((_adc)->CTRLB = ((_adc)->CTRLB & (~(ADC_RESOLUTION_gm|ADC_CONMODE_bm)))| \
(_resolution| ( _signedMode? ADC_CONMODE_bm : 0)))
#define ADC_Reference_Config(_adc, _convRef) \
((_adc)->REFCTRL = ((_adc)->REFCTRL & ~(ADC_REFSEL_gm)) | _convRef)
#define ADC_Prescaler_Config(_adc, _div) \
((_adc)->PRESCALER = ((_adc)->PRESCALER & (~ADC_PRESCALER_gm)) | _div)
#define ADC_Ch_InputMode_and_Gain_Config(_adc_ch, _inputMode, _gain) \
(_adc_ch)->CTRL = ((_adc_ch)->CTRL & \
(~(ADC_CH_INPUTMODE_gm|ADC_CH_GAIN_gm))) | \
((uint8_t) _inputMode|_gain)
#define ADC_Ch_InputMux_Config(_adc_ch, _posInput, _negInput) \
((_adc_ch)->MUXCTRL = (uint8_t) _posInput | _negInput)
#define ADC_Enable(_adc) ((_adc)->CTRLA |= ADC_ENABLE_bm)
#define COMMON_MODE_CYCLES 16
#define ADC_Conversions_Start(_adc, _channelMask) \
(_adc)->CTRLA |= _channelMask & \
(ADC_CH0START_bm | ADC_CH1START_bm | \
ADC_CH2START_bm | ADC_CH3START_bm)
#define ADC_Ch_Conversion_Start(_adc_ch) ((_adc_ch)->CTRL |= ADC_CH_START_bm)
#define ADC_Ch_Conversion_Complete(_adc_ch) \
(((_adc_ch)->INTFLAGS & ADC_CH_CHIF_bm) != 0x00)
#define ADC_BandgapReference_Enable(_adc) ((_adc)->REFCTRL |= ADC_BANDGAP_bm)
#define ADC_BandgapReference_Disable(_adc) ((_adc)->REFCTRL &= ~ADC_BANDGAP_bm)
uint8_t SP_ReadCalibrationByte( uint8_t index )
{
uint8_t result;
/* Load the NVM Command register to read the calibration row. */
NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
result = pgm_read_byte(index);
/* Clean up NVM Command register. */
NVM_CMD = NVM_CMD_NO_OPERATION_gc;
return result;
}
void ADC_Wait_8MHz(ADC_t * adc)
{
/* Store old prescaler value. */
uint8_t prescaler_val = adc->PRESCALER;
/* Set prescaler value to minimum value. */
adc->PRESCALER = ADC_PRESCALER_DIV4_gc;
/* Wait 4*COMMON_MODE_CYCLES for common mode to settle. */
_delay_us(4*COMMON_MODE_CYCLES);
/* Set prescaler to old value*/
adc->PRESCALER = prescaler_val;
}
int16_t ADC_ResultCh_GetWord_Signed(ADC_CH_t * adc_ch, int8_t signedOffset)
{
int16_t answer;
/* Clear interrupt flag.*/
adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
/* Return result register contents*/
answer = adc_ch->RES - signedOffset;
return answer;
}
uint16_t ADC_ResultCh_GetWord(ADC_CH_t * adc_ch)
{
/* Clear interrupt flag.*/
adc_ch->INTFLAGS = ADC_CH_CHIF_bm;
/* Return result register contents*/
return adc_ch->RES;;
}
int8_t ADC_Offset_Get_Signed(ADC_t * adc, ADC_CH_t *ch, int oversampling_n)
{
if (oversampling_n) {
int16_t offset=0;
for (int i=0; i<oversampling_n; i++) {
/* Do one conversion to find offset. */
ADC_Ch_Conversion_Start(ch);
do{
} while (!ADC_Ch_Conversion_Complete(ch));
offset += ADC_ResultCh_GetWord_Signed(ch, 0x00);
}
return ((int8_t)(offset/oversampling_n));
} else {
int8_t offset=0;
/* Do one conversion to find offset. */
ADC_Ch_Conversion_Start(ch);
do{
} while (!ADC_Ch_Conversion_Complete(ch));
offset = (uint8_t)ADC_ResultCh_GetWord_Signed(ch, 0x00);
return offset;
}
}
\ No newline at end of file
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define output(directions,pin) (directions |= pin) // set port direction for output
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 8.5 // bit delay for 115200 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define char_delay() _delay_ms(10) // char delay
void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) {
//
// read character into rxbyte on pins pin
// assumes line driver (inverts bits)
//
*rxbyte = 0;
while (pin_test(*pins,pin))
//
// wait for start bit
//
;
//
// delay to middle of first data bit
//
half_bit_delay();
bit_delay();
//
// unrolled loop to read data bits
//
if pin_test(*pins,pin)
*rxbyte |= (1 << 0);
else
*rxbyte |= (0 << 0);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 1);
else
*rxbyte |= (0 << 1);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 2);
else
*rxbyte |= (0 << 2);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 3);
else
*rxbyte |= (0 << 3);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 4);
else
*rxbyte |= (0 << 4);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 5);
else
*rxbyte |= (0 << 5);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 6);
else
*rxbyte |= (0 << 6);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 7);
else
*rxbyte |= (0 << 7);
//
// wait for stop bit
//
bit_delay();
half_bit_delay();
}
void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
//
// send character in txchar on port pin
// assumes line driver (inverts bits)
//
// start bit
//
clear(*port,pin);
bit_delay();
//
// unrolled loop to write data bits
//
if bit_test(txchar,0)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,1)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,2)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,3)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,4)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,5)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,6)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,7)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
//
// stop bit
//
set(*port,pin);
bit_delay();
//
// char delay
//
bit_delay();
}
void put_string(volatile unsigned char *port, unsigned char pin, char *str) {
//
// print a null-terminated string
//
static int index;
index = 0;
do {
put_char(port, pin, str[index]);
++index;
} while (str[index] != 0);
}
//
// hello.dac.8E5.c
//
// 8E5 dac
//
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
uint16_t lookup[128] = {
2047, 2147, 2247, 2347, 2446, 2544, 2641, 2736, 2830, 2922, 3011, 3099, 3184, 3266, 3345, 3421, 3494, 3563, 3629, 3691, 3749, 3802, 3852, 3897, 3938, 3974, 4005, 4032, 4054, 4071, 4084, 4091, 4094, 4091, 4084, 4071, 4054, 4032, 4005, 3974, 3938, 3897, 3852, 3802, 3749, 3691, 3629, 3563, 3494, 3421, 3345, 3266, 3184, 3099, 3011, 2922, 2830, 2736, 2641, 2544, 2446, 2347, 2247, 2147, 2047, 1947, 1847, 1747, 1648, 1550, 1453, 1358, 1264, 1172, 1083, 995, 910, 828, 749, 673, 600, 531, 465, 403, 345, 292, 242, 197, 156, 120, 89, 62, 40, 23, 10, 3, 0, 3, 10, 23, 40, 62, 89, 120, 156, 197, 242, 292, 345, 403, 465, 531, 600, 673, 749, 828, 910, 995, 1083, 1172, 1264, 1358, 1453, 1550, 1648, 1747, 1847, 1947
};
int main(void) {
//
// main
//
uint16_t angle=0;
//
// set up clock
//
//OSC.CTRL = OSC_RC32MEN_bm; // enable 32MHz clock
//while (!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for clock to be ready
//CCP = CCP_IOREG_gc; // enable protected register change
//CLK.CTRL = CLK_SCLKSEL_RC32M_gc; // switch to 32MHz clock
OSC.PLLCTRL = OSC_PLLFAC4_bm | OSC_PLLFAC3_bm; // 2 MHz * 24 = 48 MHz
OSC.CTRL = OSC_PLLEN_bm; // enable PLL
while (!(OSC.STATUS & OSC_PLLRDY_bm)); // wait for PLL to be ready
CCP = CCP_IOREG_gc; // enable protected register change
CLK.CTRL = CLK_SCLKSEL_PLL_gc; // switch to PLL
//set up dac
DACA.CTRLB = ( DACA.CTRLB & ~DAC_CHSEL_gm ) | DAC_CHSEL_DUAL_gc;
DACA.CTRLC = ( DACA.CTRLC & ~( DAC_REFSEL_gm | DAC_LEFTADJ_bm ) ) | DAC_REFSEL_AVCC_gc;
DACA.CTRLA = ( DACA.CTRLA & ~DAC_CH1EN_bm ) | DAC_CH0EN_bm | DAC_ENABLE_bm;
while(1){
DACA.CH0DATA = lookup[angle];
angle = (angle+1)%128;
}
}
PROJECT=hello.8E5.dac
SOURCES=$(PROJECT).c
MMCU=atxmega8e5
F_CPU = 32000000
TARGET = x8e5
PROGRAMMER= atmelice_pdi
CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)
$(PROJECT).hex: $(PROJECT).out
avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out
$(PROJECT).out: $(SOURCES)
avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program: $(PROJECT).hex
avrdude -p $(TARGET) -c $(PROGRAMMER) -U flash:w:$(PROJECT).c.hex
#!/usr/bin/env python
from math import *
a = 2048-1
r = 128
f = lambda x: sin(2*pi*x/r)
print [int(a*f(ti))+a for ti in range(r)]
<html>
<head></head>
<body>
<h1>XMega Learning</h1>
<h2>Toolchain Installation</h2>
<h3>Linux</h3>
<p>This installation is more or less straightforward:</p>
<ul>
<li><p>sudo apt get install ...</p></li>
</ul>
<p>TODO: do a fresh install and make notes.</p>
<h3>Mac</h3>
<p>Cross pack is a great bundle available via homebrew for these tools. Unfortunately, currently (3/21/2016) it doesn't include avr-libc v2.0, and so doesn't include support for the xmega8e5. I made an experimental homebrew tap with avr-libc v2.0 and arg-gcc 5.3.0. To get it, run:</p>
<ul>
<li><p>brew tap calischs/homebrew-avr</p></li>
<li><p>brew install calischs/avr/avr-gcc53</p></li>
<li><p>brew install calischs/avr/avr-libc20</p></li>
</ul>
<p>Also, as of 10/31/2016, there seems to be some strange behavior when trying to use an Atmel Ice programmer from a mac. When you try to program, you may see an error message from usbdev_open() about not claiming the interface. I used the answer posted <a href='http://www.avrfreaks.net/comment/1421981#comment-1421981'>here (post 32 and 33)</a> -- the attached kext file already has the correct VID and PID. A full restart was required.</p>
<h2>Examples</h2>
<p>Below are projects using the xmega peripherals as I'm learning about them. They definitely aren't minimal "hello world" examples, but at some point hopefully I'll get around to boiling them down. For the moment, however, hopefully they demonstrate how to use each capability of the mcu.</p>
<h3>DAC</h3>
<ul>
<li><a href='dac/sine.png'>Sine Wave</a></li>
<li><a href='dac/hello.8E5.dac.c'>hello.8E5.dac.c</a></li>
<li><a href='dac/hello.8E5.dac.make'>hello.8E5.dac.make</a></li>
<li><a href='dac/make_lookup.py'>make_lookup.py</a></li>
<li><a href='dac/xmega-8e5-dac-layout.png'>Layout</a></li>
<li><a href='dac/xmega-8e5-dac-traces.png'>Traces</a></li>
<li><a href='dac/xmega-8e5-dac-outline.png'>Outline</a></li>
<li><a href='dac/xmega-8e5-dac-board.jpg'>Board</a></li>
</ul>
<h3>Quadrature Decoding with Timer/Counters</h3>
<ul>
<li><a href='qdec/qdec.mp4'>Operation</a></li>
<li><a href='qdec/hello.16a4u.qdec.c'>hello.16a4u.qdec.c</a></li>
<li><a href='qdec/hello.16a4u.qdec.make'>hello.16a4u.qdec.make</a></li>
<li><a href='qdec/serial.h'>serial.h</a></li>
<li><a href='qdec/xmega-16a4u-qdec-layout.png'>Layout</a></li>
<li><a href='qdec/xmega-16a4u-qdec-traces.png'>Traces</a></li>
<li><a href='qdec/xmega-16a4u-qdec-interior.png'>Outline</a></li>
<li><a href='qdec/xmega-16a4u-qdec-board.jpg'>Board</a></li>
</ul>
<h3>ADC</h3>
<ul>
<li><a href='adc/adc.8E5.c'>adc.8E5.c</a></li>
<li><a href='adc/adc.8E5.make'>adc.8E5.make</a></li>
<li><a href='adc/serial.h'>serial.h</a></li>
<li><a href='adc/adc.h'>adc.h</a></li>
<li><a href='adc/adc.8E5.layout.png'>Layout</a></li>
<li><a href='adc/adc.8E5.traces.png'>Traces</a></li>
<li><a href='adc/adc.8E5.interior.png'>Outline</a></li>
<li><a href='adc/adc.8E5.board.jpg'>Board</a></li>
<li><a href='http://www.tag-connect.com/'>Tag Connect Programming connector</a></li>
<li><a href='adc/load-cell-small.mp4'>Force measurement using onboard 64x gain.</a></li>
<li><a href='http://www.phidgets.com/products.php?category=34&product_id=3133_0'>$7 load cell</a></li>
</ul>
<h3>USART</h3>
<ul>
<li><a href='usart/usart.32a4u.c'>usart.32a4u.c</a></li>
<li><a href='usart/usart.32a4u.make'>usart.32a4u.make</a></li>
<li><a href='usart/serial.h'>serial.h</a></li>
<li><a href='usart/usart.32a4u.layout.png'>Layout</a></li>
<li><a href='usart/usart.32a4u.traces.png'>Traces</a></li>
<li><a href='usart/usart.32a4u.interior.png'>Outline</a></li>
<li><a href='http://www.tag-connect.com/'>Tag Connect Programming connector</a></li>
</ul>
<h3>XCL</h3>
<ul>
<li><a href='xcl/xcl.8e5.c'>xcl.8e5.c</a></li>
<li><a href='xcl/xcl.8e5.make'>xcl.8e5.make</a></li>
<li><a href='xcl/xcl.8e5.layout.png'>Layout</a></li>
<li><a href='xcl/xcl.8e5.traces.png'>Traces</a></li>
<li><a href='xcl/xcl.8e5.interior.png'>Outline</a></li>
<li><a href='xcl/xcl.8e5.scope.png'>ANDing square waves (without power supplied to VCC!)</a></li>
</ul>
<h3>USB</h3>
<h3>DMA</h3>
<h3>WEX</h3>
</body>
</html>
\ No newline at end of file
//
// hello.ftdi.16A4.qdec.c
//
// 16A4 quadrature decoder with 115200 baud FTDI position and frequency report
//
#include <stdio.h>
#include "serial.h"
#define serial_port PORTD.OUT
#define serial_direction PORTD.DIR
#define serial_pins PORTD.IN
#define serial_pin_in PIN6_bm
#define serial_pin_out PIN7_bm
#define led_port PORTD.OUT
#define led_direction PORTD.DIR
#define led_pin PIN4_bm
#define CLOCK_DIV_bm TC_CLKSEL_DIV64_gc
#define CLOCK_DIV 64
int main(void) {
static char buffer[50] = {0};
uint16_t calcFreq = 0;
uint16_t calcPos = 0;