kopia lustrzana https://github.com/ozarchie/EQMOD-ETX
335 wiersze
8.9 KiB
C++
335 wiersze
8.9 KiB
C++
/**@file*/
|
|
/*
|
|
* Copyright 2017, 2018 John Archbold
|
|
*/
|
|
|
|
/********************************************************
|
|
HBX Comms related functions
|
|
===========================
|
|
*********************************************************/
|
|
|
|
// HBX Attempt to reset
|
|
// --------------------
|
|
void HBXMotorReset(unsigned char Motor)
|
|
{
|
|
/*
|
|
int i;
|
|
|
|
// Write LOW
|
|
HDATalk();
|
|
digitalWrite(HDA1, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
|
else digitalWrite(HCL2, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
|
else digitalWrite(HCL2, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
}
|
|
|
|
// Write HIGH
|
|
digitalWrite(HDA1, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
|
else digitalWrite(HCL2, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
|
else digitalWrite(HCL2, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
}
|
|
|
|
// Read, and discard, a byte
|
|
HDAListen();
|
|
for (i = 0; i < 8; i++) {
|
|
if (Motor == MotorAz) digitalWrite(HCL1, LOW);
|
|
else digitalWrite(HCL2, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
if (Motor == MotorAz) digitalWrite(HCL1, HIGH);
|
|
else digitalWrite(HCL2, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
}
|
|
*/
|
|
|
|
// Force Clock Low, High for reset, time ~.75s
|
|
if (Motor == MotorAz) digitalWrite(HCLAz, LOW);
|
|
else digitalWrite(HCLAlt, LOW);
|
|
TimerDelaymS(MOTORDETECT);
|
|
if (Motor == MotorAz) digitalWrite(HCLAz, HIGH);
|
|
else digitalWrite(HCLAlt, HIGH);
|
|
TimerDelaymS(MOTORDETECT >> 1);
|
|
}
|
|
|
|
// HBX transmission functions
|
|
// ==========================
|
|
|
|
// HBX Send a command
|
|
// ------------------
|
|
bool HBXSendCommand(unsigned char Command, unsigned char Motor) {
|
|
|
|
if (Command != GetStatus){
|
|
dbgSerial.println(""); dbgSerial.print("+++ "); dbgSerial.print(Motor);
|
|
}
|
|
axis[Motor].Command = Command;
|
|
|
|
// Select the interface
|
|
if (Motor == MotorAz) {
|
|
HDA = HDAAz;
|
|
HCL = HCLAz;
|
|
}
|
|
else {
|
|
HDA = HDAAlt;
|
|
HCL = HCLAlt;
|
|
}
|
|
|
|
// Send the start sequence
|
|
// -----------------------
|
|
if (HBXStartSequence(Motor)) {
|
|
// Send the command byte
|
|
// ---------------------
|
|
HBXSendByte(Command, Motor);
|
|
return(true);
|
|
}
|
|
else {
|
|
HDAListen(); // Set data inbound
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
// HBX Initiate start sequence
|
|
// ---------------------------
|
|
bool HBXStartSequence(unsigned char Motor) {
|
|
// 1. HDA as input, Clock as output
|
|
HDAListen();
|
|
HCLTalk();
|
|
// 2. Set clock low
|
|
digitalWrite(HCL, LOW);
|
|
TimerDelayuS(HBXBitTime >> 1); // 1/2 bit-time
|
|
// 3. Wait for data low (HDA = 0) by MC, or timeout
|
|
H2XStart = micros();
|
|
do {
|
|
H2XTimer = micros() - H2XStart;
|
|
} while ((digitalRead(HDA) == 1) && (H2XTimer < (HBXBitTime << 3)));
|
|
TimerDelayuS((HBXBitTime >> 5)); // 1/32 bit-time delay, in case of data line glitch
|
|
// 4. Re-read data line, check if (data low) or (MC timeout)
|
|
if ((digitalRead(HDA) == 1) || (H2XTimer >= (HBXBitTime << 3))) {
|
|
digitalWrite(HCL, HIGH);
|
|
return(false); // error exit if no response from Motor
|
|
}
|
|
// 5. Set clock high if data low occurred (i.e. MC acknowledged clock low)
|
|
digitalWrite(HCL, HIGH);
|
|
TimerDelayuS(HBXBitTime >> 1);
|
|
// 6. Wait for data line release (HDA = 1) by MC, or timeout
|
|
H2XStart = micros();
|
|
do {
|
|
H2XTimer = micros() - H2XStart;
|
|
} while ((digitalRead(HDA) == 0) && (H2XTimer < (HBXBitTime << 3)));
|
|
TimerDelayuS(HBXBitTime); // Wait one bit-time, in case of success
|
|
// 7. Check timeout for data line released or no response from MC
|
|
if (H2XTimer >= (HBXBitTime << 3)) {
|
|
return(false); // Error Exit if no response from MC
|
|
}
|
|
return(true); // Success
|
|
}
|
|
|
|
// HBX Send a single byte
|
|
// ----------------------
|
|
void HBXSendByte(unsigned char databyte, unsigned char Motor) {
|
|
|
|
unsigned char mask;
|
|
if (axis[Motor].Command != GetStatus) {
|
|
dbgSerial.print("-> "); dbgSerial.print(databyte, HEX);
|
|
}
|
|
|
|
HDATalk(); // HDA as output
|
|
axis[Motor].HBXBitCount = 8; // 8bits to go
|
|
mask = 0x80; // MSB first
|
|
// Clock was set high before entry
|
|
TimerDelayuS(HBXBitTime);
|
|
do {
|
|
axis[Motor].HBXBitCount -= 1;
|
|
// Set data bit
|
|
if (databyte & mask) digitalWrite(HDA, HIGH);
|
|
else digitalWrite(HDA, LOW);
|
|
TimerDelayuS(HBXBitTime >> 1); // Let data stabilise
|
|
mask = mask >> 1; // Next data bit
|
|
// Set clock low
|
|
digitalWrite(HCL, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
// Set clock high
|
|
digitalWrite(HCL, HIGH);
|
|
TimerDelayuS(HBXBitTime-(HBXBitTime >> 1)); // Data is written DSTABLE before clock low
|
|
// for 8 bits
|
|
} while (axis[Motor].HBXBitCount);
|
|
TimerDelayuS(HBXBitTime >> 1); // Last high clock
|
|
HDAListen(); // Turn data pin inbound
|
|
TimerDelayuS(HBXBitTime);
|
|
}
|
|
|
|
// HBX Send two bytes in sequence
|
|
// ------------------------------
|
|
void HBXSend2Bytes(unsigned char Motor) {
|
|
HBXSendByte(axis[Motor].HBXP1, Motor);
|
|
HBXSendByte(axis[Motor].HBXP2, Motor);
|
|
}
|
|
|
|
// HBX Send three bytes in sequence
|
|
// --------------------------------
|
|
void HBXSend3Bytes(unsigned char Motor) {
|
|
HBXSendByte(axis[Motor].HBXP1, Motor);
|
|
HBXSendByte(axis[Motor].HBXP2, Motor);
|
|
HBXSendByte(axis[Motor].HBXP3, Motor);
|
|
}
|
|
|
|
// HBX Get a single byte
|
|
// ----------------------
|
|
unsigned char HBXGetByte(unsigned char Motor) {
|
|
|
|
// HDA as input
|
|
HDAListen();
|
|
axis[Motor].HBXBitCount = 8;
|
|
axis[Motor].HBXData = 0;
|
|
// Clock was set high before entry
|
|
while (axis[Motor].HBXBitCount) {
|
|
// Set clock low
|
|
digitalWrite(HCL, LOW);
|
|
TimerDelayuS(HBXBitTime >> 1);
|
|
// Read data bit
|
|
axis[Motor].HBXData = axis[Motor].HBXData << 1; // Shift previous bit
|
|
if (digitalRead(HDA)) axis[Motor].HBXData |= 0x01; // Read next bit
|
|
axis[Motor].HBXBitCount--; // Need eight bits
|
|
TimerDelayuS(HBXBitTime-(HBXBitTime >> 1)); // Wait for low time
|
|
// Set clock high
|
|
digitalWrite(HCL, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
}
|
|
TimerDelayuS(HBXBitTime);
|
|
if (axis[Motor].Command != GetStatus) {
|
|
dbgSerial.print("<- "); dbgSerial.print(axis[Motor].HBXData, HEX);
|
|
}
|
|
// Return data byte
|
|
axis[Motor].HBXCount = 1;
|
|
return (axis[Motor].HBXData);
|
|
}
|
|
|
|
// HBX Get the status bytes (25 bits)
|
|
// ----------------------------------
|
|
void HBXGet3Bytes(unsigned char Motor) {
|
|
|
|
axis[Motor].HBXP1 = HBXGetByte(Motor);
|
|
TimerDelayuS(HBXBitTime);
|
|
axis[Motor].HBXP2 = HBXGetByte(Motor);
|
|
TimerDelayuS(HBXBitTime);
|
|
axis[Motor].HBXP3 = HBXGetByte(Motor);
|
|
TimerDelayuS(HBXBitTime);
|
|
axis[Motor].HBXP4 = 0;
|
|
|
|
// Read 'byte4' = error bit
|
|
// ------------------------
|
|
digitalWrite(HCL, LOW);
|
|
TimerDelayuS(HBXBitTime >> 1);
|
|
axis[Motor].HBXP4 |= digitalRead(HDA); // Read the battery error bit
|
|
TimerDelayuS(HBXBitTime-(HBXBitTime >> 1));
|
|
digitalWrite(HCL, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
if (axis[Motor].Command != GetStatus) {
|
|
dbgSerial.print("- "); dbgSerial.print(axis[Motor].HBXP4, HEX);
|
|
}
|
|
axis[Motor].HBXCount = 4;
|
|
}
|
|
|
|
// H2X Low level Functions
|
|
// -----------------------
|
|
void HDAListen(void) {
|
|
// digitalWrite(HDA, HIGH);
|
|
pinMode(HDA, H2C_INPUT);
|
|
}
|
|
void HDAFloat(void) {
|
|
pinMode(HDA, H2C_INPUT);
|
|
}
|
|
void HDATalk(void) {
|
|
digitalWrite(HDA, HIGH);
|
|
pinMode(HDA, H2C_OUTPUT);
|
|
}
|
|
void HCLListen(void) {
|
|
// digitalWrite(HCL, HIGH);
|
|
pinMode(HCL, H2C_INPUTPU);
|
|
}
|
|
void HCLFloat(void) {
|
|
pinMode(HCL, H2C_INPUT);
|
|
}
|
|
void HCLTalk(void) {
|
|
digitalWrite(HCL, HIGH);
|
|
pinMode(HCL, H2C_OUTPUT);
|
|
}
|
|
void HDAAuxListen(void) {
|
|
pinMode(HDAAux, H2C_INPUT);
|
|
}
|
|
void HDAAuxFloat(void) {
|
|
pinMode(HDAAux, H2C_INPUT);
|
|
}
|
|
void HDAAuxTalk(void) {
|
|
digitalWrite(HDAAux, HIGH);
|
|
pinMode(HDAAux, H2C_OUTPUT);
|
|
}
|
|
void HCLAuxListen(void) {
|
|
pinMode(HCLAux, H2C_INPUTPU);
|
|
}
|
|
void HCLAuxTalk(void) {
|
|
digitalWrite(HCLAux, HIGH);
|
|
pinMode(HCLAux, H2C_OUTPUT);
|
|
}
|
|
|
|
void HBXReset() {
|
|
int ClockCount = 0;
|
|
// Do Az first
|
|
// ===========
|
|
HDA = HDAAz;
|
|
HCL = HCLAz;
|
|
// Set clock high
|
|
HCLTalk();
|
|
// Set data inbound
|
|
HDAListen();
|
|
TimerDelayuS(HBXBitTime);
|
|
// Data should be high
|
|
while ((!digitalRead(HDA)) && (ClockCount < 25)) {
|
|
digitalWrite(HCL, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
digitalWrite(HCL, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
ClockCount += 1;
|
|
}
|
|
// Then Alt
|
|
// ========
|
|
HDA = HDAAlt;
|
|
HCL = HCLAlt;
|
|
// Set clock high
|
|
HCLTalk();
|
|
// Set data inbound
|
|
HDAListen();
|
|
TimerDelayuS(HBXBitTime);
|
|
// Data should be high
|
|
while ((!digitalRead(HDA)) && (ClockCount < 25)) {
|
|
digitalWrite(HCL, LOW);
|
|
TimerDelayuS(HBXBitTime);
|
|
digitalWrite(HCL, HIGH);
|
|
TimerDelayuS(HBXBitTime);
|
|
ClockCount += 1;
|
|
}
|
|
// Finally AUX
|
|
// Set clock high
|
|
HCLAuxTalk();
|
|
// Set data inbound
|
|
HDAAuxListen();
|
|
}
|
|
|
|
long TwosComplement(long p) { // Calculate 2s complement
|
|
long q;
|
|
q = ~p; // Bitwise invert
|
|
q = q + 1; // +1
|
|
return q;
|
|
}
|