SparkFun Line Follower Array Library. based on https://github.com/sparkfun/SparkFun_Line_Follower_Array_Arduino_Library
Dependents: WRS_mechanamu_test
SensorBar.cpp@0:c1d649c7b904, 2018-08-31 (annotated)
- Committer:
- sgrsn
- Date:
- Fri Aug 31 02:52:24 2018 +0000
- Revision:
- 0:c1d649c7b904
First commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sgrsn | 0:c1d649c7b904 | 1 | #include "SensorBar.h" |
sgrsn | 0:c1d649c7b904 | 2 | #include "stdint.h" |
sgrsn | 0:c1d649c7b904 | 3 | #include "sx1509_registers.h" |
sgrsn | 0:c1d649c7b904 | 4 | |
sgrsn | 0:c1d649c7b904 | 5 | /*example*************************************************** |
sgrsn | 0:c1d649c7b904 | 6 | |
sgrsn | 0:c1d649c7b904 | 7 | #include "mbed.h" |
sgrsn | 0:c1d649c7b904 | 8 | #include "SensorBar.h" |
sgrsn | 0:c1d649c7b904 | 9 | |
sgrsn | 0:c1d649c7b904 | 10 | const uint8_t SX1509_ADDRESS = 0x3E<<1; // SX1509 I2C address (00) |
sgrsn | 0:c1d649c7b904 | 11 | |
sgrsn | 0:c1d649c7b904 | 12 | int main() |
sgrsn | 0:c1d649c7b904 | 13 | { |
sgrsn | 0:c1d649c7b904 | 14 | I2C i2c(p28, p27); |
sgrsn | 0:c1d649c7b904 | 15 | SensorBar mySensorBar(&i2c, SX1509_ADDRESS); |
sgrsn | 0:c1d649c7b904 | 16 | mySensorBar.setBarStrobe(); |
sgrsn | 0:c1d649c7b904 | 17 | mySensorBar.clearInvertBits(); |
sgrsn | 0:c1d649c7b904 | 18 | uint8_t returnStatus = mySensorBar.begin(); |
sgrsn | 0:c1d649c7b904 | 19 | printf("next, %d\r\n", returnStatus); |
sgrsn | 0:c1d649c7b904 | 20 | if(returnStatus) |
sgrsn | 0:c1d649c7b904 | 21 | { |
sgrsn | 0:c1d649c7b904 | 22 | printf("sx1509 IC communication OK"); |
sgrsn | 0:c1d649c7b904 | 23 | } |
sgrsn | 0:c1d649c7b904 | 24 | else |
sgrsn | 0:c1d649c7b904 | 25 | { |
sgrsn | 0:c1d649c7b904 | 26 | printf("i2c failed"); |
sgrsn | 0:c1d649c7b904 | 27 | wait_ms(10); |
sgrsn | 0:c1d649c7b904 | 28 | while(1); |
sgrsn | 0:c1d649c7b904 | 29 | } |
sgrsn | 0:c1d649c7b904 | 30 | |
sgrsn | 0:c1d649c7b904 | 31 | while(1) |
sgrsn | 0:c1d649c7b904 | 32 | { |
sgrsn | 0:c1d649c7b904 | 33 | uint8_t rawValue = mySensorBar.getRaw(); |
sgrsn | 0:c1d649c7b904 | 34 | |
sgrsn | 0:c1d649c7b904 | 35 | for( int i = 7; i >= 0; i-- ) |
sgrsn | 0:c1d649c7b904 | 36 | { |
sgrsn | 0:c1d649c7b904 | 37 | printf("%d", (rawValue >> i) & 0x01); |
sgrsn | 0:c1d649c7b904 | 38 | } |
sgrsn | 0:c1d649c7b904 | 39 | printf("b, "); |
sgrsn | 0:c1d649c7b904 | 40 | printf("%d\r\n", mySensorBar.getPosition()); |
sgrsn | 0:c1d649c7b904 | 41 | wait_ms(10); |
sgrsn | 0:c1d649c7b904 | 42 | } |
sgrsn | 0:c1d649c7b904 | 43 | } |
sgrsn | 0:c1d649c7b904 | 44 | |
sgrsn | 0:c1d649c7b904 | 45 | ***********************************************************/ |
sgrsn | 0:c1d649c7b904 | 46 | |
sgrsn | 0:c1d649c7b904 | 47 | |
sgrsn | 0:c1d649c7b904 | 48 | SensorBar::SensorBar(I2C *i2c, uint8_t address, uint8_t resetPin, uint8_t interruptPin, uint8_t oscillatorPin) |
sgrsn | 0:c1d649c7b904 | 49 | { |
sgrsn | 0:c1d649c7b904 | 50 | // Store the received parameters into member variables |
sgrsn | 0:c1d649c7b904 | 51 | _i2c = i2c; |
sgrsn | 0:c1d649c7b904 | 52 | deviceAddress = address; |
sgrsn | 0:c1d649c7b904 | 53 | pinInterrupt = interruptPin; |
sgrsn | 0:c1d649c7b904 | 54 | pinOscillator = oscillatorPin; |
sgrsn | 0:c1d649c7b904 | 55 | pinReset = resetPin; |
sgrsn | 0:c1d649c7b904 | 56 | invertBits = 0; |
sgrsn | 0:c1d649c7b904 | 57 | barStrobe = 0; //Default always on |
sgrsn | 0:c1d649c7b904 | 58 | } |
sgrsn | 0:c1d649c7b904 | 59 | |
sgrsn | 0:c1d649c7b904 | 60 | void SensorBar::debounceConfig(uint8_t configValue) |
sgrsn | 0:c1d649c7b904 | 61 | { |
sgrsn | 0:c1d649c7b904 | 62 | // First make sure clock is configured |
sgrsn | 0:c1d649c7b904 | 63 | uint8_t tempuint8_t = readByte(REG_MISC); |
sgrsn | 0:c1d649c7b904 | 64 | if ((tempuint8_t & 0x70) == 0) |
sgrsn | 0:c1d649c7b904 | 65 | { |
sgrsn | 0:c1d649c7b904 | 66 | tempuint8_t |= (1 << 4); // Just default to no divider if not set |
sgrsn | 0:c1d649c7b904 | 67 | writeByte(REG_MISC, tempuint8_t); |
sgrsn | 0:c1d649c7b904 | 68 | } |
sgrsn | 0:c1d649c7b904 | 69 | tempuint8_t = readByte(REG_CLOCK); |
sgrsn | 0:c1d649c7b904 | 70 | if ((tempuint8_t & 0x60) == 0) |
sgrsn | 0:c1d649c7b904 | 71 | { |
sgrsn | 0:c1d649c7b904 | 72 | tempuint8_t |= (1 << 6); // default to internal osc. |
sgrsn | 0:c1d649c7b904 | 73 | writeByte(REG_CLOCK, tempuint8_t); |
sgrsn | 0:c1d649c7b904 | 74 | } |
sgrsn | 0:c1d649c7b904 | 75 | |
sgrsn | 0:c1d649c7b904 | 76 | configValue &= 0b111; // 3-bit value |
sgrsn | 0:c1d649c7b904 | 77 | writeByte(REG_DEBOUNCE_CONFIG, configValue); |
sgrsn | 0:c1d649c7b904 | 78 | } |
sgrsn | 0:c1d649c7b904 | 79 | |
sgrsn | 0:c1d649c7b904 | 80 | void SensorBar::debounceEnable(uint8_t pin) |
sgrsn | 0:c1d649c7b904 | 81 | { |
sgrsn | 0:c1d649c7b904 | 82 | unsigned int debounceEnable = readWord(REG_DEBOUNCE_ENABLE_B); |
sgrsn | 0:c1d649c7b904 | 83 | debounceEnable |= (1 << pin); |
sgrsn | 0:c1d649c7b904 | 84 | writeWord(REG_DEBOUNCE_ENABLE_B, debounceEnable); |
sgrsn | 0:c1d649c7b904 | 85 | } |
sgrsn | 0:c1d649c7b904 | 86 | |
sgrsn | 0:c1d649c7b904 | 87 | //Run this once during initialization to configure the SX1509 as a sensor bar |
sgrsn | 0:c1d649c7b904 | 88 | //Returns 1 for success |
sgrsn | 0:c1d649c7b904 | 89 | uint8_t SensorBar::begin(void) |
sgrsn | 0:c1d649c7b904 | 90 | { |
sgrsn | 0:c1d649c7b904 | 91 | uint8_t returnVar = 0; |
sgrsn | 0:c1d649c7b904 | 92 | |
sgrsn | 0:c1d649c7b904 | 93 | // Reset the SX1509 |
sgrsn | 0:c1d649c7b904 | 94 | reset(); |
sgrsn | 0:c1d649c7b904 | 95 | |
sgrsn | 0:c1d649c7b904 | 96 | // Communication test. We'll read from two registers with different |
sgrsn | 0:c1d649c7b904 | 97 | // default values to verify communication. |
sgrsn | 0:c1d649c7b904 | 98 | unsigned int testRegisters = 0; |
sgrsn | 0:c1d649c7b904 | 99 | testRegisters = readWord(REG_INTERRUPT_MASK_A); // This should return 0xFF00 |
sgrsn | 0:c1d649c7b904 | 100 | // Then read a uint8_t that should be 0x00 |
sgrsn | 0:c1d649c7b904 | 101 | if (testRegisters == 0xFF00) |
sgrsn | 0:c1d649c7b904 | 102 | { |
sgrsn | 0:c1d649c7b904 | 103 | //Success! Configure the device. |
sgrsn | 0:c1d649c7b904 | 104 | writeByte(REG_DIR_A, 0xFF); |
sgrsn | 0:c1d649c7b904 | 105 | writeByte(REG_DIR_B, 0xFC); |
sgrsn | 0:c1d649c7b904 | 106 | writeByte(REG_DATA_B, 0x01); |
sgrsn | 0:c1d649c7b904 | 107 | |
sgrsn | 0:c1d649c7b904 | 108 | returnVar = 1; |
sgrsn | 0:c1d649c7b904 | 109 | } |
sgrsn | 0:c1d649c7b904 | 110 | else |
sgrsn | 0:c1d649c7b904 | 111 | { |
sgrsn | 0:c1d649c7b904 | 112 | returnVar = 0; |
sgrsn | 0:c1d649c7b904 | 113 | } |
sgrsn | 0:c1d649c7b904 | 114 | |
sgrsn | 0:c1d649c7b904 | 115 | return returnVar; |
sgrsn | 0:c1d649c7b904 | 116 | } |
sgrsn | 0:c1d649c7b904 | 117 | |
sgrsn | 0:c1d649c7b904 | 118 | //Do a software reset |
sgrsn | 0:c1d649c7b904 | 119 | void SensorBar::reset( void ) |
sgrsn | 0:c1d649c7b904 | 120 | { |
sgrsn | 0:c1d649c7b904 | 121 | // No hardware option, try software reset |
sgrsn | 0:c1d649c7b904 | 122 | writeByte(REG_RESET, 0x12); |
sgrsn | 0:c1d649c7b904 | 123 | writeByte(REG_RESET, 0x34); |
sgrsn | 0:c1d649c7b904 | 124 | } |
sgrsn | 0:c1d649c7b904 | 125 | |
sgrsn | 0:c1d649c7b904 | 126 | unsigned int SensorBar::interruptSource(void) |
sgrsn | 0:c1d649c7b904 | 127 | { |
sgrsn | 0:c1d649c7b904 | 128 | unsigned int intSource = readWord(REG_INTERRUPT_SOURCE_B); |
sgrsn | 0:c1d649c7b904 | 129 | writeWord(REG_INTERRUPT_SOURCE_B, 0xFFFF); // Clear interrupts |
sgrsn | 0:c1d649c7b904 | 130 | return intSource; |
sgrsn | 0:c1d649c7b904 | 131 | } |
sgrsn | 0:c1d649c7b904 | 132 | |
sgrsn | 0:c1d649c7b904 | 133 | void SensorBar::configClock(uint8_t oscSource, uint8_t oscPinFunction, uint8_t oscFreqOut, uint8_t oscDivider) |
sgrsn | 0:c1d649c7b904 | 134 | { |
sgrsn | 0:c1d649c7b904 | 135 | // RegClock constructed as follows: |
sgrsn | 0:c1d649c7b904 | 136 | // 6:5 - Oscillator frequency souce |
sgrsn | 0:c1d649c7b904 | 137 | // 00: off, 01: external input, 10: internal 2MHz, 1: reserved |
sgrsn | 0:c1d649c7b904 | 138 | // 4 - OSCIO pin function |
sgrsn | 0:c1d649c7b904 | 139 | // 0: input, 1 ouptut |
sgrsn | 0:c1d649c7b904 | 140 | // 3:0 - Frequency of oscout pin |
sgrsn | 0:c1d649c7b904 | 141 | // 0: LOW, 0xF: high, else fOSCOUT = FoSC/(2^(RegClock[3:0]-1)) |
sgrsn | 0:c1d649c7b904 | 142 | oscSource = (oscSource & 0b11) << 5; // 2-bit value, bits 6:5 |
sgrsn | 0:c1d649c7b904 | 143 | oscPinFunction = (oscPinFunction & 1) << 4; // 1-bit value bit 4 |
sgrsn | 0:c1d649c7b904 | 144 | oscFreqOut = (oscFreqOut & 0b1111); // 4-bit value, bits 3:0 |
sgrsn | 0:c1d649c7b904 | 145 | uint8_t regClock = oscSource | oscPinFunction | oscFreqOut; |
sgrsn | 0:c1d649c7b904 | 146 | writeByte(REG_CLOCK, regClock); |
sgrsn | 0:c1d649c7b904 | 147 | |
sgrsn | 0:c1d649c7b904 | 148 | // Config RegMisc[6:4] with oscDivider |
sgrsn | 0:c1d649c7b904 | 149 | // 0: off, else ClkX = fOSC / (2^(RegMisc[6:4] -1)) |
sgrsn | 0:c1d649c7b904 | 150 | oscDivider = (oscDivider & 0b111) << 4; // 3-bit value, bits 6:4 |
sgrsn | 0:c1d649c7b904 | 151 | uint8_t regMisc = readByte(REG_MISC); |
sgrsn | 0:c1d649c7b904 | 152 | regMisc &= ~(0b111 << 4); |
sgrsn | 0:c1d649c7b904 | 153 | regMisc |= oscDivider; |
sgrsn | 0:c1d649c7b904 | 154 | writeByte(REG_MISC, regMisc); |
sgrsn | 0:c1d649c7b904 | 155 | } |
sgrsn | 0:c1d649c7b904 | 156 | |
sgrsn | 0:c1d649c7b904 | 157 | //Call .setBarStrobing(); to only illuminate while reading line |
sgrsn | 0:c1d649c7b904 | 158 | void SensorBar::setBarStrobe( void ) |
sgrsn | 0:c1d649c7b904 | 159 | { |
sgrsn | 0:c1d649c7b904 | 160 | barStrobe = 1; //Do strobe |
sgrsn | 0:c1d649c7b904 | 161 | } |
sgrsn | 0:c1d649c7b904 | 162 | |
sgrsn | 0:c1d649c7b904 | 163 | //Call .clearBarStrobing(); to illuminate all the time |
sgrsn | 0:c1d649c7b904 | 164 | void SensorBar::clearBarStrobe( void ) |
sgrsn | 0:c1d649c7b904 | 165 | { |
sgrsn | 0:c1d649c7b904 | 166 | barStrobe = 0; //Always on |
sgrsn | 0:c1d649c7b904 | 167 | } |
sgrsn | 0:c1d649c7b904 | 168 | |
sgrsn | 0:c1d649c7b904 | 169 | // .setInvertBits(); to make the bar functions look for a white line on dark surface |
sgrsn | 0:c1d649c7b904 | 170 | void SensorBar::setInvertBits( void ) |
sgrsn | 0:c1d649c7b904 | 171 | { |
sgrsn | 0:c1d649c7b904 | 172 | invertBits = 1; //Do strobe |
sgrsn | 0:c1d649c7b904 | 173 | } |
sgrsn | 0:c1d649c7b904 | 174 | |
sgrsn | 0:c1d649c7b904 | 175 | // .clearInvertBits(); to make the bar look for a dark line on a reflective surface |
sgrsn | 0:c1d649c7b904 | 176 | void SensorBar::clearInvertBits( void ) |
sgrsn | 0:c1d649c7b904 | 177 | { |
sgrsn | 0:c1d649c7b904 | 178 | invertBits = 0; //Always on |
sgrsn | 0:c1d649c7b904 | 179 | } |
sgrsn | 0:c1d649c7b904 | 180 | |
sgrsn | 0:c1d649c7b904 | 181 | //****************************************************************************// |
sgrsn | 0:c1d649c7b904 | 182 | // |
sgrsn | 0:c1d649c7b904 | 183 | // Bar functions |
sgrsn | 0:c1d649c7b904 | 184 | // |
sgrsn | 0:c1d649c7b904 | 185 | //****************************************************************************// |
sgrsn | 0:c1d649c7b904 | 186 | |
sgrsn | 0:c1d649c7b904 | 187 | uint8_t SensorBar::getRaw( void ) |
sgrsn | 0:c1d649c7b904 | 188 | { |
sgrsn | 0:c1d649c7b904 | 189 | //Get the information from the wire, stores in lastBarRawValue |
sgrsn | 0:c1d649c7b904 | 190 | scan(); |
sgrsn | 0:c1d649c7b904 | 191 | |
sgrsn | 0:c1d649c7b904 | 192 | return lastBarRawValue; |
sgrsn | 0:c1d649c7b904 | 193 | } |
sgrsn | 0:c1d649c7b904 | 194 | |
sgrsn | 0:c1d649c7b904 | 195 | int8_t SensorBar::getPosition( void ) |
sgrsn | 0:c1d649c7b904 | 196 | { |
sgrsn | 0:c1d649c7b904 | 197 | //Assign values to each bit, -127 to 127, sum, and divide |
sgrsn | 0:c1d649c7b904 | 198 | int16_t accumulator = 0; |
sgrsn | 0:c1d649c7b904 | 199 | uint8_t bitsCounted = 0; |
sgrsn | 0:c1d649c7b904 | 200 | int16_t i; |
sgrsn | 0:c1d649c7b904 | 201 | |
sgrsn | 0:c1d649c7b904 | 202 | //Get the information from the wire, stores in lastBarRawValue |
sgrsn | 0:c1d649c7b904 | 203 | scan(); |
sgrsn | 0:c1d649c7b904 | 204 | |
sgrsn | 0:c1d649c7b904 | 205 | //count bits |
sgrsn | 0:c1d649c7b904 | 206 | for ( i = 0; i < 8; i++ ) |
sgrsn | 0:c1d649c7b904 | 207 | { |
sgrsn | 0:c1d649c7b904 | 208 | if ( ((lastBarRawValue >> i) & 0x01) == 1 ) |
sgrsn | 0:c1d649c7b904 | 209 | { |
sgrsn | 0:c1d649c7b904 | 210 | bitsCounted++; |
sgrsn | 0:c1d649c7b904 | 211 | } |
sgrsn | 0:c1d649c7b904 | 212 | } |
sgrsn | 0:c1d649c7b904 | 213 | |
sgrsn | 0:c1d649c7b904 | 214 | //Find the vector value of each positive bit and sum |
sgrsn | 0:c1d649c7b904 | 215 | for ( i = 7; i > 3; i-- ) //iterate negative side bits |
sgrsn | 0:c1d649c7b904 | 216 | { |
sgrsn | 0:c1d649c7b904 | 217 | if ( ((lastBarRawValue >> i) & 0x01) == 1 ) |
sgrsn | 0:c1d649c7b904 | 218 | { |
sgrsn | 0:c1d649c7b904 | 219 | accumulator += ((-32 * (i - 3)) + 1); |
sgrsn | 0:c1d649c7b904 | 220 | } |
sgrsn | 0:c1d649c7b904 | 221 | } |
sgrsn | 0:c1d649c7b904 | 222 | for ( i = 0; i < 4; i++ ) //iterate positive side bits |
sgrsn | 0:c1d649c7b904 | 223 | { |
sgrsn | 0:c1d649c7b904 | 224 | if ( ((lastBarRawValue >> i) & 0x01) == 1 ) |
sgrsn | 0:c1d649c7b904 | 225 | { |
sgrsn | 0:c1d649c7b904 | 226 | accumulator += ((32 * (4 - i)) - 1); |
sgrsn | 0:c1d649c7b904 | 227 | } |
sgrsn | 0:c1d649c7b904 | 228 | } |
sgrsn | 0:c1d649c7b904 | 229 | |
sgrsn | 0:c1d649c7b904 | 230 | if ( bitsCounted > 0 ) |
sgrsn | 0:c1d649c7b904 | 231 | { |
sgrsn | 0:c1d649c7b904 | 232 | lastBarPositionValue = accumulator / bitsCounted; |
sgrsn | 0:c1d649c7b904 | 233 | } |
sgrsn | 0:c1d649c7b904 | 234 | else |
sgrsn | 0:c1d649c7b904 | 235 | { |
sgrsn | 0:c1d649c7b904 | 236 | lastBarPositionValue = 0; |
sgrsn | 0:c1d649c7b904 | 237 | } |
sgrsn | 0:c1d649c7b904 | 238 | |
sgrsn | 0:c1d649c7b904 | 239 | return lastBarPositionValue; |
sgrsn | 0:c1d649c7b904 | 240 | } |
sgrsn | 0:c1d649c7b904 | 241 | |
sgrsn | 0:c1d649c7b904 | 242 | uint8_t SensorBar::getDensity( void ) |
sgrsn | 0:c1d649c7b904 | 243 | { |
sgrsn | 0:c1d649c7b904 | 244 | uint8_t bitsCounted = 0; |
sgrsn | 0:c1d649c7b904 | 245 | uint8_t i; |
sgrsn | 0:c1d649c7b904 | 246 | |
sgrsn | 0:c1d649c7b904 | 247 | //get input from the I2C machine |
sgrsn | 0:c1d649c7b904 | 248 | scan(); |
sgrsn | 0:c1d649c7b904 | 249 | |
sgrsn | 0:c1d649c7b904 | 250 | //count bits |
sgrsn | 0:c1d649c7b904 | 251 | for ( i = 0; i < 8; i++ ) |
sgrsn | 0:c1d649c7b904 | 252 | { |
sgrsn | 0:c1d649c7b904 | 253 | if ( ((lastBarRawValue >> i) & 0x01) == 1 ) |
sgrsn | 0:c1d649c7b904 | 254 | { |
sgrsn | 0:c1d649c7b904 | 255 | bitsCounted++; |
sgrsn | 0:c1d649c7b904 | 256 | } |
sgrsn | 0:c1d649c7b904 | 257 | } |
sgrsn | 0:c1d649c7b904 | 258 | return bitsCounted; |
sgrsn | 0:c1d649c7b904 | 259 | } |
sgrsn | 0:c1d649c7b904 | 260 | |
sgrsn | 0:c1d649c7b904 | 261 | |
sgrsn | 0:c1d649c7b904 | 262 | //****************************************************************************// |
sgrsn | 0:c1d649c7b904 | 263 | // |
sgrsn | 0:c1d649c7b904 | 264 | // Utilities |
sgrsn | 0:c1d649c7b904 | 265 | // |
sgrsn | 0:c1d649c7b904 | 266 | //****************************************************************************// |
sgrsn | 0:c1d649c7b904 | 267 | void SensorBar::scan( void ) |
sgrsn | 0:c1d649c7b904 | 268 | { |
sgrsn | 0:c1d649c7b904 | 269 | if( barStrobe == 1 ) |
sgrsn | 0:c1d649c7b904 | 270 | { |
sgrsn | 0:c1d649c7b904 | 271 | writeByte(REG_DATA_B, 0x02); //Turn on IR |
sgrsn | 0:c1d649c7b904 | 272 | wait_ms(2); //Additional delay required after IR is turned on to allow LEDs to achieve full brightness |
sgrsn | 0:c1d649c7b904 | 273 | writeByte(REG_DATA_B, 0x00); //Turn on feedback |
sgrsn | 0:c1d649c7b904 | 274 | } |
sgrsn | 0:c1d649c7b904 | 275 | else |
sgrsn | 0:c1d649c7b904 | 276 | { |
sgrsn | 0:c1d649c7b904 | 277 | writeByte(REG_DATA_B, 0x00); //make sure both IR and indicators are on |
sgrsn | 0:c1d649c7b904 | 278 | } |
sgrsn | 0:c1d649c7b904 | 279 | //Operate the I2C machine |
sgrsn | 0:c1d649c7b904 | 280 | lastBarRawValue = readByte( REG_DATA_A ); //Peel the data off port A |
sgrsn | 0:c1d649c7b904 | 281 | |
sgrsn | 0:c1d649c7b904 | 282 | if( invertBits == 1 ) //Invert the bits if needed |
sgrsn | 0:c1d649c7b904 | 283 | { |
sgrsn | 0:c1d649c7b904 | 284 | lastBarRawValue ^= 0xFF; |
sgrsn | 0:c1d649c7b904 | 285 | } |
sgrsn | 0:c1d649c7b904 | 286 | |
sgrsn | 0:c1d649c7b904 | 287 | if( barStrobe == 1 ) |
sgrsn | 0:c1d649c7b904 | 288 | { |
sgrsn | 0:c1d649c7b904 | 289 | writeByte(REG_DATA_B, 0x03); //Turn off IR and feedback when done |
sgrsn | 0:c1d649c7b904 | 290 | } |
sgrsn | 0:c1d649c7b904 | 291 | //delay(8); |
sgrsn | 0:c1d649c7b904 | 292 | } |
sgrsn | 0:c1d649c7b904 | 293 | |
sgrsn | 0:c1d649c7b904 | 294 | // readByte(uint8_t registerAddress) |
sgrsn | 0:c1d649c7b904 | 295 | // This function reads a single uint8_t located at the registerAddress register. |
sgrsn | 0:c1d649c7b904 | 296 | // - deviceAddress should already be set by the constructor. |
sgrsn | 0:c1d649c7b904 | 297 | // - Return value is the uint8_t read from registerAddress |
sgrsn | 0:c1d649c7b904 | 298 | // |
sgrsn | 0:c1d649c7b904 | 299 | // Currently returns 0 if communication has timed out |
sgrsn | 0:c1d649c7b904 | 300 | // |
sgrsn | 0:c1d649c7b904 | 301 | uint8_t SensorBar::readByte(uint8_t registerAddress) |
sgrsn | 0:c1d649c7b904 | 302 | { |
sgrsn | 0:c1d649c7b904 | 303 | char readValue; |
sgrsn | 0:c1d649c7b904 | 304 | char data[2] = {registerAddress, 0}; |
sgrsn | 0:c1d649c7b904 | 305 | _i2c->write(deviceAddress, data, 1); |
sgrsn | 0:c1d649c7b904 | 306 | uint8_t val = _i2c->read(deviceAddress, &readValue, 1); |
sgrsn | 0:c1d649c7b904 | 307 | |
sgrsn | 0:c1d649c7b904 | 308 | return readValue; |
sgrsn | 0:c1d649c7b904 | 309 | } |
sgrsn | 0:c1d649c7b904 | 310 | |
sgrsn | 0:c1d649c7b904 | 311 | // readWord(uint8_t registerAddress) |
sgrsn | 0:c1d649c7b904 | 312 | // This function will read a two-uint8_t word beginning at registerAddress |
sgrsn | 0:c1d649c7b904 | 313 | // - A 16-bit unsigned int will be returned. |
sgrsn | 0:c1d649c7b904 | 314 | // - The msb of the return value will contain the value read from registerAddress |
sgrsn | 0:c1d649c7b904 | 315 | // - The lsb of the return value will contain the value read from registerAddress + 1 |
sgrsn | 0:c1d649c7b904 | 316 | unsigned int SensorBar::readWord(uint8_t registerAddress) |
sgrsn | 0:c1d649c7b904 | 317 | { |
sgrsn | 0:c1d649c7b904 | 318 | unsigned int readValue; |
sgrsn | 0:c1d649c7b904 | 319 | unsigned int msb, lsb; |
sgrsn | 0:c1d649c7b904 | 320 | //unsigned int timeout = RECEIVE_TIMEOUT_VALUE * 2; |
sgrsn | 0:c1d649c7b904 | 321 | char data[2] = {registerAddress, 0}; |
sgrsn | 0:c1d649c7b904 | 322 | char r_data[2]; |
sgrsn | 0:c1d649c7b904 | 323 | uint8_t val = _i2c->write(deviceAddress, data, 1); |
sgrsn | 0:c1d649c7b904 | 324 | val = _i2c->read(deviceAddress, r_data, 2); |
sgrsn | 0:c1d649c7b904 | 325 | msb = ((unsigned int)r_data[0] & 0x00FF) << 8; |
sgrsn | 0:c1d649c7b904 | 326 | lsb = ((unsigned int)r_data[1] & 0x00FF); |
sgrsn | 0:c1d649c7b904 | 327 | readValue = msb | lsb; |
sgrsn | 0:c1d649c7b904 | 328 | |
sgrsn | 0:c1d649c7b904 | 329 | return readValue; |
sgrsn | 0:c1d649c7b904 | 330 | } |
sgrsn | 0:c1d649c7b904 | 331 | |
sgrsn | 0:c1d649c7b904 | 332 | // readBytes(uint8_t firstRegisterAddress, uint8_t * destination, uint8_t length) |
sgrsn | 0:c1d649c7b904 | 333 | // This function reads a series of uint8_ts incrementing from a given address |
sgrsn | 0:c1d649c7b904 | 334 | // - firstRegsiterAddress is the first address to be read |
sgrsn | 0:c1d649c7b904 | 335 | // - destination is an array of uint8_ts where the read values will be stored into |
sgrsn | 0:c1d649c7b904 | 336 | // - length is the number of uint8_ts to be read |
sgrsn | 0:c1d649c7b904 | 337 | // - No return value. |
sgrsn | 0:c1d649c7b904 | 338 | void SensorBar::readBytes(uint8_t firstRegisterAddress, char * destination, uint8_t length) |
sgrsn | 0:c1d649c7b904 | 339 | { |
sgrsn | 0:c1d649c7b904 | 340 | char data[2] = {firstRegisterAddress, 0}; |
sgrsn | 0:c1d649c7b904 | 341 | _i2c->write(deviceAddress, data, 1); |
sgrsn | 0:c1d649c7b904 | 342 | uint8_t val = _i2c->read(deviceAddress, destination, length); |
sgrsn | 0:c1d649c7b904 | 343 | } |
sgrsn | 0:c1d649c7b904 | 344 | |
sgrsn | 0:c1d649c7b904 | 345 | // writeByte(uint8_t registerAddress, uint8_t writeValue) |
sgrsn | 0:c1d649c7b904 | 346 | // This function writes a single uint8_t to a single register on the SX509. |
sgrsn | 0:c1d649c7b904 | 347 | // - writeValue is written to registerAddress |
sgrsn | 0:c1d649c7b904 | 348 | // - deviceAddres should already be set from the constructor |
sgrsn | 0:c1d649c7b904 | 349 | // - No return value. |
sgrsn | 0:c1d649c7b904 | 350 | void SensorBar::writeByte(uint8_t registerAddress, uint8_t writeValue) |
sgrsn | 0:c1d649c7b904 | 351 | { |
sgrsn | 0:c1d649c7b904 | 352 | char data[2] = {registerAddress, writeValue}; |
sgrsn | 0:c1d649c7b904 | 353 | _i2c->write(deviceAddress, data, 2); |
sgrsn | 0:c1d649c7b904 | 354 | } |
sgrsn | 0:c1d649c7b904 | 355 | |
sgrsn | 0:c1d649c7b904 | 356 | // writeWord(uint8_t registerAddress, ungisnged int writeValue) |
sgrsn | 0:c1d649c7b904 | 357 | // This function writes a two-uint8_t word to registerAddress and registerAddress + 1 |
sgrsn | 0:c1d649c7b904 | 358 | // - the upper uint8_t of writeValue is written to registerAddress |
sgrsn | 0:c1d649c7b904 | 359 | // - the lower uint8_t of writeValue is written to registerAddress + 1 |
sgrsn | 0:c1d649c7b904 | 360 | // - No return value. |
sgrsn | 0:c1d649c7b904 | 361 | void SensorBar::writeWord(uint8_t registerAddress, unsigned int writeValue) |
sgrsn | 0:c1d649c7b904 | 362 | { |
sgrsn | 0:c1d649c7b904 | 363 | uint8_t msb, lsb; |
sgrsn | 0:c1d649c7b904 | 364 | msb = ((writeValue & 0xFF00) >> 8); |
sgrsn | 0:c1d649c7b904 | 365 | lsb = (writeValue & 0x00FF); |
sgrsn | 0:c1d649c7b904 | 366 | char data[3] = {registerAddress, msb, lsb}; |
sgrsn | 0:c1d649c7b904 | 367 | _i2c->write(deviceAddress, data, 3); |
sgrsn | 0:c1d649c7b904 | 368 | } |
sgrsn | 0:c1d649c7b904 | 369 | |
sgrsn | 0:c1d649c7b904 | 370 | // writeBytes(uint8_t firstRegisterAddress, uint8_t * writeArray, uint8_t length) |
sgrsn | 0:c1d649c7b904 | 371 | // This function writes an array of uint8_ts, beggining at a specific adddress |
sgrsn | 0:c1d649c7b904 | 372 | // - firstRegisterAddress is the initial register to be written. |
sgrsn | 0:c1d649c7b904 | 373 | // - All writes following will be at incremental register addresses. |
sgrsn | 0:c1d649c7b904 | 374 | // - writeArray should be an array of uint8_t values to be written. |
sgrsn | 0:c1d649c7b904 | 375 | // - length should be the number of uint8_ts to be written. |
sgrsn | 0:c1d649c7b904 | 376 | // - no return value. |
sgrsn | 0:c1d649c7b904 | 377 | void SensorBar::writeBytes(uint8_t firstRegisterAddress, uint8_t * writeArray, uint8_t length) |
sgrsn | 0:c1d649c7b904 | 378 | { |
sgrsn | 0:c1d649c7b904 | 379 | char data[10] = {}; |
sgrsn | 0:c1d649c7b904 | 380 | data[0] = firstRegisterAddress; |
sgrsn | 0:c1d649c7b904 | 381 | for(int i = 0; i < length; i++) |
sgrsn | 0:c1d649c7b904 | 382 | { |
sgrsn | 0:c1d649c7b904 | 383 | data[1+i] = writeArray[i]; |
sgrsn | 0:c1d649c7b904 | 384 | } |
sgrsn | 0:c1d649c7b904 | 385 | _i2c->write(deviceAddress, data, length+1); |
sgrsn | 0:c1d649c7b904 | 386 | } |
sgrsn | 0:c1d649c7b904 | 387 | |
sgrsn | 0:c1d649c7b904 | 388 | |
sgrsn | 0:c1d649c7b904 | 389 | //****************************************************************************// |
sgrsn | 0:c1d649c7b904 | 390 | // |
sgrsn | 0:c1d649c7b904 | 391 | // Circular buffer |
sgrsn | 0:c1d649c7b904 | 392 | // |
sgrsn | 0:c1d649c7b904 | 393 | //****************************************************************************// |
sgrsn | 0:c1d649c7b904 | 394 | |
sgrsn | 0:c1d649c7b904 | 395 | //Construct a CircularBuffer type with arguments |
sgrsn | 0:c1d649c7b904 | 396 | // uint16_t inputSize: number of elements |
sgrsn | 0:c1d649c7b904 | 397 | |
sgrsn | 0:c1d649c7b904 | 398 | //mbed has CircularBuffer |
sgrsn | 0:c1d649c7b904 | 399 | namespace name |
sgrsn | 0:c1d649c7b904 | 400 | { |
sgrsn | 0:c1d649c7b904 | 401 | |
sgrsn | 0:c1d649c7b904 | 402 | CircularBuffer::CircularBuffer(uint16_t inputSize) |
sgrsn | 0:c1d649c7b904 | 403 | { |
sgrsn | 0:c1d649c7b904 | 404 | cBufferData = new int16_t[inputSize]; |
sgrsn | 0:c1d649c7b904 | 405 | cBufferLastPtr = 0; |
sgrsn | 0:c1d649c7b904 | 406 | cBufferElementsUsed = 0; |
sgrsn | 0:c1d649c7b904 | 407 | cBufferSize = inputSize; |
sgrsn | 0:c1d649c7b904 | 408 | } |
sgrsn | 0:c1d649c7b904 | 409 | |
sgrsn | 0:c1d649c7b904 | 410 | CircularBuffer::~CircularBuffer() |
sgrsn | 0:c1d649c7b904 | 411 | { |
sgrsn | 0:c1d649c7b904 | 412 | delete[] cBufferData; |
sgrsn | 0:c1d649c7b904 | 413 | } |
sgrsn | 0:c1d649c7b904 | 414 | |
sgrsn | 0:c1d649c7b904 | 415 | //Get an element at some depth into the circular buffer |
sgrsn | 0:c1d649c7b904 | 416 | //zero is the push location. Max is cBufferSize - 1 |
sgrsn | 0:c1d649c7b904 | 417 | // |
sgrsn | 0:c1d649c7b904 | 418 | //Arguments: |
sgrsn | 0:c1d649c7b904 | 419 | // uint16_t elementNum: number of element in |
sgrsn | 0:c1d649c7b904 | 420 | // |
sgrsn | 0:c1d649c7b904 | 421 | int16_t CircularBuffer::getElement( uint16_t elementNum ) |
sgrsn | 0:c1d649c7b904 | 422 | { |
sgrsn | 0:c1d649c7b904 | 423 | //Translate elementNum into terms of cBufferLastPtr. |
sgrsn | 0:c1d649c7b904 | 424 | int16_t virtualElementNum; |
sgrsn | 0:c1d649c7b904 | 425 | virtualElementNum = cBufferLastPtr - elementNum; |
sgrsn | 0:c1d649c7b904 | 426 | if( virtualElementNum < 0 ) |
sgrsn | 0:c1d649c7b904 | 427 | { |
sgrsn | 0:c1d649c7b904 | 428 | virtualElementNum += cBufferSize; |
sgrsn | 0:c1d649c7b904 | 429 | } |
sgrsn | 0:c1d649c7b904 | 430 | |
sgrsn | 0:c1d649c7b904 | 431 | //Output the value |
sgrsn | 0:c1d649c7b904 | 432 | return cBufferData[virtualElementNum]; |
sgrsn | 0:c1d649c7b904 | 433 | } |
sgrsn | 0:c1d649c7b904 | 434 | |
sgrsn | 0:c1d649c7b904 | 435 | //Put a new element into the buffer. |
sgrsn | 0:c1d649c7b904 | 436 | //This also expands the size up to the max size |
sgrsn | 0:c1d649c7b904 | 437 | //Arguments: |
sgrsn | 0:c1d649c7b904 | 438 | // |
sgrsn | 0:c1d649c7b904 | 439 | // int16_t elementVal: value of new element |
sgrsn | 0:c1d649c7b904 | 440 | // |
sgrsn | 0:c1d649c7b904 | 441 | void CircularBuffer::pushElement( int16_t elementVal ) |
sgrsn | 0:c1d649c7b904 | 442 | { |
sgrsn | 0:c1d649c7b904 | 443 | //inc. the pointer |
sgrsn | 0:c1d649c7b904 | 444 | cBufferLastPtr++; |
sgrsn | 0:c1d649c7b904 | 445 | |
sgrsn | 0:c1d649c7b904 | 446 | //deal with roll |
sgrsn | 0:c1d649c7b904 | 447 | if( cBufferLastPtr >= cBufferSize ) |
sgrsn | 0:c1d649c7b904 | 448 | { |
sgrsn | 0:c1d649c7b904 | 449 | cBufferLastPtr = 0; |
sgrsn | 0:c1d649c7b904 | 450 | } |
sgrsn | 0:c1d649c7b904 | 451 | |
sgrsn | 0:c1d649c7b904 | 452 | //write data |
sgrsn | 0:c1d649c7b904 | 453 | cBufferData[cBufferLastPtr] = elementVal; |
sgrsn | 0:c1d649c7b904 | 454 | |
sgrsn | 0:c1d649c7b904 | 455 | //increase length up to cBufferSize |
sgrsn | 0:c1d649c7b904 | 456 | if( cBufferElementsUsed < cBufferSize ) |
sgrsn | 0:c1d649c7b904 | 457 | { |
sgrsn | 0:c1d649c7b904 | 458 | cBufferElementsUsed++; |
sgrsn | 0:c1d649c7b904 | 459 | } |
sgrsn | 0:c1d649c7b904 | 460 | } |
sgrsn | 0:c1d649c7b904 | 461 | |
sgrsn | 0:c1d649c7b904 | 462 | //Averages the last n numbers and provides that. Discards fractions |
sgrsn | 0:c1d649c7b904 | 463 | int16_t CircularBuffer::averageLast( uint16_t numElements ) |
sgrsn | 0:c1d649c7b904 | 464 | { |
sgrsn | 0:c1d649c7b904 | 465 | //Add up all the elements |
sgrsn | 0:c1d649c7b904 | 466 | int32_t accumulator = 0; |
sgrsn | 0:c1d649c7b904 | 467 | int8_t i; |
sgrsn | 0:c1d649c7b904 | 468 | for( i = 0; i < numElements; i++ ) |
sgrsn | 0:c1d649c7b904 | 469 | { |
sgrsn | 0:c1d649c7b904 | 470 | accumulator += getElement( i ); |
sgrsn | 0:c1d649c7b904 | 471 | } |
sgrsn | 0:c1d649c7b904 | 472 | //Divide by number of elements |
sgrsn | 0:c1d649c7b904 | 473 | accumulator /= numElements; |
sgrsn | 0:c1d649c7b904 | 474 | return accumulator; |
sgrsn | 0:c1d649c7b904 | 475 | } |
sgrsn | 0:c1d649c7b904 | 476 | |
sgrsn | 0:c1d649c7b904 | 477 | //Returns the current size of the buffer |
sgrsn | 0:c1d649c7b904 | 478 | uint16_t CircularBuffer::recordLength( void ) |
sgrsn | 0:c1d649c7b904 | 479 | { |
sgrsn | 0:c1d649c7b904 | 480 | return cBufferElementsUsed; |
sgrsn | 0:c1d649c7b904 | 481 | } |
sgrsn | 0:c1d649c7b904 | 482 | |
sgrsn | 0:c1d649c7b904 | 483 | } |
sgrsn | 0:c1d649c7b904 | 484 |