blob: adf1c548608350ac3d7f9b029cef85b6f5144067 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include "frc/I2C.h"
6
7#include <utility>
8
9#include <hal/FRCUsageReporting.h>
10#include <hal/I2C.h>
11
Austin Schuh812d0d12021-11-04 20:16:48 -070012#include "frc/Errors.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080013
14using namespace frc;
15
16I2C::I2C(Port port, int deviceAddress)
17 : m_port(static_cast<HAL_I2CPort>(port)), m_deviceAddress(deviceAddress) {
18 int32_t status = 0;
19 HAL_InitializeI2C(m_port, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070020 FRC_CheckErrorStatus(status, "Port {}", port);
Brian Silverman8fce7482020-01-05 13:18:21 -080021
22 HAL_Report(HALUsageReporting::kResourceType_I2C, deviceAddress);
23}
24
Austin Schuh812d0d12021-11-04 20:16:48 -070025I2C::~I2C() {
26 HAL_CloseI2C(m_port);
27}
28
29I2C::Port I2C::GetPort() const {
30 return static_cast<Port>(static_cast<int>(m_port));
31}
32
33int I2C::GetDeviceAddress() const {
34 return m_deviceAddress;
35}
Brian Silverman8fce7482020-01-05 13:18:21 -080036
37bool I2C::Transaction(uint8_t* dataToSend, int sendSize, uint8_t* dataReceived,
38 int receiveSize) {
39 int32_t status = 0;
40 status = HAL_TransactionI2C(m_port, m_deviceAddress, dataToSend, sendSize,
41 dataReceived, receiveSize);
Brian Silverman8fce7482020-01-05 13:18:21 -080042 return status < 0;
43}
44
Austin Schuh812d0d12021-11-04 20:16:48 -070045bool I2C::AddressOnly() {
46 return Transaction(nullptr, 0, nullptr, 0);
47}
Brian Silverman8fce7482020-01-05 13:18:21 -080048
49bool I2C::Write(int registerAddress, uint8_t data) {
50 uint8_t buffer[2];
51 buffer[0] = registerAddress;
52 buffer[1] = data;
53 int32_t status = 0;
54 status = HAL_WriteI2C(m_port, m_deviceAddress, buffer, sizeof(buffer));
55 return status < 0;
56}
57
58bool I2C::WriteBulk(uint8_t* data, int count) {
59 int32_t status = 0;
60 status = HAL_WriteI2C(m_port, m_deviceAddress, data, count);
61 return status < 0;
62}
63
64bool I2C::Read(int registerAddress, int count, uint8_t* buffer) {
65 if (count < 1) {
Austin Schuh812d0d12021-11-04 20:16:48 -070066 throw FRC_MakeError(err::ParameterOutOfRange, "count {}", count);
Brian Silverman8fce7482020-01-05 13:18:21 -080067 }
Austin Schuh812d0d12021-11-04 20:16:48 -070068 if (!buffer) {
69 throw FRC_MakeError(err::NullParameter, "{}", "buffer");
Brian Silverman8fce7482020-01-05 13:18:21 -080070 }
71 uint8_t regAddr = registerAddress;
72 return Transaction(&regAddr, sizeof(regAddr), buffer, count);
73}
74
75bool I2C::ReadOnly(int count, uint8_t* buffer) {
76 if (count < 1) {
Austin Schuh812d0d12021-11-04 20:16:48 -070077 throw FRC_MakeError(err::ParameterOutOfRange, "count {}", count);
Brian Silverman8fce7482020-01-05 13:18:21 -080078 }
Austin Schuh812d0d12021-11-04 20:16:48 -070079 if (!buffer) {
80 throw FRC_MakeError(err::NullParameter, "{}", "buffer");
Brian Silverman8fce7482020-01-05 13:18:21 -080081 }
82 return HAL_ReadI2C(m_port, m_deviceAddress, buffer, count) < 0;
83}
84
85bool I2C::VerifySensor(int registerAddress, int count,
86 const uint8_t* expected) {
87 // TODO: Make use of all 7 read bytes
88 uint8_t deviceData[4];
89 for (int i = 0, curRegisterAddress = registerAddress; i < count;
90 i += 4, curRegisterAddress += 4) {
91 int toRead = count - i < 4 ? count - i : 4;
92 // Read the chunk of data. Return false if the sensor does not respond.
Austin Schuh812d0d12021-11-04 20:16:48 -070093 if (Read(curRegisterAddress, toRead, deviceData)) {
94 return false;
95 }
Brian Silverman8fce7482020-01-05 13:18:21 -080096
97 for (int j = 0; j < toRead; j++) {
Austin Schuh812d0d12021-11-04 20:16:48 -070098 if (deviceData[j] != expected[i + j]) {
99 return false;
100 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800101 }
102 }
103 return true;
104}