@ -1,16 +1,5 @@
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"
}
@ -19,6 +8,10 @@ extern "C" {
# define _HDQ_readPin() (*inputReg & bitmask)>>pin /* Change me to inline!*/
/**
* Constructor
* @ param pin : pin number to attach to
* */
HDQ : : HDQ ( uint8_t pinArg )
{
pin = pinArg ;
@ -29,98 +22,138 @@ HDQ::HDQ(uint8_t pinArg)
modeReg = portModeRegister ( port ) ;
}
/**
* sendBreak : writes a break to the HDQ line
* */
void HDQ : : doBreak ( void )
{
sbi ( * modeReg , pin ) ; // Set pin as output
cbi ( * outputReg , pin ) ; // Bring pin low
// Wait the minimum break time
// Singal a break on the line
cbi ( * outputReg , pin ) ; // Bring pin low
delayMicroseconds ( HDQ_DELAY_TB ) ;
sbi ( * outputReg , pin ) ; // Bring the pin high again
// Wait the minimum break time
// Make sure we leave enough time for the slave to recover
cbi ( * modeReg , pin ) ; // Release pin
delayMicroseconds ( HDQ_DELAY_TBR ) ;
}
/**
* writeByte : write a raw byte of data to the bus
* @ param payload : the byte to send
*
* */
void HDQ : : writeByte ( uint8_t payload )
{
sbi ( * modeReg , pin ) ; // Set pin as output
for ( uint8_t ii = 0 ; ii < 8 ; ii + + )
{
sbi ( * modeReg , pin ) ; // Set pin as outpu t
// Start bi t
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 ) ;
sbi ( * outputReg , pin ) ; // High
}
else {
cbi ( * outputReg , pin ) ;
cbi ( * outputReg , pin ) ; // Low
}
// Bit time
delayMicroseconds ( HDQ_DELAY_BIT_WRITE ) ;
sbi ( * outputReg , pin ) ;
// Stop bit
sbi ( * outputReg , pin ) ; // Bring the pin high
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 ;
}
/**
* 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 HDQ : : write ( uint8_t reg , uint8_t payload )
{
// Singal a break
HDQ : : doBreak ( ) ;
// Write the register to write
HDQ : : writeByte ( ( reg | = HDQ_ADDR_MASK_WRITE ) ) ;
// Wait for the slave to finish reading the register
delayMicroseconds ( ( HDQ_DELAY_TRSPS_MAX - HDQ_DELAY_BIT_TOTAL ) / 2 ) ;
// Write the payload
HDQ : : writeByte ( payload ) ;
// Wait for the slave to finish writing the payload
delayMicroseconds ( ( HDQ_DELAY_TRSPS_MAX - HDQ_DELAY_BIT_TOTAL ) / 2 ) ;
cbi ( * modeReg , pin ) ; // Release pin
return true ;
}
/**
* Write with verification
* */
boolean HDQ : : write ( uint8_t reg , uint8_t payload , boolean verif )
{
// Write the payload
HDQ : : write ( reg , payload ) ;
// Verify the write
if ( payload = = HDQ : : read ( reg ) ) return true ;
return false ;
}
/**
* read : read from the device
* @ param register : address of the register to read
* @ return a uint8_t integer
* */
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 ;
// Singal a break
HDQ : : doBreak ( ) ;
// Write the register to read
HDQ : : writeByte ( ( reg | = HDQ_ADDR_MASK_READ ) ) ;
for ( ii = 0 ; ii < 8 ; ii + + )
{
// Wait for the slave to toggle a low
// Wait for the slave to toggle a low , or fail
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
// Wait until Tdsub and half or one bit has passed
delayMicroseconds ( HDQ_DELAY_BIT_WRITE / 2 + HDQ_DELAY_BIT_START ) ;
// Read the bit
result | = _HDQ_readPin ( ) < < ii ;
delayMicroseconds ( HDQ_DELAY_TSSUB - ( HDQ_DELAY_BIT_WRITE / 2 + HDQ_DELAY_BIT_START ) + 10 ) ; // pass Tssub
// Wait until Tssub has passed
delayMicroseconds ( HDQ_DELAY_TSSUB - ( HDQ_DELAY_BIT_WRITE / 2 + HDQ_DELAY_BIT_START ) + 10 ) ;
// Wait for the slave to toggle a high again
// Wait for the slave to toggle a high , or fail
maxTries = HDQ_DELAY_FAIL_TRIES ;
while ( _HDQ_readPin ( ) ! = 1 & & maxTries - - > 0 )
if ( maxTries = = 1 ) return 0xFF ;
}
return result ;