summaryrefslogtreecommitdiff
path: root/include/sensorI2C.hpp
blob: bd497a5c3ea7208127e6e4cedff0a97d19ef7bd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#pragma once

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <cstdint>
#include <string>

class sensorI2C {
    

    //Predominantly used for I2C handler functions; implement high-level functions in sensor classes
    //Implemented as a combination of Jazz' implementation and Derek Malloy's code
    public:
        
        //Initial single byte write, used at beginning of read operation
        //Returns 0 if successful, -1 if not
        int initialWrite(unsigned char registerAddress) {
            unsigned char *convertedAddressBuffer = new unsigned char[1];
            convertedAddressBuffer[0] = registerAddress;
            //Expect 1 byte response from 1 byte write
            if (write(i2c_bus, convertedAddressBuffer, 1) != 1) {
                fprintf(stderr, "ERROR DOING INITIAL READ TRANSACTION WRITE TO REGISTER %x FOR DEVICE %x\n", registerAddress, deviceAddress);
                return 0;
            }
            return 1;
        }

        int writeRegister(unsigned char registerAddress, unsigned char value) {
            //initialWrite() not used here because it's easier to just pack it into one buffer for file writing
            unsigned char writeBuffer[2];
            writeBuffer[0] = registerAddress;
            writeBuffer[1] = value;

            //Expect 2 byte output
            if (write(i2c_bus, writeBuffer, 2) != 2) {
                //These error messages are kind of obtuse but I'd rather have too much information than not enough
                fprintf(stderr, "ERROR WRITING %x TO REGISTER %x ON DEVICE %x\n", value, registerAddress, deviceAddress);
                return -1;
            }
            return 0;
        }

        //Could probably be uint8_t but Derek Malloy does it with unsigned chars and that's what worked during testing so I don't want to touch it
        unsigned char readSingleRegister(unsigned char registerAddress) {
            printf("reg addr: %X\n", registerAddress);

            initialWrite(registerAddress);
            unsigned char* readBuffer = new unsigned char[1];
            if (read(i2c_bus, readBuffer, 1) != 1){
                fprintf(stderr, "FAILED TO READ VALUE FROM REGISTER %x ON DEVICE %x\n", registerAddress, deviceAddress);
                return -1;
            }
            printf("readBuffer: %X\n", readBuffer[0]);
            return readBuffer[0];
        }

        unsigned char* readMultipleRegisters(unsigned char startingRegisterAddress, int numberOfRegisters) {            
            initialWrite(startingRegisterAddress);
            unsigned char* readBuffer = new unsigned char[numberOfRegisters];
            if (read(i2c_bus, readBuffer, numberOfRegisters) != numberOfRegisters) {
                fprintf(stderr, "ERROR TRYING TO READ %d REGISTERS STARTING AT ADDRESS %x ON DEVICE %x\n", 
                    numberOfRegisters, startingRegisterAddress, deviceAddress);
            }
            return readBuffer;
        }


        //Intakes device address and file 
        //Private because IT'S ASSUMED PROGRAMMER WILL CALL THIS METHOD DURING INIT() ROUTINE
        int setupI2C(std::string I2C_FILE) {
            // Open i2c driver file
            i2c_bus = open("/dev/i2c-2", O_RDWR);
            if(i2c_bus < 0){
                fprintf(stderr, "FAILED TO OPEN I2C BUS USING FILE %s\n", "/dev/i2c-2");
                close(i2c_bus);
                return -1;
            }

            // Identify slave device address (MODIFIED FROM INITIAL IMPLEMENTATION, USES INTERNAL deviceAddress INSTEAD OF PARAMETER)
            if(ioctl(i2c_bus, I2C_SLAVE, deviceAddress) < 0){
                fprintf(stderr, "FAILED TO CONNECT TO DEVICE AT ADDRESS %x VIA I2C\n", deviceAddress);
                close(i2c_bus);
                return -1;
            }
            return 0;
        }

        /**
         * @brief Initialize the sensor. 
         * 
         * @param data Data for initializing the sensor
         * 
         * @return true Initialization Success
         * @return false Initialization Failure
         */
        virtual bool init() = 0;

        unsigned char deviceAddress;
        int i2c_bus;
        std::string I2C_FILE;
};