Compare commits
14 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 59086bd28b | |||
| 6477248e3b | |||
| 604dc1ad60 | |||
| b97b731bb9 | |||
| 1bc91feed8 | |||
| 755f8a96a2 | |||
| 875ad2f30a | |||
| c389c998dd | |||
| 0c5fcf85ac | |||
| 530ea98b28 | |||
| 8161e5c857 | |||
| c5fc7461e7 | |||
| 42853f1ca2 | |||
| 53990d1d3c |
5 changed files with 556 additions and 81 deletions
11
README.md
11
README.md
|
|
@ -46,5 +46,16 @@ ctest
|
||||||
- add functions to load saved configs
|
- add functions to load saved configs
|
||||||
|
|
||||||
|
|
||||||
|
###Mocking the TWI/I2C
|
||||||
|
|
||||||
|
The twi needs to be mocked or faked correctly to make the testing
|
||||||
|
of the functions doable.
|
||||||
|
|
||||||
|
The best way I can find to handle this is with a buffer of twi data
|
||||||
|
that simulate registers that the program reads/writes to.
|
||||||
|
|
||||||
|
This is handled by using function pointers for the tx and rx of i2c/twi data.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,18 @@
|
||||||
* Description: The implimentation file for the gy521 module, assumes TWI/I2c
|
* Description: The implimentation file for the gy521 module, assumes TWI/I2c
|
||||||
*/
|
*/
|
||||||
#include "gy521_driver.h"
|
#include "gy521_driver.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* MACROS
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*DEBUG macro*/
|
||||||
|
#define DEBUG
|
||||||
|
#define debug_print(fmt, ...) \
|
||||||
|
do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0)
|
||||||
|
|
||||||
|
|
||||||
/*Stuff for cmocka*/
|
/*Stuff for cmocka*/
|
||||||
#if UNIT_TESTING
|
#if UNIT_TESTING
|
||||||
|
|
@ -16,51 +27,16 @@ extern void _test_free(void* const ptr, const char* file, const int line);
|
||||||
#define malloc(size) _test_malloc(size, __FILE__, __LINE__)
|
#define malloc(size) _test_malloc(size, __FILE__, __LINE__)
|
||||||
#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
|
#define calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__)
|
||||||
#define free(ptr) _test_free(ptr, __FILE__, __LINE__)
|
#define free(ptr) _test_free(ptr, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
/*Mock assertions: redefines assert() calls*/
|
||||||
|
extern void mock_assert(const int result, const char* const expression,
|
||||||
|
const char * const file, const int line);
|
||||||
|
#undef assert
|
||||||
|
#define assert(expression) \
|
||||||
|
mock_assert((int)(expression), #expression, __FILE__, __LINE__);
|
||||||
|
|
||||||
#endif // UNIT_TESTING
|
#endif // UNIT_TESTING
|
||||||
|
|
||||||
#define NUM_ACCEL_REGS 6
|
|
||||||
#define NUM_GYRO_REGS 6
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ############################
|
|
||||||
* REGISTER MAP
|
|
||||||
* ############################
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum gy521_map {
|
|
||||||
accel_xouth = 0x3B,
|
|
||||||
accel_xoutl,
|
|
||||||
accel_youth,
|
|
||||||
accel_youtl,
|
|
||||||
accel_zouth,
|
|
||||||
accel_zoutl,
|
|
||||||
temp_outh,
|
|
||||||
temp_outl,
|
|
||||||
gyro_xouth,
|
|
||||||
gyro_xoutl,
|
|
||||||
gyro_youth,
|
|
||||||
gyro_youtl,
|
|
||||||
gyro_zouth,
|
|
||||||
gyro_zoutl,
|
|
||||||
fifo_couth = 0x72,
|
|
||||||
fifo_contl,
|
|
||||||
fifo_r_w,
|
|
||||||
who_am_i,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ############################
|
|
||||||
* Structures
|
|
||||||
* ############################
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct gy521_module{
|
|
||||||
uint8_t slave_address;
|
|
||||||
gyro_values_struct gyro;
|
|
||||||
accel_values_struct accel;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ############################
|
* ############################
|
||||||
|
|
@ -82,7 +58,8 @@ uint8_t read_register(gy521_module *m, enum gy521_map reg)
|
||||||
|
|
||||||
void write_register(gy521_module *m, enum gy521_map reg, uint8_t data)
|
void write_register(gy521_module *m, enum gy521_map reg, uint8_t data)
|
||||||
{
|
{
|
||||||
gy521_twi_tx(m->slave_address, (uint8_t *) ®, data);
|
uint8_t in_data = reg;
|
||||||
|
gy521_twi_tx(m->slave_address, &in_data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -132,8 +109,10 @@ void gy521_update_accel(gy521_module *m)
|
||||||
/*We shift the High byte over by 8 for a u16*/
|
/*We shift the High byte over by 8 for a u16*/
|
||||||
m->accel.x = read_register(m, accel_xouth) <<8;
|
m->accel.x = read_register(m, accel_xouth) <<8;
|
||||||
m->accel.x |= read_register(m, accel_xoutl);
|
m->accel.x |= read_register(m, accel_xoutl);
|
||||||
|
|
||||||
m->accel.y = read_register(m, accel_youth) <<8;
|
m->accel.y = read_register(m, accel_youth) <<8;
|
||||||
m->accel.y |= read_register(m, accel_youtl);
|
m->accel.y |= read_register(m, accel_youtl);
|
||||||
|
|
||||||
m->accel.z = read_register(m, accel_zouth) <<8;
|
m->accel.z = read_register(m, accel_zouth) <<8;
|
||||||
m->accel.z |= read_register(m, accel_zoutl);
|
m->accel.z |= read_register(m, accel_zoutl);
|
||||||
}
|
}
|
||||||
|
|
@ -143,8 +122,10 @@ void gy521_update_gyro(gy521_module *m)
|
||||||
/*We shift the High byte over by 8 for a u16*/
|
/*We shift the High byte over by 8 for a u16*/
|
||||||
m->gyro.x = read_register(m, gyro_xouth) <<8;
|
m->gyro.x = read_register(m, gyro_xouth) <<8;
|
||||||
m->gyro.x |= read_register(m, gyro_xoutl);
|
m->gyro.x |= read_register(m, gyro_xoutl);
|
||||||
|
|
||||||
m->gyro.y = read_register(m, gyro_youth) <<8;
|
m->gyro.y = read_register(m, gyro_youth) <<8;
|
||||||
m->gyro.y |= read_register(m, gyro_youtl);
|
m->gyro.y |= read_register(m, gyro_youtl);
|
||||||
|
|
||||||
m->gyro.z = read_register(m, gyro_zouth) <<8;
|
m->gyro.z = read_register(m, gyro_zouth) <<8;
|
||||||
m->gyro.z |= read_register(m, gyro_zoutl);
|
m->gyro.z |= read_register(m, gyro_zoutl);
|
||||||
}
|
}
|
||||||
|
|
@ -168,3 +149,101 @@ struct gyro_values gy521_get_gyro(struct gy521_module* m)
|
||||||
s.z = m->gyro.z;
|
s.z = m->gyro.z;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void enable_self_test_gyro(struct gy521_module* m)
|
||||||
|
{
|
||||||
|
/*Set the values in the GYRO_CONFIG register*/
|
||||||
|
/*According to the datasheet setting it for 250 is needed*/
|
||||||
|
uint8_t reg = XG_ST + YG_ST + ZG_ST + FS_SEL_250;
|
||||||
|
write_register(m, gyro_config, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable_self_test_gyro(struct gy521_module* m)
|
||||||
|
{
|
||||||
|
write_register(m, gyro_config, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ft_vals self_test_ft_calculation(struct gy521_module* m)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*We make an array with 0 --> x, 1--> y, 2-->z*/
|
||||||
|
float factory_trim_vals[3];
|
||||||
|
uint8_t gyro_test[3] = {0};
|
||||||
|
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 3; i++) {
|
||||||
|
/*Reads the registers for self testing the gyro*/
|
||||||
|
gyro_test[i] = read_register(m, self_test_x + i) & 0x0F;
|
||||||
|
|
||||||
|
/*Skip doing calculations if the test value is zero*/
|
||||||
|
if(gyro_test[i] == 0){
|
||||||
|
factory_trim_vals[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(gyro_test[i] == 1) {
|
||||||
|
factory_trim_vals[i] = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
factory_trim_vals[i] = 1.046;
|
||||||
|
for(uint8_t j = 0; j < (gyro_test[i] - 1); j++){
|
||||||
|
factory_trim_vals[i] *= 1.046;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
factory_trim_vals[i] *= (25 * 131);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ft_vals ft;
|
||||||
|
ft.x = factory_trim_vals[0];
|
||||||
|
ft.y = factory_trim_vals[1];
|
||||||
|
ft.z = factory_trim_vals[2];
|
||||||
|
|
||||||
|
return ft;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Self Test register functions*/
|
||||||
|
self_test_results gy521_self_test(struct gy521_module* m)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*0. Enable self test*/
|
||||||
|
enable_self_test_gyro(m);
|
||||||
|
|
||||||
|
/*1. read the reg FT values*/
|
||||||
|
/*2. calulate the FT using the formula from the datasheet*/
|
||||||
|
struct ft_vals factory_trim = self_test_ft_calculation(m);
|
||||||
|
|
||||||
|
/*3. Read the STR data from the gyro*/
|
||||||
|
gy521_update_gyro(m);
|
||||||
|
struct gyro_values STR = m->gyro;
|
||||||
|
|
||||||
|
/*4. Disable the self test mode.*/
|
||||||
|
disable_self_test_gyro(m);
|
||||||
|
|
||||||
|
/*5. Now get the normal gyro data*/
|
||||||
|
gy521_update_gyro(m);
|
||||||
|
|
||||||
|
/*6. Finish the STR calculation*/
|
||||||
|
STR.x -= m->gyro.x;
|
||||||
|
STR.y -= m->gyro.y;
|
||||||
|
STR.z -= m->gyro.z;
|
||||||
|
|
||||||
|
/*7. Now we calculate the change from the FT of the STR*/
|
||||||
|
float testing_value = ( ((float)STR.x) - factory_trim.x) / factory_trim.x;
|
||||||
|
if(testing_value > GYRO_MAX_ST || testing_value < GYRO_MIN_ST) {
|
||||||
|
return gyro_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
testing_value = ( ((float)STR.y) - factory_trim.y) / factory_trim.y;
|
||||||
|
if(testing_value > GYRO_MAX_ST || testing_value < GYRO_MIN_ST) {
|
||||||
|
return gyro_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
testing_value = ( ((float)STR.z) - factory_trim.z) / factory_trim.z;
|
||||||
|
if(testing_value > GYRO_MAX_ST || testing_value < GYRO_MIN_ST) {
|
||||||
|
return gyro_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Return that we passed the self test if it's within parameters*/
|
||||||
|
return passed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
#ifndef GY521_DRIVER_H
|
#ifndef GY521_DRIVER_H
|
||||||
#define GY521_DRIVER_H
|
#define GY521_DRIVER_H
|
||||||
|
#include "gy521_interface.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -16,15 +15,31 @@
|
||||||
* ############################
|
* ############################
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STARTUP_DELAY 30 //in ms
|
#define NUM_ACCEL_REGS 6
|
||||||
#define TWI_GY521_ADDR1 0x68 //ADO Logic Low
|
#define NUM_GYRO_REGS 6
|
||||||
#define TWI_GY521_ADDR2 0x69 //ADO Logic High
|
|
||||||
|
/*GYRO MIN MAX PARAMETERS(percentage)*/
|
||||||
|
#define GYRO_MIN_ST -14
|
||||||
|
#define GYRO_MAX_ST 14
|
||||||
|
|
||||||
|
|
||||||
|
/*GYRO_CONFIG*/
|
||||||
|
#define XG_ST (1<<7)
|
||||||
|
#define YG_ST (1<<6)
|
||||||
|
#define ZG_ST (1<<5)
|
||||||
|
#define FS_SEL_MSK 0x18//0b00011000
|
||||||
|
#define FS_SEL_250 0
|
||||||
|
#define FS_SEL_500 (1<<3)
|
||||||
|
#define FS_SEL_1000 (1<<4)
|
||||||
|
#define FS_SEL_2000 (1<<4)|(1<<3)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ############################
|
* ############################
|
||||||
* Types/Structures
|
* Types/Structures
|
||||||
* ############################
|
* ############################
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct gyro_values{
|
typedef struct gyro_values{
|
||||||
uint16_t x;
|
uint16_t x;
|
||||||
uint16_t y;
|
uint16_t y;
|
||||||
|
|
@ -37,7 +52,115 @@ typedef struct accel_values{
|
||||||
uint16_t z;
|
uint16_t z;
|
||||||
}accel_values_struct;
|
}accel_values_struct;
|
||||||
|
|
||||||
typedef struct gy521_module gy521_module;
|
struct gy521_module{
|
||||||
|
uint8_t slave_address;
|
||||||
|
gyro_values_struct gyro;
|
||||||
|
accel_values_struct accel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ft_vals{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* REGISTER MAP
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*This thing is fairly huge, but it's got pretty much all the registers
|
||||||
|
* on it.*/
|
||||||
|
|
||||||
|
enum gy521_map {
|
||||||
|
self_test_x = 0x0D,
|
||||||
|
self_test_y,
|
||||||
|
self_test_z,
|
||||||
|
self_test_a,
|
||||||
|
smplrt_div = 0x19,
|
||||||
|
config,
|
||||||
|
gyro_config,
|
||||||
|
accel_config,
|
||||||
|
fifo_en = 0x23,
|
||||||
|
i2c_mst_ctrl,
|
||||||
|
i2c_slv0_addr,
|
||||||
|
i2c_slv0_reg,
|
||||||
|
i2c_slv0_ctrl,
|
||||||
|
i2c_slv1_addr,
|
||||||
|
i2c_slv1_reg,
|
||||||
|
i2c_slv1_ctrl,
|
||||||
|
i2c_slv2_addr,
|
||||||
|
i2c_slv2_reg,
|
||||||
|
i2c_slv2_ctrl,
|
||||||
|
i2c_slv3_addr,
|
||||||
|
i2c_slv3_reg,
|
||||||
|
i2c_slv3_ctrl,
|
||||||
|
i2c_slv4_addr,
|
||||||
|
i2c_slv4_reg,
|
||||||
|
i2c_slv4_do,
|
||||||
|
i2c_slv4_ctrl,
|
||||||
|
i2c_slv4_di,
|
||||||
|
i2c_mst_status,
|
||||||
|
int_pin_cfg,
|
||||||
|
int_enable,
|
||||||
|
int_status,
|
||||||
|
accel_xouth = 0x3B,
|
||||||
|
accel_xoutl,
|
||||||
|
accel_youth,
|
||||||
|
accel_youtl,
|
||||||
|
accel_zouth,
|
||||||
|
accel_zoutl,
|
||||||
|
temp_outh,
|
||||||
|
temp_outl,
|
||||||
|
gyro_xouth,
|
||||||
|
gyro_xoutl,
|
||||||
|
gyro_youth,
|
||||||
|
gyro_youtl,
|
||||||
|
gyro_zouth,
|
||||||
|
gyro_zoutl,
|
||||||
|
ext_sens_data_00,
|
||||||
|
ext_sens_data_01,
|
||||||
|
ext_sens_data_02,
|
||||||
|
ext_sens_data_03,
|
||||||
|
ext_sens_data_04,
|
||||||
|
ext_sens_data_05,
|
||||||
|
ext_sens_data_06,
|
||||||
|
ext_sens_data_07,
|
||||||
|
ext_sens_data_08,
|
||||||
|
ext_sens_data_09,
|
||||||
|
ext_sens_data_10,
|
||||||
|
ext_sens_data_11,
|
||||||
|
ext_sens_data_12,
|
||||||
|
ext_sens_data_13,
|
||||||
|
ext_sens_data_14,
|
||||||
|
ext_sens_data_15,
|
||||||
|
ext_sens_data_16,
|
||||||
|
ext_sens_data_17,
|
||||||
|
ext_sens_data_18,
|
||||||
|
ext_sens_data_19,
|
||||||
|
ext_sens_data_20,
|
||||||
|
ext_sens_data_21,
|
||||||
|
ext_sens_data_22,
|
||||||
|
ext_sens_data_23,
|
||||||
|
i2c_slv0_do,
|
||||||
|
i2c_slv1_do,
|
||||||
|
i2c_slv2_do,
|
||||||
|
i2c_slv3_do,
|
||||||
|
i2c_mst_delay_ctrl,
|
||||||
|
signal_path_reset,
|
||||||
|
user_ctrl,
|
||||||
|
pwr_mgmt_1,
|
||||||
|
pwr_mgmt_2,
|
||||||
|
fifo_couth = 0x72,
|
||||||
|
fifo_contl,
|
||||||
|
fifo_r_w,
|
||||||
|
who_am_i,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ############################
|
* ############################
|
||||||
|
|
@ -45,22 +168,22 @@ typedef struct gy521_module gy521_module;
|
||||||
* ############################
|
* ############################
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
gy521_module* gy521_new(void);
|
||||||
|
|
||||||
/*Function pointers for the TX and RX fuctionality*/
|
void disable_self_test_gyro(struct gy521_module* m);
|
||||||
|
void enable_self_test_gyro(struct gy521_module* m);
|
||||||
|
struct ft_vals self_test_ft_calculation(struct gy521_module* m);
|
||||||
|
self_test_results gy521_self_test(struct gy521_module* m);
|
||||||
|
|
||||||
extern void (*gy521_twi_tx)(uint8_t, uint8_t*, uint8_t);
|
uint8_t read_register(gy521_module *m, enum gy521_map reg);
|
||||||
extern void (*gy521_twi_rx)(uint8_t, uint8_t*, uint8_t);
|
void write_register(gy521_module *m, enum gy521_map reg, uint8_t data);
|
||||||
|
|
||||||
|
|
||||||
struct gy521_module* gy521_new(void);
|
|
||||||
_Bool gy521_init(struct gy521_module *m, uint8_t slave_address);
|
|
||||||
void gy521_update_gyro(struct gy521_module* m);
|
|
||||||
void gy521_update_accel(struct gy521_module* m);
|
|
||||||
void gy521_free(struct gy521_module *m);
|
|
||||||
|
|
||||||
/*These are used instead of direct access; assuming interrupt driven*/
|
/*These are used instead of direct access; assuming interrupt driven*/
|
||||||
/*updates to the gy521 then it protects the user from using volatile values*/
|
/*updates to the gy521 then it protects the user from using volatile values*/
|
||||||
struct accel_values gy521_get_accel(struct gy521_module* m);
|
struct accel_values gy521_get_accel(struct gy521_module* m);
|
||||||
struct gyro_values gy521_get_gyro(struct gy521_module* m);
|
struct gyro_values gy521_get_gyro(struct gy521_module* m);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* GY521_DRIVER_H */
|
#endif /* GY521_DRIVER_H */
|
||||||
|
|
|
||||||
56
src/gy521_driver/gy521_interface.h
Normal file
56
src/gy521_driver/gy521_interface.h
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake Goodwin
|
||||||
|
* Filename: interface.h
|
||||||
|
* Description: The file you should include for normal use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*Function pointers for the TX and RX fuctionality*/
|
||||||
|
|
||||||
|
#ifndef _GY521_INTERFACE_H
|
||||||
|
#define _GY521_INTERFACE_H
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* DEFINES
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define STARTUP_DELAY 30 //in ms
|
||||||
|
#define TWI_GY521_ADDR1 0x68 //ADO Logic Low
|
||||||
|
#define TWI_GY521_ADDR2 0x69 //ADO Logic High
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* Structures & Typedefs
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct gy521_module gy521_module;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
passed = 0,
|
||||||
|
gyro_failed,
|
||||||
|
accel_failed,
|
||||||
|
}self_test_results;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* Fuction Prototypes
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern void (*gy521_twi_tx)(uint8_t, uint8_t*, uint8_t);
|
||||||
|
extern void (*gy521_twi_rx)(uint8_t, uint8_t*, uint8_t);
|
||||||
|
|
||||||
|
|
||||||
|
struct gy521_module* gy521_new(void);
|
||||||
|
_Bool gy521_init(struct gy521_module *m, uint8_t slave_address);
|
||||||
|
void gy521_update_gyro(struct gy521_module* m);
|
||||||
|
void gy521_update_accel(struct gy521_module* m);
|
||||||
|
void gy521_free(struct gy521_module *m);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
@ -7,6 +8,7 @@
|
||||||
#include "gy521_driver.h"
|
#include "gy521_driver.h"
|
||||||
|
|
||||||
#define WRITE_BIT (1<<7)
|
#define WRITE_BIT (1<<7)
|
||||||
|
#define REG_SIZE 32
|
||||||
|
|
||||||
typedef struct reg_addr{
|
typedef struct reg_addr{
|
||||||
uint8_t dev_addr;
|
uint8_t dev_addr;
|
||||||
|
|
@ -14,40 +16,61 @@ typedef struct reg_addr{
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
}reg_addr;
|
}reg_addr;
|
||||||
|
|
||||||
reg_addr reg_addr_arr[16] = {{0x0, 0x0, 0x0}};
|
reg_addr reg_addr_arr[REG_SIZE] = {{0x0, 0x0, 0x0}};
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
|
|
||||||
|
void mock_twi_tx(uint8_t slave_addr, uint8_t *data, uint8_t size)
|
||||||
|
{
|
||||||
|
check_expected(slave_addr);
|
||||||
|
check_expected_ptr(data);
|
||||||
|
check_expected(size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Fake Object for TWI_TX*/
|
/* Fake Object for TWI_TX*/
|
||||||
void fake_twi_tx(uint8_t slave_addr, uint8_t *data, uint8_t size)
|
void fake_twi_tx(uint8_t slave_addr, uint8_t *data, uint8_t size)
|
||||||
{
|
{
|
||||||
/*Save the slave address passed*/
|
/*read the device address.*/
|
||||||
reg_addr_arr[0].dev_addr = slave_addr;
|
reg_addr_arr[idx].dev_addr = slave_addr;
|
||||||
|
|
||||||
|
/*Save the register it's trying to access.*/
|
||||||
|
reg_addr_arr[idx].addr = *data;
|
||||||
|
|
||||||
|
/*Save the data it's sending to that address.*/
|
||||||
|
reg_addr_arr[idx].value = *(data + 1);
|
||||||
|
|
||||||
/*Now write all the passed data*/
|
|
||||||
for(; idx < size; idx++) {
|
|
||||||
reg_addr_arr[idx].addr = *(data);
|
|
||||||
reg_addr_arr[idx].value = *(++data);
|
|
||||||
}
|
|
||||||
/*Post increment the global index*/
|
/*Post increment the global index*/
|
||||||
idx++;
|
idx++;
|
||||||
|
if(idx > REG_SIZE){
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Make use of recursion if there is still more data*/
|
||||||
|
if((size - 2) > 0) {
|
||||||
|
fake_twi_tx(slave_addr, data + 2, size - 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fake Object for TWI_RX*/
|
/* Fake Object for TWI_RX*/
|
||||||
void fake_twi_rx(uint8_t slave_addr, uint8_t *data, uint8_t size)
|
void fake_twi_rx(uint8_t slave_addr, uint8_t *data, uint8_t size)
|
||||||
{
|
{
|
||||||
/*Save the slave address passed*/
|
|
||||||
reg_addr_arr[0].dev_addr = slave_addr;
|
/*Read the device address*/
|
||||||
|
reg_addr_arr[idx].dev_addr = slave_addr;
|
||||||
|
|
||||||
|
/*Put down the register address it's trying to read.*/
|
||||||
|
reg_addr_arr[idx].addr = *data;
|
||||||
|
|
||||||
/*Read the registers requested*/
|
/*Fill it with the data from the register*/
|
||||||
for(uint8_t i = 0; i < size; i++) {
|
*data = reg_addr_arr[idx].value;
|
||||||
/*Wridxte the register read address*/
|
|
||||||
reg_addr_arr[i + idx].addr = *(data + i);
|
|
||||||
|
|
||||||
/*Read the response value into the pased data ptr*/
|
|
||||||
*(data + i) = reg_addr_arr[i + idx].value;
|
|
||||||
}
|
|
||||||
/*Post increment the global index*/
|
/*Post increment the global index*/
|
||||||
idx++;
|
idx++;
|
||||||
|
if(idx > REG_SIZE){
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -56,6 +79,59 @@ void fake_twi_rx(uint8_t slave_addr, uint8_t *data, uint8_t size)
|
||||||
void (*gy521_twi_tx)(uint8_t, uint8_t*, uint8_t) = &fake_twi_tx;
|
void (*gy521_twi_tx)(uint8_t, uint8_t*, uint8_t) = &fake_twi_tx;
|
||||||
void (*gy521_twi_rx)(uint8_t, uint8_t*, uint8_t) = &fake_twi_rx;
|
void (*gy521_twi_rx)(uint8_t, uint8_t*, uint8_t) = &fake_twi_rx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* Helper functions
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print_reg_arr(void)
|
||||||
|
{
|
||||||
|
printf("FAKE REGISTERS::\n");
|
||||||
|
for(uint8_t i = 0; i < REG_SIZE; i++){
|
||||||
|
print_error("%d:: val: %d, addr: %d, dev_addr: %d\n",
|
||||||
|
i,
|
||||||
|
reg_addr_arr[i].value,
|
||||||
|
reg_addr_arr[i].addr,
|
||||||
|
reg_addr_arr[i].dev_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_twi(void)
|
||||||
|
{
|
||||||
|
idx = 0;
|
||||||
|
for(int i = 0; i < REG_SIZE; i++){
|
||||||
|
reg_addr_arr[i].value = 0;
|
||||||
|
reg_addr_arr[i].addr = 0;
|
||||||
|
reg_addr_arr[i].dev_addr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int setup_gy521_instance(void **state)
|
||||||
|
{
|
||||||
|
clear_twi();
|
||||||
|
*state = gy521_new();
|
||||||
|
assert_non_null(*state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int teardown_gy521_instance(void **state)
|
||||||
|
{
|
||||||
|
gy521_free(*state);
|
||||||
|
clear_twi();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ############################
|
||||||
|
* TESTS
|
||||||
|
* ############################
|
||||||
|
*/
|
||||||
|
|
||||||
/* Tests the donothing function */
|
/* Tests the donothing function */
|
||||||
static void test_gy521_init(void **state) {
|
static void test_gy521_init(void **state) {
|
||||||
gy521_module *m = gy521_new();
|
gy521_module *m = gy521_new();
|
||||||
|
|
@ -136,7 +212,7 @@ static void test_gy521_update_gyro(void **sate)
|
||||||
gy521_init(m, TWI_GY521_ADDR1);
|
gy521_init(m, TWI_GY521_ADDR1);
|
||||||
|
|
||||||
/*Setup the fake gyro values.*/
|
/*Setup the fake gyro values.*/
|
||||||
for(uint8_t i = 0; i < 6; i++) {
|
for(uint8_t i = 1; i < 7; i++) {
|
||||||
reg_addr_arr[i].value = i * 8;
|
reg_addr_arr[i].value = i * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,14 +243,144 @@ static void test_gy521_update_gyro(void **sate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_gy521_self_test_gyro(void **sate)
|
||||||
|
{
|
||||||
|
/*Create instance of struct.*/
|
||||||
|
gy521_module *m = gy521_new();
|
||||||
|
reg_addr_arr[0].addr = TWI_GY521_ADDR1;
|
||||||
|
gy521_init(m, TWI_GY521_ADDR1);
|
||||||
|
|
||||||
|
/*Zero the global index for the twi*/
|
||||||
|
clear_twi();
|
||||||
|
|
||||||
|
/*Setup the full-scale range to +-250dps*/
|
||||||
|
|
||||||
|
/*Load up the gyro regs with passing test values*/
|
||||||
|
/*Load up the selftest regs with passing test values.*/
|
||||||
|
/*Load up the gyro regs for disabled ST reads*/
|
||||||
|
for(uint8_t i = 1; i < 17; i++) { /*(6regs * 2) + 3ST regs = 15*/
|
||||||
|
reg_addr_arr[i].value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
self_test_results result = gy521_self_test(m);
|
||||||
|
assert_false(result); /*The value should be zero, aka zero faults*/
|
||||||
|
|
||||||
|
/*Check to make sure it can fail.*/
|
||||||
|
clear_twi();
|
||||||
|
for(uint8_t i = 1; i < 5; i++){
|
||||||
|
reg_addr_arr[i].value = 2;
|
||||||
|
}
|
||||||
|
for(int i = 4; i < 9; i++){
|
||||||
|
reg_addr_arr[i].value = 255;
|
||||||
|
}
|
||||||
|
for(int i = 9; i < 17; i++){
|
||||||
|
reg_addr_arr[i].value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gy521_self_test(m);
|
||||||
|
|
||||||
|
|
||||||
|
/*Print out the register values*/
|
||||||
|
print_reg_arr();
|
||||||
|
|
||||||
|
assert_true(result);
|
||||||
|
|
||||||
|
/*Free the struct*/
|
||||||
|
gy521_free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_gy521_self_test_accel(void **sate)
|
||||||
|
{
|
||||||
|
/*Create instance of struct.*/
|
||||||
|
gy521_module *m = gy521_new();
|
||||||
|
reg_addr_arr[0].addr = TWI_GY521_ADDR1;
|
||||||
|
gy521_init(m, TWI_GY521_ADDR1);
|
||||||
|
|
||||||
|
/*Zero the global index for the twi*/
|
||||||
|
clear_twi();
|
||||||
|
|
||||||
|
/*Setup the full-scale range to +-250dps*/
|
||||||
|
|
||||||
|
/*Load up the gyro regs with passing test values*/
|
||||||
|
/*Load up the selftest regs with passing test values.*/
|
||||||
|
/*Load up the gyro regs for disabled ST reads*/
|
||||||
|
for(uint8_t i = 1; i < 17; i++) { /*(6regs * 2) + 3ST regs = 15*/
|
||||||
|
reg_addr_arr[i].value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
self_test_results result = gy521_self_test(m);
|
||||||
|
assert_false(result); /*The value should be zero, aka zero faults*/
|
||||||
|
|
||||||
|
/*Check to make sure it can fail.*/
|
||||||
|
clear_twi();
|
||||||
|
for(uint8_t i = 1; i < 5; i++){
|
||||||
|
reg_addr_arr[i].value = 2;
|
||||||
|
}
|
||||||
|
for(int i = 4; i < 9; i++){
|
||||||
|
reg_addr_arr[i].value = 255;
|
||||||
|
}
|
||||||
|
for(int i = 9; i < 17; i++){
|
||||||
|
reg_addr_arr[i].value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gy521_self_test(m);
|
||||||
|
|
||||||
|
|
||||||
|
/*Print out the register values*/
|
||||||
|
print_reg_arr();
|
||||||
|
|
||||||
|
assert_true(result);
|
||||||
|
|
||||||
|
/*Free the struct*/
|
||||||
|
gy521_free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*Mock Object/function for TWI RX*/
|
||||||
|
|
||||||
|
|
||||||
|
static void test_gy521_testing(void **state)
|
||||||
|
{
|
||||||
|
assert_false(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_gyro_update(void **state)
|
||||||
|
{
|
||||||
|
assert_true(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_enable_self_test_gyro(void **state)
|
||||||
|
{
|
||||||
|
//expect_value(func, param, val);
|
||||||
|
|
||||||
|
/*The read register function should be called with */
|
||||||
|
expect_value(read_register, reg, 27);
|
||||||
|
enable_self_test_gyro(*state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
/*For testing TWI/I2C related stuff*/
|
||||||
|
const struct CMUnitTest twi_group[] = {
|
||||||
|
cmocka_unit_test_setup_teardown(test_gy521_testing, setup_gy521_instance, teardown_gy521_instance),
|
||||||
|
cmocka_unit_test_setup_teardown(test_gyro_update, setup_gy521_instance, teardown_gy521_instance),
|
||||||
|
cmocka_unit_test_setup_teardown(test_enable_self_test_gyro, setup_gy521_instance, teardown_gy521_instance),
|
||||||
|
};
|
||||||
const struct CMUnitTest tests[] = {
|
const struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test(test_gy521_init),
|
cmocka_unit_test(test_gy521_init),
|
||||||
cmocka_unit_test(test_gy521_update_accel),
|
cmocka_unit_test(test_gy521_update_accel),
|
||||||
cmocka_unit_test(test_gy521_update_gyro),
|
cmocka_unit_test(test_gy521_update_gyro),
|
||||||
};
|
cmocka_unit_test(test_gy521_self_test_gyro),
|
||||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
cmocka_unit_test(test_gy521_self_test_accel),
|
||||||
|
};
|
||||||
|
//result = cmocka_run_group_tests(twi_group, setup_gy521_instance, teardown_gy521_instance);
|
||||||
|
result = cmocka_run_group_tests(twi_group, NULL, NULL);
|
||||||
|
result = cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue