aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Embedded_SW/Embedded/Drivers/I2C_Communication/I2C_FIFO.c
blob: b72e23576f129fc6b93de488becfcdadf72db351 (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * I2C_FIFO.c
 *
 *  Created on: Jan 2, 2020
 *      Author: avi
 *      https://cryptography.gmu.edu:4443/XBX/xbh/blob/02a7edc0a62a7ab48341ca5b34de07eb7bf1c609/hal/i2c.c
 */

#include <stdint.h>
#include <stdbool.h>
#include "include.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/tm4c1294ncpdt.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/i2c.h"

#define MAX_FIFO_BURST 8
#define I2C_BUSY_DELAY 5000
///
/**
 * Flushes I2C fifos
 * @param base Base address of I2C transceiver
 */
void i2c_flush(uint32_t base){
    I2CTxFIFOFlush(base);
    I2CRxFIFOFlush(base);
}

/**
 * Sets up fifos and clock for I2C. Does not configure pins
 * @param base Base address of I2C transceiver
 * @param highspeed True if 400kbit, else 100kbit
 */
void i2c_fifo_setup(uint32_t base) {
    I2CTxFIFOConfigSet(base, I2C_FIFO_CFG_TX_MASTER | I2C_FIFO_CFG_TX_TRIG_3);
    I2CRxFIFOConfigSet(base, I2C_FIFO_CFG_RX_MASTER | I2C_FIFO_CFG_RX_TRIG_2);
    I2CMasterGlitchFilterConfigSet(base, I2C_MASTER_GLITCH_FILTER_8);
    i2c_flush(base);
}

uint32_t I2C_BusyWithTimeout(uint32_t base)
{
    uint32_t count = 0;
    while(I2CMasterBusy(base) && (count++ < 10)) {
        SysCtlDelay(I2C_BUSY_DELAY);
        if(count > 10) {
            return I2C_MASTER_ERR_CLK_TOUT;
        }
    }
    return 0;
}

/**
 * Writes array over I2C to address given
 * @param base Base address of I2C transceiver
 * @param addr Address of I2C device to write to
 * @param data Data to write
 * @param len Length of data
 * @return 0 if success, else value of I2CMasterErr
 */
uint32_t I2C_WriteFifo(uint32_t base, uint8_t addr, uint8_t *data, uint32_t len){
    uint32_t offset = 0;
    uint32_t len_mod = len % MAX_FIFO_BURST;
    uint32_t final_burst = (len_mod !=0 )? len_mod : MAX_FIFO_BURST;
    uint32_t i, err;

    // Send configuration to INA219 config register
    I2CMasterSlaveAddrSet(base, addr, false);

    for(offset = 0; offset < (len-1)/MAX_FIFO_BURST; offset++){
        I2CMasterBurstLengthSet(base, MAX_FIFO_BURST);
        for(i = 0; i < MAX_FIFO_BURST; ++i){
            I2CFIFODataPutNonBlocking(base, *data++);
        }
        if( 0 == offset){
            I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_SEND_START);
        }else{
            I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_SEND_CONT);
        }
    }
    I2CMasterBurstLengthSet(base, final_burst);
    for(i = 0; i < final_burst; ++i){
        I2CFIFODataPutNonBlocking(base, *data++);
    }
    if(len <= MAX_FIFO_BURST){
        I2CMasterControl(base, I2C_MASTER_CMD_FIFO_SINGLE_SEND);
    }else{
        I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH);
    }
    if((err = I2C_BusyWithTimeout(base)) != 0) {
        return err;
    } else {
        err = I2CMasterErr(base);
    }
    return err;
}

uint32_t I2C_ReadFifo(uint32_t base, uint8_t addr, uint8_t *data, uint32_t len) {
    uint32_t len_mod = len % MAX_FIFO_BURST;
    uint32_t final_burst = (len_mod !=0 )? len_mod : MAX_FIFO_BURST;
    uint32_t i, offset, err;

    // Send configuration to INA219 config register
    I2CRxFIFOFlush(base);
    I2CMasterSlaveAddrSet(base, addr, true);
    for(offset = 0; offset < len/MAX_FIFO_BURST; offset++) {
        I2CMasterBurstLengthSet(base, MAX_FIFO_BURST);

        if(0 == offset) {
            I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START);
        } else {
            I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_CONT);
        }
        if((err = I2C_BusyWithTimeout(base)) != 0)
            return err;
        for(i = 0; i < MAX_FIFO_BURST; ++i) {
            I2CFIFODataGetNonBlocking(base, data++);
        }
    }

    I2CMasterBurstLengthSet(base, final_burst);
    if(len <= MAX_FIFO_BURST){
        I2CMasterControl(base, I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE);
    } else {
        I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH);
    }
    if((err = I2C_BusyWithTimeout(base)) != 0)
        return err;
    for(i = 0; i < final_burst; ++i) {
        I2CFIFODataGetNonBlocking(base, data++);
    }
    err = I2CMasterErr(base);
    return err;
}

/*
void i2c_comm_setup(void){
    // Configure I2C pins
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1);
    GPIOPinConfigure(GPIO_PG0_I2C1SCL);
    GPIOPinConfigure(GPIO_PG1_I2C1SDA);
    GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_0);
    GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_1);

    // Configure I2C master and fifos, and flush fifos
    i2c_setup(I2C2_BASE, true);
}
*/