Commit a43306c5 authored by Bruno Laurencich's avatar Bruno Laurencich

new EEPROM mapping table

parent 70d32be5
<!-- Chordata.xml -->
<Chordata version="0.1.0">
<Configuration>
<KC_revision> 2 </KC_revision>
<KC_revision> 1 </KC_revision>
<Communication>
<Adapter>
/dev/i2c-1
......@@ -46,7 +46,7 @@
<Branch Name="left" id="1">
CH_1
<K_Ceptor Name="Unico" id="2">
0x0f
6
</K_Ceptor>
</Branch>
</Mux>
......
This diff is collapsed.
......@@ -61,7 +61,21 @@
/////////////////////////////////
///The version of the program
/////////////////////////////////
#define _CHORDATA_VERSION "0.1.0"
#define _CHORDATA_VERSION_MAJOR 0
#define _CHORDATA_VERSION_MINOR 1
#define _CHORDATA_VERSION_PATCH 0
#define _CHORDATA_VERSION (( _CHORDATA_VERSION_MAJOR * 10000 ) +\
( _CHORDATA_VERSION_MINOR * 100 ) +\
( _CHORDATA_VERSION_PATCH ) )
#define _CHORDATA_VERSION_STR fmt::format("{}.{}.{}",\
_CHORDATA_VERSION_MAJOR,\
_CHORDATA_VERSION_MINOR,\
_CHORDATA_VERSION_PATCH)
//this is the string "chordata", used for checking presense of data in EEPROM
#define _CHORDATA_CRC32 0xCBF43926
//////////////////////////////////
/// The name of the client (where the render is performed and the animation recorded)
......@@ -230,14 +244,15 @@
#define _CHORDATA_MUX_MAX 6
//////////////////////////////////
/// The starting chunk of the gyro calib data stored on the EEPROM
/// The starting addrs of the chunks of calib data stored on the EEPROM
//////////////////////////////////
#define _CHORDATA_EEPROM_GYRO_OFFSET 8
#define _CHORDATA_EEPROM_VAL_CHKSUM 0
#define _CHORDATA_EEPROM_VERSION 8
#define _CHORDATA_EEPROM_TIMESTAMP 12
#define _CHORDATA_EEPROM_GYRO_SPACE 16
#define _CHORDATA_EEPROM_ACEL_SPACE 24
#define _CHORDATA_EEPROM_MAG_SPACE 32
//////////////////////////////////
/// The starting chunk of the acel calib data stored on the EEPROM
//////////////////////////////////
#define _CHORDATA_EEPROM_ACEL_OFFSET 16
///@}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
......@@ -375,7 +390,7 @@ namespace Chordata {
struct Conf_info{
std::string description;
std::string notes;
std::string version;
uint32_t version;
} info;
struct Conf_XML{
......
......@@ -152,29 +152,28 @@ void KC::bang(){
uint8_t eeprom_addr = (Chordata::getConf().kc_ver == 1)? R1_EEPROM_ADDR : R2_EEPROM_ADDR;
eeprom_addr = this->getAddress() ^ eeprom_addr;
auto eeprom = read_calib(i2c, eeprom_addr);
static const std::array<int16_t,3> niente = {0,0,0};
static const std::array<int16_t,3> tutti = {0,0,0};
auto validation = read_info(i2c, eeprom_addr, _CHORDATA_EEPROM_VAL_CHKSUM);
if (eeprom == niente || eeprom == tutti){
if (validation != _CHORDATA_CRC32){
comm::try_debug("K_Ceptor {}: No EEPROM calib data found.", getLabel());
return;
}
magOffset[0] = eeprom[0];
auto eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_MAG_SPACE);
magOffset[0] = eeprom[0];//TODO; use std::copy here
magOffset[1] = eeprom[1];
magOffset[2] = eeprom[2];
comm::try_debug("K_Ceptor {}: EEPROM calib data found :\n\t{}\n\t{}\n\t{}",
comm::try_debug("K_Ceptor {}: EEPROM calib data found. Mag correction vector =\n\t{}\t{}\t{}",
getLabel(),
eeprom[0],eeprom[1],eeprom[2]);
//get gyro offsets
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_GYRO_OFFSET);
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_GYRO_SPACE);
std::copy(std::begin(eeprom), std::end(eeprom), std::begin(imu->gBiasRaw));
//get acel offsets
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_ACEL_OFFSET);
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_ACEL_SPACE);
std::copy(std::begin(eeprom), std::end(eeprom), std::begin(imu->aBiasRaw));
......@@ -182,7 +181,7 @@ void KC::bang(){
comm::try_warn("EEPROM not found on {}", getLabel());
} //end try to read EEPROM
return; //setup and EEPROM read done. h
return; //setup and EEPROM read done
} else {
comm::try_err("K_Ceptor {}: setup ERROR!.", getLabel());
......
......@@ -54,7 +54,9 @@
#include "MadgwickAHRS.h"
#include "EEPROM.h" //This can't be included anywhere else :P << why?
#include "EEPROM.h" //This can't be included anywhere else :P
// belongs to some parts of this programs that were developed on the rush.
// It shoudl be completely refactored one day
#include <cstdint>
......
......@@ -128,6 +128,7 @@ Configuration_Data Chordata::parse_cmd_line(int argc, const char **argv){
args::Flag wait(parser, "no_wait", msgs::wait, {'y', "yes"});
args::Flag raw(parser, "raw_lectures", msgs::wait, {'r', "raw"});
args::ValueFlag<int> kc_ver(parser, "K_Ceptor revision", msgs::kc_ver, {'k', "kceptor"});
args::Group xml(parser, msgs::xml_g, args::Group::Validators::DontCare);
......@@ -174,7 +175,7 @@ Configuration_Data Chordata::parse_cmd_line(int argc, const char **argv){
using args::get;
if (version){
args::Error e("");
throw CMDLine_Parse_Error(format(msgs::version_dump, _CHORDATA_VERSION), e);
throw CMDLine_Parse_Error(format(msgs::version_dump, _CHORDATA_VERSION_STR), e);
}
conf.wait = (wait)? false : true;
......
......@@ -165,6 +165,10 @@ namespace Chordata{
time_point getStart() const {return start;};
inline const std::time_t initialTimestamp() const{
return std::chrono::system_clock::to_time_t(start);
}
inline const char *initialTime() const{
const std::time_t time = std::chrono::system_clock::to_time_t(start);
return std::ctime(&time);
......
......@@ -3,6 +3,9 @@
* Declarations of functions to perform read/write operations on an EEPROM memory.
* Definitions in Notochord.cpp
*
* // This file belongs to some parts of this programs that were developed on the rush.
* // It should be completely refactored one day
*
* @author Bruno Laurencich
* @version 0.1.0
* @date 2018/08/20
......@@ -54,7 +57,15 @@
#define R1_EEPROM_ADDR 0x50
#define R2_EEPROM_ADDR 0x51
//TODO: set date on write!
bool write_calib(I2C_io* io, uint16_t xor_val, std::array<int16_t, 3> vals, const int offset = 0);
std::array<int16_t, 3> read_calib(I2C_io* io, uint16_t xor_val, const int offset = 0);
void write_calib(I2C_io* io, uint16_t address, std::array<int16_t, 3> vals, const int offset = 0);
std::array<int16_t, 3> read_calib(I2C_io* io, uint16_t address, const int offset = 0);
void write_info(I2C_io* io, uint16_t address, uint32_t val, const int offset = 0);
uint32_t read_info(I2C_io* io, uint16_t address, const int offset = 0);
......@@ -88,7 +88,7 @@ config_fn Chordata::getConf = []()-> const Chordata::Configuration_Data& {
//////////////////////////////////
#define EEPROM_RW_SLEEP 1
bool write_calib(I2C_io* io, uint16_t address, std::array<int16_t, 3> vals, int offset){
void write_calib(I2C_io* io, uint16_t address, std::array<int16_t, 3> vals, int offset){
// cout << "WRITING EEPROM OFFSET: " << offset << endl;
for (int i = 0; i < 6; i+=2)
{
......@@ -104,8 +104,6 @@ bool write_calib(I2C_io* io, uint16_t address, std::array<int16_t, 3> vals, int
// printf("SLOT %d [ MSB:%2x LSB:%2x - VAL: %4x / %d]\n", i , msb, lsb, val, val);
}
return true;
}
std::array<int16_t, 3> read_calib(I2C_io* io, uint16_t address, int offset){
......@@ -126,6 +124,40 @@ std::array<int16_t, 3> read_calib(I2C_io* io, uint16_t address, int offset){
return results;
}
void write_info(I2C_io* io, uint16_t address, uint32_t val, const int offset){
static const std::size_t N = 4;
uint8_t chunks[N] = {
(val & 0xff000000UL) >> 24,
(val & 0x00ff0000UL) >> 16,
(val & 0x0000ff00UL) >> 8,
(val & 0x000000ffUL)
};
for (std::size_t i = 0; i < N; ++i){
io->writeByte( address, offset+i , chunks[i] );
thread_sleep(Chordata::millis(EEPROM_RW_SLEEP));
}
}
uint32_t read_info(I2C_io* io, uint16_t address, const int offset){
static const std::size_t N = 4;
uint8_t chunks[N];
for (std::size_t i = 0; i < N; ++i){
chunks[i] = io->readByte( address, offset+i );
thread_sleep(Chordata::millis(EEPROM_RW_SLEEP));
}
uint32_t result = 0x00000000UL;
result |= ( chunks[0] << 24 ) & 0xff000000UL;
result |= ( chunks[1] << 16 ) & 0x00ff0000UL;
result |= ( chunks[2] << 8 ) & 0x0000ff00UL;
result |= chunks[3] & 0x000000ffUL;
return result;
}
//////////////////////////////////
......@@ -265,9 +297,9 @@ bool Notochord::run(){
std::thread t;
if (config.raw){ //if the raw flag is set, wait for an user imput to stop the timer
std::cout << "**Calibration mode**\n Enter the xor value of the node\n" << std::endl;
std::cout << "**Calibration mode**\n Enter the xor value of the node\n"_CHORDATA_DEF_PROMPT << std::endl;
std::cin >> user_xor_val;
std::cout << "Enter the label of the node" << std::endl;
std::cout << "Enter the label of the node\n"_CHORDATA_DEF_PROMPT << std::endl;
std::cin >> user_label;
std::cout << "Initilizing callibration procedure,\n1. Put the KCEPTOR facing up in a flat surface." << std::endl;
......@@ -290,10 +322,10 @@ bool Notochord::run(){
bool started = main_timer.startTimer(comm::timekeeper.getStart(), sleepMicros);
std::array<int16_t, 3> result;
std::array<int16_t, 3> mag_offsets;
try{ //If the timer was started, run the octave interpreter
result = runOctave(mag_lectures);
mag_offsets = runOctave(mag_lectures);
// comm::info("Results from the calibration: \nMAG OFFSETS:\t{}\t{}\t{}"
// "\nACEL OFFSETS:\t{}\t{}\t{}\nGYRO OFFSETS:\t{}\t{}\t{}",
......@@ -302,7 +334,7 @@ bool Notochord::run(){
// acel_offsets[0],acel_offsets[1],acel_offsets[2]);
comm::info("Results from the calibration for [{}]({}):\n{}\n{}\n{}",
user_label, user_xor_val,
OFFSET_TAG("mag", result),
OFFSET_TAG("mag", mag_offsets),
OFFSET_TAG("acel", acel_offsets),
OFFSET_TAG("gyro", gyro_offsets));
......@@ -312,22 +344,27 @@ bool Notochord::run(){
uint8_t eeprom_addr = (Chordata::getConf().kc_ver == 1)? R1_EEPROM_ADDR : R2_EEPROM_ADDR;
eeprom_addr = eeprom_addr ^ Chordata::K_Ceptor_addr;
write_calib(i2c, eeprom_addr, result, 0);
write_calib(i2c, eeprom_addr, gyro_offsets, _CHORDATA_EEPROM_GYRO_OFFSET);
write_calib(i2c, eeprom_addr, acel_offsets, _CHORDATA_EEPROM_ACEL_OFFSET);
write_info(i2c, eeprom_addr, _CHORDATA_VERSION, _CHORDATA_EEPROM_VERSION);
write_info(i2c, eeprom_addr, comm::timekeeper.initialTimestamp(), _CHORDATA_EEPROM_TIMESTAMP);
write_calib(i2c, eeprom_addr, mag_offsets, _CHORDATA_EEPROM_MAG_SPACE);
write_calib(i2c, eeprom_addr, gyro_offsets, _CHORDATA_EEPROM_GYRO_SPACE);
write_calib(i2c, eeprom_addr, acel_offsets, _CHORDATA_EEPROM_ACEL_SPACE);
write_info(i2c, eeprom_addr, _CHORDATA_CRC32, _CHORDATA_EEPROM_VAL_CHKSUM);
auto eeprom = read_calib(i2c, eeprom_addr);
auto eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_MAG_SPACE);
if (eeprom != result)
if (eeprom != mag_offsets)
comm::err("The readed values (MAG) from the eeprom are different than those written:\n\t{}\n\t{}\n\t{}",
eeprom[0],eeprom[1],eeprom[2]);
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_GYRO_OFFSET);
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_GYRO_SPACE);
if (eeprom != gyro_offsets)
comm::err("The readed values (GYRO) from the eeprom are different than those written:\n\t{}\n\t{}\n\t{}",
eeprom[0],eeprom[1],eeprom[2]);
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_ACEL_OFFSET);
eeprom = read_calib(i2c, eeprom_addr, _CHORDATA_EEPROM_ACEL_SPACE);
if (eeprom != acel_offsets)
comm::err("The readed values (ACEL) from the eeprom are different than those written:\n\t{}\n\t{}\n\t{}",
eeprom[0],eeprom[1],eeprom[2]);
......@@ -342,7 +379,7 @@ bool Notochord::run(){
myfile.open (filename, std::ios_base::app);
myfile << "<!-- Value written on " << comm::timekeeper.now() << " -->\n";
myfile << "<K_Ceptor Name=" << user_label <<" id=\"0\">\n\t" << user_xor_val << "\n";
myfile << OFFSET_TAG("mag", result) << '\n';
myfile << OFFSET_TAG("mag", mag_offsets) << '\n';
myfile << OFFSET_TAG("acel", acel_offsets) << '\n';
myfile << OFFSET_TAG("gyro", gyro_offsets) << '\n';
myfile << "</K_Ceptor>";
......
......@@ -208,7 +208,7 @@ SCENARIO("The Command_Line_Parser parses the arguments "
THEN("It should fill the configuration struct with the default, and the user data "){
CHECK_THAT(config.info.description, Equals(_NOTOCHORD_DESCRIPTION));
CHECK_THAT(config.info.notes, Equals(_NOTOCHORD_NOTES));
CHECK(config.info.version == _CHORDATA_VERSION );
CHECK(config.info.version == _CHORDATA_VERSION_STR );
CHECK_THAT(config.xml.filename, Contains(config.exe_path) && Contains(_CHORDATA_CONF));
CHECK_THAT(config.xml.schema, Contains(config.exe_path) && Contains(_CHORDATA_CONF_SCHEMA));
......@@ -229,7 +229,7 @@ SCENARIO("The Command_Line_Parser parses the arguments "
THEN("It should fill the configuration struct with the default data"){
REQUIRE_THAT(config.info.description, Equals(_NOTOCHORD_DESCRIPTION));
REQUIRE_THAT(config.info.notes, Equals(_NOTOCHORD_NOTES));
REQUIRE(config.info.version == _CHORDATA_VERSION );
REQUIRE(config.info.version == _CHORDATA_VERSION_STR );
REQUIRE_THAT(config.comm.ip, Equals(_CHORDATA_TRANSMIT_ADDR));
REQUIRE(config.comm.port == _CHORDATA_TRANSMIT_PORT );
......
Markdown is supported
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