Command processor to access I2C and SPI Takes URI coded commands and returns JSON array

Fork of SerialInterface by Greg Steiert

SerialInterface.cpp

Committer:
switches
Date:
2016-12-15
Revision:
7:06a2eb2483f6
Parent:
6:c9b7256c8261
Child:
9:f52181496512

File content as of revision 7:06a2eb2483f6:

/* Pmod Interface Library
 *
 */

#include "mbed.h"
#include "SerialInterface.h"

SerialInterface::SerialInterface(I2C &i2c, SPI &spi, DigitalInOut* gpio, AnalogIn* ain): _i2c(i2c), _spi(spi) 
{
    _gpio = gpio;  // save pointer to GPIO pins
    _ain = ain;  // save pointer to GPIO pins
}

SerialInterface::~SerialInterface()
{
}

/* Analog In
 * /a              read all
 * /a/[pin]        read from pin
 *   Returns 16bit normalized result
 */
void SerialInterface::fnc_ain(char* resp)
{
    switch (_args[0]) {
        case 0:
            sprintf(resp, "[0x%04X,0x%04X,0x%04X,0x%04X,0x%04X,0x%04X,0x%04X,0x%04X]", 
            _ain[0].read_u16(), _ain[1].read_u16(), _ain[2].read_u16(), _ain[3].read_u16(), 
            _ain[4].read_u16(), _ain[5].read_u16(), _ain[6].read_u16(), _ain[7].read_u16() );
            break;
        case 1:
            sprintf(resp, "[0x%04X]", _ain[_args[1]].read_u16());
            break;
        default:
            sprintf(resp, "[-1]");
            break;
    }
}

/* Digital I/O
 * /d              read all
 * /d/[pin]        read from pin
 * /d/[pin]/[cfg]  write configuration to pin
 * [pin] = number (from 0 to 7) of the pin to access
 * [cfg] = pin configuration:
 *     0 - output low
 *     1 - output high
 *     2 - input pull down
 *     3 - input pull up
 *     4 - input pull none
 */
void SerialInterface::fnc_dio(char* resp)
{
    int bdat;
    int bcnt;
    switch (_args[0]) {
        case 0:
            sprintf(resp, "[");
            resp +=1;
            for (bcnt = 0; bcnt < 8 ; bcnt++) {
                bdat = _gpio[bcnt].read();
                sprintf(resp, "%d,", bdat);
                resp +=2;
            }
            sprintf((resp-1), "]");
            break;
        case 1:
            if (_args[1] > 7) {
                sprintf(resp, "[-1]");
            } else {
                sprintf(resp,"[%d]", _gpio[_args[1]].read());
            }
            break;
        case 2:
            if (_args[1] > 7) {
                sprintf(resp, "[-1]");
            } else {
                if (_args[2] < 2) {
                    _gpio[_args[1]].write(_args[2]);
                    _gpio[_args[1]].output();
                } else {
                    if (_args[2] == 2) {
                        _gpio[_args[1]].mode(PullDown);
                    } else if (_args[2] == 3) {
                        _gpio[_args[1]].mode(PullUp);
                    } else {
                        _gpio[_args[1]].mode(PullNone);
                    }
                    _gpio[_args[1]].input();
                }
                sprintf(resp,"[%d]", _args[2]);
            }
            break;
        default:
            sprintf(resp, "[-1]");
            break;
    }
}

/* I2C
 * /i/[even]/[data]...       write
 * /i/[odd]/[cnt]/[data]...  read
 * [even] = even I2C address used for writes
 * [odd]  = odd I2C address used for reads
 * [data] = data to be writen, if data is included with a read, the data
 *     will be written prior to the read to set the register address
 * [cnt]  = number of bytes to read
 * returns data read in JSON array
 */
void SerialInterface::fnc_i2c(char* resp)
{
    int dcnt=0;
    if (_args[IA_CNT] < 2) {
        sprintf(resp, "[-1]");
    } else {
        if (_args[IA_ADD] & 1) {
            sprintf(resp, "[");
            resp +=1;
            if (_args[IA_CNT] > 2) {
                for (dcnt = 0; dcnt < (_args[IA_CNT] -2) ; dcnt++) {
                    _dbuf[dcnt] = _args[(dcnt +3)];
                }
                if (_i2c.write(_args[IA_ADD], _dbuf, dcnt, true) != 0) {
                    sprintf(resp, "-1,");
                    resp +=3;
                }
            }
            if (_i2c.read(_args[IA_ADD], _dbuf, _args[IA_DATA])!=0) {
                sprintf(resp, "-1]");
            } else {
                for (dcnt = 0; dcnt < _args[IA_DATA]; dcnt++) {
                    sprintf(resp,"0x%02X,", _dbuf[dcnt]);
                    resp +=5;
                }
                sprintf((resp-1), "]");
            }
        } else {
            for (dcnt = 0; dcnt < (_args[IA_CNT] -1) ; dcnt++) {
                _dbuf[dcnt] = _args[(dcnt +2)];
            }
            if (_i2c.write(_args[IA_ADD], _dbuf, dcnt) == 0) {
                sprintf(resp,"[%d]", dcnt);
            } else {
                sprintf(resp, "[-1]");
            }
        }
    }
}

/* SPI
 * /s/[cfg]/[data]...      read+write
 * [cfg] = SPI configuration specifies gpio to use for chip
 *   select and other SPI parameters:
 *   0x[Byte3][Byte2][Byte1][Byte0]
 *     Byte3 = SCK frequency in MHz (0 = no change)
 *     Byte2 = Format:
 *       0 = no change
 *       1 = Mode 1
 *       2 = Mode 2
 *       3 = Mode 3
 *       4 = Mode 0
 *     Byte1 = CS polarity 1 = active high, 0 = active low
 *     Byte0 = GPIO to use for CS (0-7)
 *       0 = P5_3
 *       1 = P5_4
 *       2 = P5_5
 *       3 = P5_6
 *       4 = P3_0
 *       5 = P3_1
 *       6 = P3_2
 *       7 = P3_3
 * [data] = data to be writen
 *   this shifts out each data byte provided and
 *   returns each byte read in a JSON array
 */
void SerialInterface::fnc_spi(char* resp)
{
    int dcnt=1;
    int dataIn;
    spiConfig_t spiCfg;
    if (_args[0] < 1) {
        sprintf(resp, "[-1]");
    } else {
        spiCfg.merged = _args[1];
        if (spiCfg.freq) {
            _spi.frequency(spiCfg.freq * 1000000);
        }
        if (spiCfg.format) {
            _spi.format(8, (spiCfg.format & 3));
        }
        if (_args[0] > 1) {
            sprintf(resp, "[");
            resp++;
            _gpio[spiCfg.csPin] = (spiCfg.csPol);
            while(dcnt < _args[0]) {
                dcnt++;
                dataIn = _spi.write(_args[dcnt]);
                sprintf(resp, "0x%02X,", dataIn);
                resp += 5;
            }
            _gpio[spiCfg.csPin] = !(spiCfg.csPol);
            sprintf((resp-1), "]");
        }
    }
}

void SerialInterface::call(char* input, char* output)
{
    char cmd;
    _args[0] = 0;
    if (*input == '/') {
        input++;
        cmd = *input;
        input = strchr(input, '/');
        while (*input == '/') {
            input++;
            _args[(_args[0]+1)] = strtol(input, &input, 0);
            if (input) {
                _args[0]++;
            }
        }
        switch (cmd) {
            case 'a':
            case 'A':
                fnc_ain(output);
                break;
            case 'd':
            case 'D':
                fnc_dio(output);
                break;
            case 'i':
            case 'I':
                fnc_i2c(output);
                break;
            case 's':
            case 'S':
                fnc_spi(output);
                break;
            default:
                sprintf(output, "!commands: ain dio i2c spi");
                break;
        }
    } else {
        sprintf(output, "!format:  /cmd/arg1/arg2...");

    }
}