Skip to content
Snippets Groups Projects
Commit f0225dec authored by Michael DM Dryden's avatar Michael DM Dryden
Browse files

In progress

parent 39ccaabb
Branches
No related merge requests found
//
// ad5933.c
// dstat-firmware
//
// Created by Marc Goudge on 2016-12-18.
// Note: the library for AD5933 communications is largely based on the C++ library written
// by Michael Meli for Arduino. Minor adaptations have been made such that this library is compatible
// with the ATXmega256a3u.
#include "ad5933.h"
#include <twi_master.h>
#include <twi_common.h>
#include <ioport.h>
#include <sysclk.h>
#include <delay.h>
#include "settings.h"
#include "config/conf_board.h"
#define EIS_TWI TWIC
#define AD5933_ADDR 0x0D
#define ADDR_PTR 0xB0
// Control Register
#define CTRL_REG1 0x80
#define CTRL_REG2 0x81
// Start Frequency Register
#define START_FREQ_1 0x82
#define START_FREQ_2 0x83
#define START_FREQ_3 0x84
// Frequency increment register
#define INC_FREQ_1 0x85
#define INC_FREQ_2 0x86
#define INC_FREQ_3 0x87
// Number of increments register
#define NUM_INC_1 0x88
#define NUM_INC_2 0x89
// Number of settling time cycles register
#define NUM_SCYCLES_1 0x8A
#define NUM_SCYCLES_2 0x8B
// Status register
#define STATUS_REG 0x8F
// Temperature data register
#define TEMP_DATA_1 0x92
#define TEMP_DATA_2 0x93
// Real data register
#define REAL_DATA_1 0x94
#define REAL_DATA_2 0x95
// Imaginary data register
#define IMAG_DATA_1 0x96
#define IMAG_DATA_2 0x97
/**
* Constants
*/
// Temperature measuring
#define TEMP_MEASURE CTRL_TEMP_MEASURE
#define TEMP_NO_MEASURE CTRL_NO_OPERATION
// Clock sources
#define CLOCK_INTERNAL CTRL_CLOCK_INTERNAL
#define CLOCK_EXTERNAL CTRL_CLOCK_EXTERNAL
// PGA gain options
#define PGA_GAIN_X1 CTRL_PGA_GAIN_X1
#define PGA_GAIN_X5 CTRL_PGA_GAIN_X5
// Power modes
#define POWER_STANDBY CTRL_STANDBY_MODE
#define POWER_DOWN CTRL_POWER_DOWN_MODE
#define POWER_ON CTRL_NO_OPERATION
// I2C result success/fail
#define I2C_RESULT_SUCCESS 0
#define I2C_RESULT_DATA_TOO_LONG 1
#define I2C_RESULT_ADDR_NAK 2
#define I2C_RESULT_DATA_NAK 3
#define I2C_RESULT_OTHER_FAIL 4
// Control register options
#define CTRL_NO_OPERATION 0b00000000
#define CTRL_INIT_START_FREQ 0b00010000
#define CTRL_START_FREQ_SWEEP 0b00100000
#define CTRL_INCREMENT_FREQ 0b00110000
#define CTRL_REPEAT_FREQ 0b01000000
#define CTRL_TEMP_MEASURE 0b10010000
#define CTRL_POWER_DOWN_MODE 0b10100000
#define CTRL_STANDBY_MODE 0b10110000
#define CTRL_RESET 0b00010000
#define CTRL_CLOCK_EXTERNAL 0b00001000
#define CTRL_CLOCK_INTERNAL 0b00000000
#define CTRL_PGA_GAIN_X1 0b00000001
#define CTRL_PGA_GAIN_X5 0b00000000
#define CTRL_OUT_RANGE_1 0b00000000
#define CTRL_OUT_RANGE_2 0b00000110
#define CTRL_OUT_RANGE_3 0b00000100
#define CTRL_OUT_RANGE_4 0b00000010
#define CTRL_ADDR_PTR 0b10110000
#define CTRL_BLK_WRITE 0b10100000
#define CTRL_BLK_READ 0b10100001
// Status register options
#define STATUS_TEMP_VALID 0x01
#define STATUS_DATA_VALID 0x02
#define STATUS_SWEEP_DONE 0x04
#define STATUS_ERROR 0xFF
// Frequency sweep parameters
#define SWEEP_DELAY 1
// this was calculated per the data sheet
#define clockSpeed 16776000
uint8_t read_byte(uint8_t address);
void read_block(uint8_t address, uint8_t length, uint8_t* buffer);
void write_byte(uint8_t address, uint8_t value);
void write_block(uint8_t address, uint8_t length, uint8_t* buffer);
void ad_reset(void);
void internal_clock_set(bool);
bool ad_set_start_frequency(uint32_t);
bool ad_set_increment_frequency(uint32_t);
bool ad_set_num_increments(uint16_t);
void ad_set_gain(uint8_t pga_gain, uint8_t o_range);
void ad_set_control_mode(uint8_t);
uint8_t ad_read_register(uint8_t);
void ad_set_power_mode(uint8_t);
cuint16_t ad_get_complex_data(void);
void eis_init(void){
ioport_set_port_mode(IOPORT_PORTC, PIN0_bm|PIN1_bm, IOPORT_MODE_WIREDANDPULL);
sysclk_enable_peripheral_clock(&EIS_TWI);
twi_master_enable(&EIS_TWI);
twi_master_options_t opt = {
.speed = 50000,
.chip = 0x42
};
twi_master_setup(&EIS_TWI, &opt);
printf("#INFO: TWI master enabled\n\r");
}
uint8_t read_byte(uint8_t address) {
/**
* Reads one byte from AD5933
*
* @param address Address on AD5933
* @return Value read.
*/
twi_package_t twi_pack;
uint8_t value;
twi_pack.addr[0] = address;
twi_pack.addr_length = 1;
twi_pack.buffer = &value;
twi_pack.chip = AD5933_ADDR;
twi_pack.no_wait = false;
twi_pack.length = 1;
//read the data to *value to access
twi_master_read(&EIS_TWI, &twi_pack);
return value;
}
void read_block(uint8_t address, uint8_t length, uint8_t* buffer) {
/**
* Reads a block of data
*
* @param address Start address on AD5933
* @param length number of bytes to read.
* @param buffer pointer to buffer to store result
*/
twi_package_t twi_pack;
twi_pack.addr[0] = address;
twi_pack.addr_length = 1;
twi_pack.buffer = buffer;
twi_pack.chip = AD5933_ADDR;
twi_pack.no_wait = false;
twi_pack.length = 0;
if(twi_master_write(&EIS_TWI, &twi_pack) != TWI_SUCCESS)
printf("#ERR: AD5933 TWI write fail\r\n");
twi_pack.addr[0] = CTRL_BLK_READ;
twi_pack.addr[1] = length;
twi_pack.addr_length = 2;
twi_pack.buffer = buffer;
twi_pack.length = length;
twi_master_read(&EIS_TWI, &twi_pack);
}
void write_byte(uint8_t address, uint8_t value) {
/**
* Writes one byte to AD5933.
*
* @param address Address on AD5933
* @param Value to send.
*/
twi_package_t twi_pack;
twi_pack.addr[0] = address;
twi_pack.addr_length = 1;
twi_pack.buffer = &value;
twi_pack.chip = AD5933_ADDR;
twi_pack.no_wait = false;
twi_pack.length = 1;
if(twi_master_write(&EIS_TWI, &twi_pack) != TWI_SUCCESS)
printf("#ERR: AD5933 TWI write fail\r\n");
}
void write_block(uint8_t address, uint8_t length, uint8_t* buffer) {
/**
* Writes a block of data
*
* @param address Start address on AD5933
* @param length number of bytes to write.
* @param buffer pointer to buffer to write
*/
twi_package_t twi_pack;
twi_pack.addr[0] = address;
twi_pack.addr_length = 1;
twi_pack.buffer = buffer;
twi_pack.chip = AD5933_ADDR;
twi_pack.no_wait = false;
twi_pack.length = 0;
if(twi_master_write(&EIS_TWI, &twi_pack) != TWI_SUCCESS)
printf("#ERR: AD5933 TWI write fail\r\n");
twi_pack.addr[0] = CTRL_BLK_WRITE;
twi_pack.addr[1] = length;
twi_pack.addr_length = 2;
twi_pack.buffer = buffer;
twi_pack.length = length;
twi_master_write(&EIS_TWI, &twi_pack);
}
void ad5933_set_params(uint32_t start, uint32_t increment, uint16_t n_increments, uint16_t settle_cycles, uint8_t gain){
/**
* Set EIS sweep parameters.
*
* @param start Start Frequency
* @param increment Frequency increment
* @param n_increments Number of increments
* @param settle_cycles Number of settling cycles
* @param gain PGA gain
*/
internal_clock_set(1);
ad_reset();
ad_set_start_frequency(start);
ad_set_increment_frequency(increment);
ad_set_num_increments(n_increments);
ad_set_gain(gain, 1);
printf("Initializing of AD5933 Complete\r\n");
return;
}
void ad_reset(void) {
//resets the AD5933
uint8_t checkbit;
// get the CTRL_REG2 (contains D7-D0)
checkbit = read_byte(CTRL_REG2);
// reset the reset bit (D4)
checkbit |= CTRL_RESET;
//write the data to the AD5933
write_byte(CTRL_REG2, checkbit);
}
void internal_clock_set(bool internal) {
//set the control register to internal or external clock
if (internal)
write_byte(CTRL_REG2, CTRL_CLOCK_INTERNAL);
else
write_byte(CTRL_REG2, CTRL_CLOCK_EXTERNAL);
}
void test(uint32_t freq){
ad_set_start_frequency(freq);
// write_block(START_FREQ_1, 3, &freq);
uint32_t buffer1 = 0;
read_block(START_FREQ_1, 3, (uint8_t*)&buffer1+1);
printf("%lx\r\n", swap32(buffer1));
}
bool ad_set_start_frequency(uint32_t start) {
if (start > 0xFFFFFF) {
printf("#ERR: AD5933: Start frequency too high.\r\n");
return false; // overflow
}
uint32_t buffer = swap32(start);
write_block(START_FREQ_1, 3, (uint8_t*)&buffer+1);
return true;
}
bool ad_set_increment_frequency(uint32_t increment) {
if (increment > 0xFFFFFF) {
printf("#ERR: AD5933: Increment too high. \r\n");
return false; // overflow
}
uint32_t buffer = swap32(increment);
write_block(INC_FREQ_1, 3, (uint8_t*)&buffer+1);
return true;
}
bool ad_set_num_increments(uint16_t num) {
if (num > 511){
printf("#ERR: AD5933: Increment number too high. \r\n");
return false; // overflow
}
uint16_t buffer = swap16(num);
// attempt to write
write_block(NUM_INC_1, 2, (uint8_t*)&buffer);
return true;
}
void ad_set_gain(uint8_t pga_gain, uint8_t o_range) {
uint8_t val = 0;
switch (pga_gain) {
case 1:
val |= PGA_GAIN_X1;
break;
case 5:
val |= PGA_GAIN_X5;
break;
default:
val |= PGA_GAIN_X1;
break;
}
switch (o_range) {
case 1:
val |= CTRL_OUT_RANGE_1;
break;
case 2:
val |= CTRL_OUT_RANGE_2;
break;
case 3:
val |= CTRL_OUT_RANGE_3;
break;
case 4:
val |= CTRL_OUT_RANGE_4;
break;
default:
val |= CTRL_OUT_RANGE_1;
break;
}
write_byte(CTRL_REG1, val);
return;
}
void ad_set_control_mode(uint8_t mode) {
uint8_t val = read_byte(CTRL_REG1);
// clear out the top 4 bits
val &= 0x00001111;
val |= mode;
write_byte(CTRL_REG1, val);
return;
}
uint8_t ad_read_register(uint8_t reg) {
// short script to read registers
uint8_t val = read_byte(reg);
return val;
}
uint8_t ad_read_status(void) {
//short script to read register
return ad_read_register(STATUS_REG);
}
void ad_set_power_mode(uint8_t level) {
switch (level) {
case POWER_ON:
ad_set_control_mode(CTRL_NO_OPERATION);
return;
case POWER_STANDBY:
ad_set_control_mode(CTRL_STANDBY_MODE);
return;
case POWER_DOWN:
ad_set_control_mode(CTRL_POWER_DOWN_MODE);
return;
}
}
void ad5933_sweep(cuint16_t imp[], int n) {
// issue needed commands to start sweep
ad_set_power_mode(POWER_STANDBY); // place in standby
ad_set_control_mode(CTRL_INIT_START_FREQ); // init start freq
ad_set_control_mode(CTRL_START_FREQ_SWEEP);
for (uint16_t i = 0; i < n; i++) {
if ((ad_read_status() & STATUS_SWEEP_DONE) != STATUS_SWEEP_DONE) { /////////////!!
break;
}
else {
imp[i] = ad_get_complex_data();
delay_ms(100);
ad_set_control_mode(CTRL_INCREMENT_FREQ);
}
}
ad_set_power_mode(POWER_STANDBY);
return;
// int i = 0;
//
// //check the register for sweep completion as loop condition
// while ((ad_read_status() & STATUS_SWEEP_DONE) != STATUS_SWEEP_DONE) {
// // Make sure we aren't exceeding the bounds of our buffer
// if (i >= n) {
// return;
// }
//
// // Get the data for this frequency point and store it in the array
// ad_get_complex_data(&real[i], &imag[i]);
//
// i++;
//
// delay_ms(100);
// ad_set_control_mode(CTRL_INCREMENT_FREQ);
// }
//
// // change power mode to standy
// ad_set_power_mode(POWER_STANDBY);
// return;
}
cuint16_t ad_get_complex_data(void) {
// poll the status register to check for data to receive
while ((ad_read_status() & STATUS_DATA_VALID) != STATUS_DATA_VALID);
uint16_t real;
uint16_t imag;
read_block(REAL_DATA_1, 2, &real);
read_block(IMAG_DATA_1, 2, &imag);
cuint16_t result;
result.real = swap16(real);
result.imag = swap16(imag);
return result;
}
//
// ad5933.h
// dstat-firmware
//
// Created by Marc Goudge on 2016-12-18.
// Note: the library for AD5933 communications is largely based on the C++ library written
// by Michael Meli for Arduino. Adaptations have been made such that this library is compatible
// with the ATXmega256a3u.
#ifndef ad5933_h
#define ad5933_h
#include <math.h>
#include <stdio.h>
void eis_init(void);
uint8_t ad_read_status(void);
void ad5933_set_params(uint32_t start, uint32_t increment, uint16_t n_increments, uint16_t settle_cycles, uint8_t gain);
void test(uint32_t freq);
typedef struct c_uint16_t {
uint16_t real;
uint16_t imag;
} cuint16_t;
void ad5933_sweep(cuint16_t imp[], int n);
#endif /* ad5933_h */
This diff is collapsed.
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment