git-svn-id: svn+ssh://oldsvn/home/mlalondesvn/svn/cral@136 3ee9b42a-b53c-0410-a25e-f0b6218d5d5bmaster
parent
f31d49e1e4
commit
9fbddf67bf
@ -0,0 +1,127 @@
|
||||
extern "C" {
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "wiring_private.h"
|
||||
#include "wiring.h"
|
||||
#include "WConstants.h"
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
#include "pins_arduino.h"
|
||||
}
|
||||
|
||||
#include "avrmacros.h"
|
||||
#include "hdq.h"
|
||||
|
||||
#define _HDQ_readPin() (*inputReg & bitmask)>>pin /* Change me to inline!*/
|
||||
|
||||
HDQ::HDQ(uint8_t pinArg)
|
||||
{
|
||||
pin = pinArg;
|
||||
port = digitalPinToPort(pin);
|
||||
bitmask = digitalPinToBitMask(pin);
|
||||
outputReg = portOutputRegister(port);
|
||||
inputReg = portInputRegister(port);
|
||||
modeReg = portModeRegister(port);
|
||||
}
|
||||
|
||||
void HDQ::doBreak(void)
|
||||
{
|
||||
sbi(*modeReg, pin); // Set pin as output
|
||||
cbi(*outputReg, pin); // Bring pin low
|
||||
|
||||
// Wait the minimum break time
|
||||
delayMicroseconds(HDQ_DELAY_TB);
|
||||
|
||||
sbi(*outputReg, pin); // Bring the pin high again
|
||||
|
||||
// Wait the minimum break time
|
||||
delayMicroseconds(HDQ_DELAY_TBR);
|
||||
}
|
||||
|
||||
void HDQ::writeByte(uint8_t payload)
|
||||
{
|
||||
|
||||
for (uint8_t ii = 0; ii < 8; ii++)
|
||||
{
|
||||
sbi(*modeReg, pin); // Set pin as output
|
||||
cbi(*outputReg, pin); // Bring pin low
|
||||
// Wait the minimum break time
|
||||
delayMicroseconds(HDQ_DELAY_BIT_START);
|
||||
|
||||
// Toggle the pin for this bit, LSB first
|
||||
if (payload>>ii & 0x01) {
|
||||
sbi(*outputReg, pin);
|
||||
}
|
||||
else {
|
||||
cbi(*outputReg, pin);
|
||||
}
|
||||
|
||||
delayMicroseconds(HDQ_DELAY_BIT_WRITE);
|
||||
|
||||
sbi(*outputReg, pin);
|
||||
|
||||
delayMicroseconds(HDQ_DELAY_BIT_END);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
boolean HDQ::write(uint8_t reg, uint8_t payload, boolean verif)
|
||||
{
|
||||
HDQ::write(reg, payload);
|
||||
|
||||
if (payload == HDQ::read(reg)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean HDQ::write(uint8_t reg, uint8_t payload)
|
||||
{
|
||||
HDQ::doBreak();
|
||||
|
||||
HDQ::writeByte((reg |= HDQ_ADDR_MASK_WRITE));
|
||||
|
||||
delayMicroseconds((HDQ_DELAY_TRSPS_MAX - HDQ_DELAY_BIT_TOTAL) / 2);
|
||||
|
||||
HDQ::writeByte(payload);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t HDQ::read(uint8_t reg)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
uint8_t maxTries = HDQ_DELAY_FAIL_TRIES; // ~128uS at 8Mhz with 8 instructions per loop
|
||||
uint8_t ii;
|
||||
|
||||
HDQ::doBreak();
|
||||
|
||||
HDQ::writeByte((reg |= HDQ_ADDR_MASK_READ));
|
||||
|
||||
for (ii = 0; ii < 8; ii++)
|
||||
{
|
||||
// Wait for the slave to toggle a low
|
||||
maxTries = HDQ_DELAY_FAIL_TRIES;
|
||||
while (_HDQ_readPin() != 0 && maxTries-- > 0)
|
||||
if (maxTries == 1) return 0xFF;
|
||||
|
||||
delayMicroseconds(HDQ_DELAY_BIT_WRITE / 2 + HDQ_DELAY_BIT_START); // 100 / 2 + 30
|
||||
|
||||
result |= _HDQ_readPin()<<ii;
|
||||
|
||||
delayMicroseconds(HDQ_DELAY_TSSUB - (HDQ_DELAY_BIT_WRITE / 2 + HDQ_DELAY_BIT_START) + 10); // pass Tssub
|
||||
|
||||
// Wait for the slave to toggle a high again
|
||||
maxTries = HDQ_DELAY_FAIL_TRIES;
|
||||
while (_HDQ_readPin() != 1 && maxTries-- > 0)
|
||||
if (maxTries == 1) return 0xFF;
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
#ifndef _HDQ_H_
|
||||
#define _HDQ_H_
|
||||
|
||||
/**
|
||||
* Default pin to use if none is specified to the constructor
|
||||
**/
|
||||
#define HDQ_DEFAULT_PIN 7 /* Arduino pin 7 */
|
||||
|
||||
/**
|
||||
* Read/write command mask
|
||||
**/
|
||||
#define HDQ_ADDR_MASK_READ 0x00
|
||||
#define HDQ_ADDR_MASK_WRITE 0x80 /* B10000000 */
|
||||
|
||||
/**
|
||||
* HDQ bit timings
|
||||
**/
|
||||
#define HDQ_DELAY_BIT_START 30
|
||||
#define HDQ_DELAY_BIT_WRITE 100
|
||||
#define HDQ_DELAY_BIT_END 70
|
||||
#define HDQ_DELAY_BIT_TOTAL 200
|
||||
|
||||
/**
|
||||
* This is the number of times the slave wait loop
|
||||
* will run before we time out.
|
||||
* As far as I can tell the loop uses ~6 instructions
|
||||
* thus giving about 200uS delay which is a full bit write
|
||||
**/
|
||||
#define HDQ_DELAY_FAIL_TRIES 225
|
||||
|
||||
/**
|
||||
* HDQ Default timings
|
||||
**/
|
||||
#define HDQ_DELAY_TB 250 /* Min: 190uS */
|
||||
#define HDQ_DELAY_TBR 50 /* Min: 40uS */
|
||||
#define HDQ_DELAY_TSTRH 1 /* Min: 5nS */
|
||||
#define HDQ_DELAY_TDSU 50 /* Max: 50uS */
|
||||
#define HDQ_DELAY_TDH 100 /* Min: 100uS */
|
||||
#define HDQ_DELAY_TSSU 145 /* Max: 145uS */
|
||||
#define HDQ_DELAY_TCYCH 190 /* Min: 190uS */
|
||||
#define HDQ_DELAY_TSTRB 32 /* Min: 32uS */
|
||||
#define HDQ_DELAY_TDSUB 50 /* Max: 50uS */
|
||||
#define HDQ_DELAY_TDV 80 /* Min 80uS */
|
||||
#define HDQ_DELAY_TSSUB 145 /* Max: 145uS */
|
||||
#define HDQ_DELAY_TCYCB_MIN 190 /* Min: 190uS */
|
||||
#define HDQ_DELAY_TCYCB_MAX 250 /* Max: 250uS */
|
||||
#define HDQ_DELAY_TRSPS_MIN 190 /* Min: 190uS */
|
||||
#define HDQ_DELAY_TRSPS_MAX 320 /* Max: 320uS */
|
||||
#define HDQ_DELAY_TRSPS_DIFF 130 /* HDQ_DELAY_TRSPS_MAX - HDQ_DELAY_TRSPS_MIN */
|
||||
|
||||
class HDQ
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param pin: pin number to attach to
|
||||
**/
|
||||
HDQ(uint8_t pinArg = HDQ_DEFAULT_PIN);
|
||||
|
||||
/**
|
||||
* sendBreak: writes a break to the HDQ line
|
||||
**/
|
||||
void doBreak(void);
|
||||
|
||||
/**
|
||||
* write: send a payload to the device
|
||||
* @param reg: the address of the register to write to
|
||||
* @param payload: data to be sent
|
||||
* @return: false, unless if verif is set, then
|
||||
* it will read back the register and
|
||||
* return true if it matches the payload
|
||||
**/
|
||||
boolean write(uint8_t reg, uint8_t payload, boolean verif);
|
||||
boolean write(uint8_t reg, uint8_t payload);
|
||||
|
||||
/**
|
||||
* read: read from the device
|
||||
* @param register: address of the register to read
|
||||
* @return a uint8_t integer
|
||||
**/
|
||||
uint8_t read(uint8_t reg);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Port variables definition
|
||||
**/
|
||||
uint8_t pin;
|
||||
uint8_t port;
|
||||
uint8_t bitmask;
|
||||
volatile uint8_t *outputReg;
|
||||
volatile uint8_t *inputReg;
|
||||
volatile uint8_t *modeReg;
|
||||
|
||||
/**
|
||||
* writeByte: write a raw byte of data to the bus
|
||||
* @param payload: the byte to send
|
||||
*
|
||||
**/
|
||||
void writeByte(uint8_t payload);
|
||||
};
|
||||
#endif
|
Loading…
Reference in new issue