// hello.stepper.bipolar.44.full.c
//
// bipolar full stepping hello-world
//
// Neil Gershenfeld
// 11/21/12
//
// modified by Luis Díaz
// 05/12
//
//
//
// (c) Massachusetts Institute of Technology 2012
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all
// liability.
//
/**
* \\mainpage User Application template doxygen documentation
*
* \\par Empty user application template
*
* Bare minimum empty user application template
*
* \\par Content
*
* -# Include the ASF header files (through asf.h)
* -# "Insert system clock initialization code here" comment
* -# Minimal main function that starts with a call to board_init()
* -# "Insert application code here" comment
*
*/
/*
* Include header files for all drivers that have been imported from
* Atmel Software Framework (ASF).
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#include <asf.h>
//#define MOTORTEST
#define ADCDAC
//#define SINETEST
//Stepper driver pins
#define A2 IOPORT_CREATE_PIN(PORTC, 1)
#define A1 IOPORT_CREATE_PIN(PORTC, 2)
#define B2 IOPORT_CREATE_PIN(PORTC, 3)
#define B1 IOPORT_CREATE_PIN(PORTC, 4)
// ADC/DAC
#define DAC1 IOPORT_CREATE_PIN(PORTA, 3)
#define DAC2 IOPORT_CREATE_PIN(PORTA, 2)
#define ADC1 IOPORT_CREATE_PIN(PORTD, 4)
#define MY_ADC ADCA
#define ADC_SND_CH ADC_CH0 //PD4
#define SPEAKER_DAC DACA
#define SPEAKER_DAC_CHANNEL DAC_CH0
#define RATE_OF_CONVERSION 22050
#define NR_OF_SAMPLES 32
//LED pins
#define GL IOPORT_CREATE_PIN(PORTR, 0) //blue led
#define BL IOPORT_CREATE_PIN(PORTR, 1) //green led
#define on_delay() delay_us(25) // PWM on time
#define off_delay() delay_us(5) // PWM off time
#define PWM_count 100 // number of PWM cycles
#define step_count 20 // number of steps
static const uint16_t sine[NR_OF_SAMPLES] = {
32768, 35325, 37784, 40050, 42036, 43666, 44877, 45623,
45875, 45623, 44877, 43666, 42036, 40050, 37784, 35325,
32768, 30211, 27752, 25486, 23500, 21870, 20659, 19913,
19661, 19913, 20659, 21870, 23500, 25486, 27752, 30211,
};
static uint8_t count;
uint8_t i = 0;
void pulse_ApBp(void);
void pulse_AmBp(void);
void pulse_ApBm(void);
void pulse_AmBm(void);
void step_ccw(void);
void step_cw(void);
uint16_t read_sound(void);
void write_sound(uint16_t);
void write_sine(void);
static void adc_init(void);
static void evsys_init(void);
void tc_init(void);
void dac_init(void);
int main (void)
{
/* Insert system clock initialization code here (sysclk_init()). */
sysclk_init();
#if defined(ADCDAC) || defined(SINETEST)
evsys_init();
tc_init();
dac_init();
adc_init();
#endif
board_init();
delay_init();
//
// main
//
#ifdef MOTORTEST
static uint8_t i,j;
#endif
//
//
// initialize bridge pins
//
//PC1 to PC4 as outputs
ioport_set_pin_dir(A1, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(A2, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(B1, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(B2, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(ADC1, IOPORT_DIR_INPUT);
ioport_set_pin_dir(DAC1, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(DAC2, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(BL, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(GL, IOPORT_DIR_OUTPUT);
ioport_set_pin_low(A1);
ioport_set_pin_low(A2);
ioport_set_pin_low(B1);
ioport_set_pin_low(B2);
ioport_set_pin_high(BL);
ioport_set_pin_high(GL);
delay_s(1);
ioport_set_pin_low(BL);
uint16_t adc_value = 0;
//
// main loop
//
while (1) {
#ifdef MOTORTEST
for (i = 0; i < step_count; ++i) {
for (j = 0; j < i; ++j)
step_cw();
for (j = 0; j < i; ++j)
step_ccw();
}
for (i = step_count; i > 0; --i) {
for (j = 0; j < i; ++j)
step_cw();
for (j = 0; j < i; ++j)
step_ccw();
}
#endif
#ifdef ADCDAC
adc_value = read_sound();
ioport_set_pin_high(BL);
delay_ms(adc_value);
ioport_set_pin_low(BL);
delay_ms(adc_value);
//write_sound(adc_value);
#endif
#ifdef SINETEST
write_sine();
#endif
}
}
//
// A+ B+ PWM pulse
//
void pulse_ApBp() {
ioport_set_pin_low(A2);
ioport_set_pin_low(B2);
ioport_set_pin_high(A1);
ioport_set_pin_high(B1);
for (count = 0; count < PWM_count; ++count) {
ioport_set_pin_high(A1);
ioport_set_pin_high(B1);
on_delay();
ioport_set_pin_low(A1);
ioport_set_pin_low(B1);
off_delay();
}
}
//
// A+ B- PWM pulse
//
void pulse_ApBm() {
ioport_set_pin_low(A2);
ioport_set_pin_low(B1);
ioport_set_pin_high(A1);
ioport_set_pin_high(B2);
for (count = 0; count < PWM_count; ++count) {
ioport_set_pin_high(A1);
ioport_set_pin_high(B2);
on_delay();
ioport_set_pin_low(A1);
ioport_set_pin_low(B2);
off_delay();
}
}
//
// A- B+ PWM pulse
//
void pulse_AmBp() {
ioport_set_pin_low(A1);
ioport_set_pin_low(B2);
ioport_set_pin_high(A2);
ioport_set_pin_high(B1);
for (count = 0; count < PWM_count; ++count) {
ioport_set_pin_high(A2);
ioport_set_pin_high(B1);
on_delay();
ioport_set_pin_low(A2);
ioport_set_pin_low(B1);
off_delay();
}
}
//
// A- B- PWM pulse
//
void pulse_AmBm() {
ioport_set_pin_low(A1);
ioport_set_pin_low(B1);
ioport_set_pin_high(A2);
ioport_set_pin_high(B2);
for (count = 0; count < PWM_count; ++count) {
ioport_set_pin_high(A2);
ioport_set_pin_high(B2);
on_delay();
ioport_set_pin_low(A2);
ioport_set_pin_low(B2);
off_delay();
}
}
//
// clockwise step
//
void step_cw() {
pulse_ApBp();
pulse_AmBp();
pulse_AmBm();
pulse_ApBm();
}
//
// counter-clockwise step
//
void step_ccw() {
pulse_ApBm();
pulse_AmBm();
pulse_AmBp();
pulse_ApBp();
}
//
// read adc
//
static void adc_init(void)
{
struct adc_config adc_conf;
struct adc_channel_config adcch_conf;
adc_read_configuration(&MY_ADC, &adc_conf);
adcch_read_configuration(&MY_ADC, ADC_SND_CH, &adcch_conf);
adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12,
ADC_REF_VCC);
adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0);
adc_set_clock_rate(&adc_conf, 200000UL);
adcch_set_input(&adcch_conf, ADCCH_POS_PIN12, ADCCH_NEG_NONE, 1);
adc_write_configuration(&MY_ADC, &adc_conf);
adcch_write_configuration(&MY_ADC, ADC_SND_CH, &adcch_conf);
}
uint16_t read_sound()
{
uint16_t result;
adc_enable(&MY_ADC);
adc_start_conversion(&MY_ADC, ADC_SND_CH);
adc_wait_for_interrupt_flag(&MY_ADC, ADC_SND_CH);
result = adc_get_result(&MY_ADC, ADC_SND_CH);
return result;
}
static void evsys_init(void)
{
sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS);
EVSYS.CH3MUX = EVSYS_CHMUX_TCC4_OVF_gc;
}
void tc_init(void)
{
tc45_enable(&TCC4);
tc45_set_wgm(&TCC4, TC45_WG_NORMAL);
tc45_write_period(&TCC4, (sysclk_get_per_hz() / RATE_OF_CONVERSION) - 1);
tc45_write_clock_source(&TCC4, TC45_CLKSEL_DIV1_gc);
}
void dac_init(void)
{
struct dac_config conf;
dac_read_configuration(&SPEAKER_DAC, &conf);
dac_set_conversion_parameters(&conf, DAC_REF_BANDGAP, DAC_ADJ_LEFT);
dac_set_active_channel(&conf, SPEAKER_DAC_CHANNEL, 0);
dac_set_conversion_trigger(&conf, SPEAKER_DAC_CHANNEL, 3);
#ifdef XMEGA_DAC_VERSION_1
dac_set_conversion_interval(&conf, 1);
#endif
dac_write_configuration(&SPEAKER_DAC, &conf);
dac_enable(&SPEAKER_DAC);
}
void write_sound(uint16_t value)
{
dac_wait_for_channel_ready(&SPEAKER_DAC, SPEAKER_DAC_CHANNEL);
dac_set_channel_value(&SPEAKER_DAC, SPEAKER_DAC_CHANNEL, value);
}
void write_sine(void)
{
dac_wait_for_channel_ready(&SPEAKER_DAC, SPEAKER_DAC_CHANNEL);
dac_set_channel_value(&SPEAKER_DAC, SPEAKER_DAC_CHANNEL, sine[i]);
i++;
i %= NR_OF_SAMPLES;
}