k3ng_rotator_controller/hh12.cpp
2014-07-02 17:49:28 -04:00

136 lines
4.1 KiB
C++
Executable File

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "hh12.h"
/*
Code adapted from here: http://www.madscientisthut.com/forum_php/viewtopic.php?f=11&t=7
*/
int hh12_clock_pin = 0;
int hh12_cs_pin = 0;
int hh12_data_pin = 0;
int inputstream = 0; //one bit read from pin
long packeddata = 0; //two bytes concatenated from inputstream
long angle = 0; //holds processed angle value
float floatangle = 0;
long anglemask = 65472; //0x1111111111000000: mask to obtain first 10 digits with position info
long statusmask = 63; //0x000000000111111; mask to obtain last 6 digits containing status info
long statusbits; //holds status/error information
int DECn; //bit holding decreasing magnet field error data
int INCn; //bit holding increasing magnet field error data
int OCF; //bit holding startup-valid bit
int COF; //bit holding cordic DSP processing error data
int LIN; //bit holding magnet field displacement error data
//-----------------------------------------------------------------------------------------------------
hh12::hh12(){
}
//-----------------------------------------------------------------------------------------------------
void hh12::initialize(int _hh12_clock_pin, int _hh12_cs_pin, int _hh12_data_pin){
hh12_clock_pin = _hh12_clock_pin;
hh12_cs_pin = _hh12_cs_pin;
hh12_data_pin = _hh12_data_pin;
pinMode(hh12_clock_pin, OUTPUT);
pinMode(hh12_cs_pin, OUTPUT);
pinMode(hh12_data_pin, INPUT);
}
//-----------------------------------------------------------------------------------------------------
float hh12::heading(){
digitalWrite(hh12_cs_pin, HIGH); // CSn high
digitalWrite(hh12_clock_pin, HIGH); // CLK high
digitalWrite(hh12_cs_pin, LOW); // CSn low: start of transfer
delayMicroseconds(HH12_DELAY); // delay for chip initialization
digitalWrite(hh12_clock_pin, LOW); // CLK goes low: start clocking
delayMicroseconds(HH12_DELAY); // hold low
for (int x=0; x <16; x++) // clock signal, 16 transitions, output to clock pin
{
digitalWrite(hh12_clock_pin, HIGH); //clock goes high
delayMicroseconds(HH12_DELAY); //
inputstream =digitalRead(hh12_data_pin); // read one bit of data from pin
#ifdef DEBUG_HH12
Serial.print(inputstream, DEC);
#endif
packeddata = ((packeddata << 1) + inputstream);// left-shift summing variable, add pin value
digitalWrite(hh12_clock_pin, LOW);
delayMicroseconds(HH12_DELAY); // end of one clock cycle
}
// end of entire clock cycle
#ifdef DEBUG_HH12
Serial.print("hh12: packed:");
Serial.println(packeddata,DEC);
Serial.print("hh12: pack bin: ");
Serial.println(packeddata,BIN);
#endif
angle = packeddata & anglemask; // mask rightmost 6 digits of packeddata to zero, into angle
#ifdef DEBUG_HH12
Serial.print("hh12: mask: ");
Serial.println(anglemask, BIN);
Serial.print("hh12: bin angle:");
Serial.println(angle, BIN);
Serial.print("hh12: angle: ");
Serial.println(angle, DEC);
#endif
angle = (angle >> 6); // shift 16-digit angle right 6 digits to form 10-digit value
#ifdef DEBUG_HH12
Serial.print("hh12: angleshft:");
Serial.println(angle, BIN);
Serial.print("hh12: angledec: ");
Serial.println(angle, DEC);
#endif
floatangle = angle * 0.3515; // angle * (360/1024) == actual degrees
#ifdef DEBUG_HH12
statusbits = packeddata & statusmask;
DECn = statusbits & 2; // goes high if magnet moved away from IC
INCn = statusbits & 4; // goes high if magnet moved towards IC
LIN = statusbits & 8; // goes high for linearity alarm
COF = statusbits & 16; // goes high for cordic overflow: data invalid
OCF = statusbits & 32; // this is 1 when the chip startup is finished
if (DECn && INCn) {
Serial.println("hh12: magnet moved out of range");
} else {
if (DECn) {
Serial.println("hh12: magnet moved away from chip");
}
if (INCn) {
Serial.println("hh12: magnet moved towards chip");
}
}
if (LIN) {
Serial.println("hh12: linearity alarm: magnet misaligned? data questionable");
}
if (COF) {
Serial.println("hh12: cordic overflow: magnet misaligned? data invalid");
}
#endif //DEBUG_HH12
return(floatangle);
}