mbd2pmd Web Server uses the mbd2pmd adapter board to serve files from a microSD card and provide a RESTful interface to the Pmod connector.
Dependencies: EthernetInterface MAX14661 PmodInterface SDFileSystem mbd2pmd mbed-rtos mbed
Fork of MBD2PMD_WebServer by
Revision 4:7fdb64fe6419, committed 2014-04-29
- Comitter:
- gsteiert
- Date:
- Tue Apr 29 04:46:29 2014 +0000
- Parent:
- 3:4f71a37a1ed2
- Child:
- 5:892b329134ca
- Commit message:
- mbd2pmd WebServer; Added abstraction to /m mux command to enable compatibility with ard2pmd. Added lookup tables with mux pin mapping.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAX14661.lib Tue Apr 29 04:46:29 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/gsteiert/code/MAX14661/#c3525ee2d636
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PmodInterface/PmodInterface.cpp Tue Apr 29 04:46:29 2014 +0000 @@ -0,0 +1,198 @@ +/* Pmod Interface Library + * + */ + +#include "mbed.h" +#include "PmodInterface.h" + +PmodInterface::PmodInterface() +{ +} + +PmodInterface::~PmodInterface() +{ +} + +// Initialize PmodInterface +void PmodInterface::init(DigitalInOut **dio, I2C* i2c, MAX14661* mux, const int* mux_a, const int* mux_p) +{ + _pmd = dio; // save pointer to digital IO + _i2c = i2c; // save pointer to I2C interface + _mux = mux; // save pointer to multiplexer + _mux_a = mux_a; // save pointer to mux micro LUT + _mux_p = mux_p; // save pointer to mux pmod LUT +} + +/* Digital I/O + * /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 command: + * bit 0 - pin state to write + * bit 1 - pin state write disable + * bit 2 - pin direction + * bit 3 - pin direction write enable + * bit 4 - pin pullup state + * bit 5 - pin pullup write enable + */ +void PmodInterface::fnc_dio(char* resp) +{ + if (_args[0] < 1) { + sprintf(resp, "!args"); + } else { + if (_args[1] > 7) { + sprintf(resp, "!pin"); + } else { + if (_args[0] < 2) { + sprintf(resp,"%d", (*_pmd[_args[1]]).read()); + } else { + if (!(_args[2] & DB_OWD)) { + if (_args[2] & DB_OUT) { + (*_pmd[_args[1]]).write(1); + sprintf(resp++, "H"); + } else { + (*_pmd[_args[1]]).write(0); + sprintf(resp++, "L"); + } + } + if (_args[2] & DB_DWE) { + if (_args[2] & DB_DIR) { + (*_pmd[_args[1]]).output(); + sprintf(resp++, "O"); + } else { + (*_pmd[_args[1]]).input(); + sprintf(resp++, "I"); + } + } + if (_args[2] & DB_PWE) { + if (_args[2] & DB_PU) { + (*_pmd[_args[1]]).mode(PullUp); + sprintf(resp++, "U"); + } else { + (*_pmd[_args[1]]).mode(PullNone); + sprintf(resp++, "N"); + } + } + } + } + } +} + +/* 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 + */ +void PmodInterface::fnc_i2c(char* resp) +{ + int dcnt=0; + if (_args[IA_CNT] < 2) { + sprintf(resp, "!args"); + } else { + if (_args[IA_ADD] & 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, "!write"); + resp +=6; + } + } + if ((*_i2c).read(_args[IA_ADD], _dbuf, _args[IA_DATA])!=0) { + sprintf(resp, "!read"); + } else { + for (dcnt = 0; dcnt < _args[IA_DATA]; dcnt++) { + sprintf(resp,"0x%02x/", _dbuf[dcnt]); + resp +=5; + } + *(--resp) = '\0'; + } + } 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, "!write"); + } + } + } +} + +/* Multiplexer + * /m/[pa]/[ma]/[pb]/[mb] Set multiplexer channels A and B + * [pa][pb] int from 0 to 7 representint pmod pin + * [ma][mb] int from 0 to 15 representing micro pin + */ +void PmodInterface::fnc_mux(char* resp) +{ + if (_args[0] !=4) { + sprintf(resp, "0x%08X", (*_mux).read()); + } else { + int chA = _mux_p[_args[1]] + _mux_a[_args[2]]; + int chB = _mux_p[_args[3]] + _mux_a[_args[4]]; + (*_mux).setAB(chA, chB); + sprintf(resp, "A: 0x%04x, B: 0x%04x", chA, chB); + } +} + + +/* SPI + * TBD + */ +void PmodInterface::fnc_spi(char* resp) +{ + if (_args[0] < 1) { + sprintf(resp, "!args"); + } else { + sprintf(resp, "spi tbd"); + } +} + +void PmodInterface::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 'd': + case 'D': + fnc_dio(output); + break; + case 'i': + case 'I': + fnc_i2c(output); + break; + case 'm': + case 'M': + fnc_mux(output); + break; + case 's': + case 'S': + fnc_spi(output); + break; + default: + sprintf(output, "!commands: dio i2c mux pwm spi"); + break; + } + } else { + sprintf(output, "!format: /cmd/arg1/arg2..."); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PmodInterface/PmodInterface.h Tue Apr 29 04:46:29 2014 +0000 @@ -0,0 +1,123 @@ +/* Pmod Interface Library + * + */ +#ifndef PMODINTERFACE_H +#define PMODINTERFACE_H + +#include "mbed.h" +#include "PmodInterface.h" +#include "mbd2pmd.h" + +/** RAPC Library, Provides utilities for remotely accessing peripherals + * + * Example: + * @code + * // Configure board to pass UART signals to peripheral connector. + * + * #include "PmodInterface.h" + * + * PmodInterface pInt(PTD0, PTD2, PTD3, PTD1, + * PTA4, PTA5, PTC8, PTC9, + * PTA12, PTE0, PTE1 + * ); + * + * int main() { + * char ibuf[256]; + * char obuf[256]; + * pInt.init(); + * while(1) { + * scanf("%s", ibuf); + * pInt.call(ibuf, obuf); + * printf("%s=", ibuf); + * printf("%s\n", obuf); + * } + * @endcode + */ +class PmodInterface +{ +public: + + /** Create a PmodInterface interface + * + */ + PmodInterface(); + + ~PmodInterface(); + + /** Name the DIO bits + */ + enum PINTdioBits { + DB_OUT = 0x01, /**< Pin Output State Bit */ + DB_OWD = 0x02, /**< Output Write Disable, set to block writing the output state */ + DB_DIR = 0x04, /**< Pin Direction, 0 = Input, 1 = Output */ + DB_DWE = 0x08, /**< Direction Write Enable, set this bit to write the direction */ + DB_PU = 0x10, /**< Pull Up State, 0 = PullNone, 1 = PullUp */ + DB_PWE = 0x20, /**< Pull Up Write Enable, set this bit to write the pull up state */ + }; + + /** Name the I2C arguments + */ + enum PINTi2cArgs { + IA_CNT = 0, /**< Argument Count */ + IA_ADD, /**< Device Address */ + IA_DATA, /**< Data, Read = # bytes to read, Write = first data byte */ + IA_RDDA /**< Read Data, data to write prior to read */ + }; + + /** Initialize the digital pins and PWM + * + */ + void init(DigitalInOut *dio[], I2C* i2c, MAX14661* mux, const int* mux_a, const int* mux_p); + + /** Process Remote Arduino Peripheral Module Command + * + * @param input a pointer to the string containing the command + * @param output a pointer to the string to write the result + */ + void call(char* input, char* output); + +private: + + // Internal Functions + + /** Process Digital I/O Command + * + * @param resp a pointer to the string to write the result + */ + void fnc_dio(char* resp); + + /** Process I2C Command + * + * @param resp a pointer to the string to write the result + */ + void fnc_i2c(char* resp); + + /** Process Multiplexer Command + * + * @param resp a pointer to the string to write the result + */ + void fnc_mux(char* resp); + + + /** Process SPI Command + * + * @param resp a pointer to the string to write the result + */ + void fnc_spi(char* resp); + + // Internal Resources + I2C *_i2c; + MAX14661 *_mux; + const int *_mux_a; // mux micro map LUT + const int *_mux_p; // mux pmod map LUT + + // Array of pointers to the DIO pins + DigitalInOut **_pmd; + + // Internal Buffers + int _args[32]; + char _dbuf[64]; + +}; + +#endif \ No newline at end of file
--- a/main.cpp Sat Apr 19 05:26:40 2014 +0000 +++ b/main.cpp Tue Apr 29 04:46:29 2014 +0000 @@ -1,6 +1,6 @@ #include "mbed.h" #include "EthernetInterface.h" -#include "SDFileSystem.h" +#include "PmodInterface.h" #include <stdio.h> #include <string.h> @@ -9,11 +9,16 @@ #define HTTPD_MAX_HDR_LENGTH 255 #define HTTPD_MAX_FNAME_LENGTH 127 #define HTTPD_MAX_DNAME_LENGTH 127 +#define CGI_MAX_RESP_LENGTH 127 +#define UART_MAX_CMD_LENGTH 127 Serial uart(USBTX, USBRX); +I2C i2c(p28, p27); +mbd2pmd m2p; +PmodInterface pInt; //SDFileSystem sd(p5, p6, p7, p8, "sd"); // LPC1768 MBD2PMD -SDFileSystem sd(P0_18, P0_17, P0_15, P0_16, "sd"); // Seeeduino Arch Pro SPI2SD +//SDFileSystem sd(P0_18, P0_17, P0_15, P0_16, "sd"); // Seeeduino Arch Pro SPI2SD EthernetInterface eth; TCPSocketServer server; @@ -23,6 +28,8 @@ char httpHeader[HTTPD_MAX_HDR_LENGTH+1]; char fileName[HTTPD_MAX_FNAME_LENGTH+1]; char dirName[HTTPD_MAX_DNAME_LENGTH+1]; +char obuf[CGI_MAX_RESP_LENGTH+1]; +char ibuf[UART_MAX_CMD_LENGTH+1]; char *uristr; char *eou; char *qrystr; @@ -80,11 +87,51 @@ } } +void get_cgi(char* uri) +{ + pInt.call(uri, obuf); + sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n"); + client.send(httpHeader,strlen(httpHeader)); + client.send(obuf,strlen(obuf)); + uart.printf("resp: %s", obuf); +} + +void uart_cmd_thread(void const *args) +{ + int i = 0; + while(true) { + if (uart.readable()) { + ibuf[i]=uart.getc(); + if (ibuf[i]!='\r') { + if (i < 255) { + i += 1; + } + } else { + if (i < 255) { + ibuf[i]=0; + uart.printf("UART CMD: %s=", ibuf); + pInt.call(ibuf, obuf); + uart.printf("%s\n", obuf); + } else { + uart.printf("UART Input Command Too Long\n"); + } + i=0; + } + } + } +} + int main (void) { -// Serial Interface eth; +// Serial Interface Setup; uart.baud(115200); - uart.printf("RAPM Serial Started\n"); + uart.printf("mbd2pmd Serial Started\n"); + +// Mbed to Pmod Initialization; + m2p.init(); + +// Pmod Interface Setup + pInt.init(&m2p.pmd[0], &i2c, &m2p.mux, m2p.mux_a, m2p.mux_p); // Check File System DIR *d = opendir("/sd/"); @@ -102,7 +149,11 @@ // TCPSocketServer server; server.bind(HTTPD_SERVER_PORT); server.listen(); - uart.printf("RAPM Server Listening\n"); + uart.printf("mbd2pmd Server Listening\n"); + +// Start UART Command Thread + Thread thread(uart_cmd_thread); + uart.printf("UART Commands Listening\n"); while (true) { uart.printf("\nWait for new connection...\r\n"); @@ -131,7 +182,11 @@ client.send(buffer,n); } else { *eou = 0; - get_file(uristr); + if (!strncmp(uristr, "/cgi/", 5)) { + get_cgi(uristr+4); + } else { + get_file(uristr); + } } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbd2pmd/mbd2pmd.cpp Tue Apr 29 04:46:29 2014 +0000 @@ -0,0 +1,37 @@ +/* mbd2pmd Board Driver Library + * + */ + +#include "mbed.h" +#include "mbd2pmd.h" + +mbd2pmd::mbd2pmd() : + mux(p28, p27), sd(p5, p6, p7, p8, "sd"), + pa1(p14), pa2(p11), pa3(p12), pa4(p13), + pb1(p24), pb2(p23), pb3(p22), pb4(p21) +{ +} + +mbd2pmd::~mbd2pmd() +{ +} + +const int mbd2pmd::mux_a[16] = {RX, TX, RD, PWM1, PB1, PB2, PB3, PB4, TD, PWM2, PA1, PA2, PA3, PA4, SDA, SCL}; +const int mbd2pmd::mux_p[8] = {PA1, PA2, PA3, PA4, PB1, PB2, PB3, PB4}; + +// Initialize Digital IO to inputs with no pullups +void mbd2pmd::init() +{ + pmd[0] = &pa1; + pmd[1] = &pa2; + pmd[2] = &pa3; + pmd[3] = &pa4; + pmd[4] = &pb1; + pmd[5] = &pb2; + pmd[6] = &pb3; + pmd[7] = &pb4; + for (int i=0; i < 8; i++) { + (*pmd[i]).mode(PullNone); + (*pmd[i]).input(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbd2pmd/mbd2pmd.h Tue Apr 29 04:46:29 2014 +0000 @@ -0,0 +1,91 @@ +/* mbd2pmd Board Driver Library + * + */ + +#ifndef MBD2PMD_H +#define MBD2PMD_H + +#include "mbed.h" +#include "SDFileSystem.h" +#include "MAX14661.h" + +/** mbd2pmd Library, Provides utilities for configuring the mbd2pmd Board + * + * Example: + * @code + * // Configure board to pass UART signals to peripheral connector. + * + * #include "mbd2pmd.h" + * + * mbd2pmd m2p; + * + * int main() { + * m2p.mux.setAB((mbd2pmd::RX | mbd2pmd::PA3), (mbd2pmd::TX | mbd2pmd::PA2)); + * } + * @endcode + */ +class mbd2pmd +{ +public: + + /** Create a mbd2pmd interface + * + */ + mbd2pmd(); + + ~mbd2pmd(); + + /** Initialize the digital pins and PWM + * + */ + void init(); + + /** mbd2pmd resources SD card, mux, digital IO + */ + SDFileSystem sd; + MAX14661 mux; + DigitalInOut pa1; + DigitalInOut pa2; + DigitalInOut pa3; + DigitalInOut pa4; + DigitalInOut pb1; + DigitalInOut pb2; + DigitalInOut pb3; + DigitalInOut pb4; + + /** Array of pointers to the DIO pins + */ + DigitalInOut *pmd[8]; + + /** LUT for multiplexer micro connections + */ + static const int mux_a[16]; + + /** LUT for multiplexer PMOD connections + */ + static const int mux_p[8]; + + /** Name the multiplexer connections + */ + enum MUXsignals { + PWM1 = MAX14661::SW01, /**< (1<<0) PWM */ + PWM2 = MAX14661::SW02, /**< (1<<1) PWM */ + SCL = MAX14661::SW03, /**< (1<<2) I2C Clock */ + SDA = MAX14661::SW04, /**< (1<<3) I2C Data */ + TD = MAX14661::SW05, /**< (1<<4) CAN Transmit */ + RD = MAX14661::SW06, /**< (1<<5) CAN Receive */ + TX = MAX14661::SW07, /**< (1<<6) UART Transmit */ + RX = MAX14661::SW08, /**< (1<<7) UART Receive */ + PA1 = MAX14661::SW09, /**< (1<<8) Pmd row A pin 1 */ + PB1 = MAX14661::SW10, /**< (1<<9) Pmd row B pin 1 */ + PA2 = MAX14661::SW11, /**< (1<<10) Pmd row A pin 2 */ + PB2 = MAX14661::SW12, /**< (1<<11) Pmd row B pin 2 */ + PA3 = MAX14661::SW13, /**< (1<<12) Pmd row A pin 3 */ + PB3 = MAX14661::SW14, /**< (1<<13) Pmd row B pin 3 */ + PA4 = MAX14661::SW15, /**< (1<<14) Pmd row A pin 4 */ + PB4 = MAX14661::SW16 /**< (1<<15) Pmd row B pin 4 */ + }; + +}; + +#endif \ No newline at end of file