blob: da26c0c9cee371906345523c32d624b38a00f1a0 [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;
Austin Schuh75263e32022-02-22 18:05:32 -080019
20 if (port == I2C::Port::kOnboard) {
James Kuszmaulcf324122023-01-14 14:07:17 -080021 FRC_ReportError(warn::Warning,
Austin Schuh75263e32022-02-22 18:05:32 -080022 "Onboard I2C port is subject to system lockups. See Known "
23 "Issues page for "
24 "details");
25 }
26
Brian Silverman8fce7482020-01-05 13:18:21 -080027 HAL_InitializeI2C(m_port, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080028 FRC_CheckErrorStatus(status, "Port {}", static_cast<int>(port));
Brian Silverman8fce7482020-01-05 13:18:21 -080029
30 HAL_Report(HALUsageReporting::kResourceType_I2C, deviceAddress);
31}
32
Austin Schuh812d0d12021-11-04 20:16:48 -070033I2C::~I2C() {
34 HAL_CloseI2C(m_port);
35}
36
37I2C::Port I2C::GetPort() const {
38 return static_cast<Port>(static_cast<int>(m_port));
39}
40
41int I2C::GetDeviceAddress() const {
42 return m_deviceAddress;
43}
Brian Silverman8fce7482020-01-05 13:18:21 -080044
45bool I2C::Transaction(uint8_t* dataToSend, int sendSize, uint8_t* dataReceived,
46 int receiveSize) {
47 int32_t status = 0;
48 status = HAL_TransactionI2C(m_port, m_deviceAddress, dataToSend, sendSize,
49 dataReceived, receiveSize);
Brian Silverman8fce7482020-01-05 13:18:21 -080050 return status < 0;
51}
52
Austin Schuh812d0d12021-11-04 20:16:48 -070053bool I2C::AddressOnly() {
54 return Transaction(nullptr, 0, nullptr, 0);
55}
Brian Silverman8fce7482020-01-05 13:18:21 -080056
57bool I2C::Write(int registerAddress, uint8_t data) {
58 uint8_t buffer[2];
59 buffer[0] = registerAddress;
60 buffer[1] = data;
61 int32_t status = 0;
62 status = HAL_WriteI2C(m_port, m_deviceAddress, buffer, sizeof(buffer));
63 return status < 0;
64}
65
66bool I2C::WriteBulk(uint8_t* data, int count) {
67 int32_t status = 0;
68 status = HAL_WriteI2C(m_port, m_deviceAddress, data, count);
69 return status < 0;
70}
71
72bool I2C::Read(int registerAddress, int count, uint8_t* buffer) {
73 if (count < 1) {
Austin Schuh812d0d12021-11-04 20:16:48 -070074 throw FRC_MakeError(err::ParameterOutOfRange, "count {}", count);
Brian Silverman8fce7482020-01-05 13:18:21 -080075 }
Austin Schuh812d0d12021-11-04 20:16:48 -070076 if (!buffer) {
James Kuszmaulcf324122023-01-14 14:07:17 -080077 throw FRC_MakeError(err::NullParameter, "buffer");
Brian Silverman8fce7482020-01-05 13:18:21 -080078 }
79 uint8_t regAddr = registerAddress;
80 return Transaction(&regAddr, sizeof(regAddr), buffer, count);
81}
82
83bool I2C::ReadOnly(int count, uint8_t* buffer) {
84 if (count < 1) {
Austin Schuh812d0d12021-11-04 20:16:48 -070085 throw FRC_MakeError(err::ParameterOutOfRange, "count {}", count);
Brian Silverman8fce7482020-01-05 13:18:21 -080086 }
Austin Schuh812d0d12021-11-04 20:16:48 -070087 if (!buffer) {
James Kuszmaulcf324122023-01-14 14:07:17 -080088 throw FRC_MakeError(err::NullParameter, "buffer");
Brian Silverman8fce7482020-01-05 13:18:21 -080089 }
90 return HAL_ReadI2C(m_port, m_deviceAddress, buffer, count) < 0;
91}
92
93bool I2C::VerifySensor(int registerAddress, int count,
94 const uint8_t* expected) {
95 // TODO: Make use of all 7 read bytes
96 uint8_t deviceData[4];
97 for (int i = 0, curRegisterAddress = registerAddress; i < count;
98 i += 4, curRegisterAddress += 4) {
99 int toRead = count - i < 4 ? count - i : 4;
100 // Read the chunk of data. Return false if the sensor does not respond.
Austin Schuh812d0d12021-11-04 20:16:48 -0700101 if (Read(curRegisterAddress, toRead, deviceData)) {
102 return false;
103 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800104
105 for (int j = 0; j < toRead; j++) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700106 if (deviceData[j] != expected[i + j]) {
107 return false;
108 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800109 }
110 }
111 return true;
112}