| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /*
- * sc03mpd.c
- *
- * Created on: Jul 12, 2022
- * Author: jylew
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "sc03mpd/sc03mpd.h"
- #define SC03MPD_UTL_NUSD(v) (void)(v)
- #define SC03MPD_UTL_V_HI(v) ((uint8_t)(((v) & 0xFF00) >> 8))
- #define SC03MPD_UTL_V_LO(v) ((uint8_t)(((v) & 0x00FF) >> 0))
- #define VC0706_PSN_REQ (0x56)
- #define VC0706_PSN_REP (0x76)
- #define SC03MPD_CMD_BDR (0x24) // SET BAUD RATE
- #define SC03MPD_CMD_RST (0x26) // RESET
- #define SC03MPD_CMD_CMP (0x31) // SET IMAGE COMPRESSION RATE
- #define SC03MPD_CMD_RES (0x31) // SET IMAGE RESOLUTION
- #define SC03MPD_CMD_CDB (0x31) // CHANGE DEFAULT BAUD RATE
- #define SC03MPD_CMD_IMG (0x32) // READ IMAGE DATA
- #define SC03MPD_CMD_LEN (0x34) // READ IMAGE DATA LENGTH
- #define SC03MPD_CMD_CTR (0x36) // CAPTURE IMAGE
- #define SC03MPD_CMD_STP (0x36) // STOP CAPTURE
- #define SC03MPD_CMD_CLR (0x3C) // COLOR CONTROL MODE AND SHOW MODE
- #define SC03MPD_PKT_REQ_LEN (4)
- #define SC03MPD_PKT_REP_LEN (5)
- #define SC03MPD_PKT_DAT_LEN (16)
- #define SC03MPD_PKT_MAX_MTU (SC03MPD_PKT_REP_LEN + SC03MPD_PKT_DAT_LEN)
- #pragma pack(push, 1)
- typedef struct
- {
- uint8_t psn; // Protocol Sign
- uint8_t dsn; // Device Serial Number
- uint8_t cmd; // Command
- uint8_t len; // Data length
- uint8_t dat[0];
- }
- sc03mpd_req_t;
- typedef struct
- {
- uint8_t psn; // Protocol Sign
- uint8_t dsn; // Device Serial Number
- uint8_t cmd; // Command
- uint8_t sts; // Status
- uint8_t len; // Data length
- uint8_t dat[0];
- }
- sc03mpd_rep_t;
- typedef union
- {
- sc03mpd_req_t req_hdr;
- sc03mpd_rep_t rep_hdr;
- uint8_t pkt_buf[SC03MPD_PKT_MAX_MTU];
- }
- sc03mpd_transaction_t;
- #pragma pack(pop)
- typedef void (*sc03mpd_cmd_builder)(sc03mpd_transaction_t*, uint16_t, uint16_t);
- static void sc03mpd_init_trx(sc03mpd_transaction_t* trx, uint8_t cmd, uint8_t len)
- {
- trx->req_hdr.psn = VC0706_PSN_REQ;
- trx->req_hdr.dsn = SC03MPD_DSN_DEF;
- trx->req_hdr.cmd = cmd;
- trx->req_hdr.len = len;
- }
- static void sc03mpd_build_rst(sc03mpd_transaction_t* trx, uint16_t arg0, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg0);
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_RST, 0);
- }
- static void sc03mpd_build_bdr(sc03mpd_transaction_t* trx, uint16_t baud, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_BDR, 3);
- trx->req_hdr.dat[0] = 0x01;
- trx->req_hdr.dat[1] = SC03MPD_UTL_V_HI(baud);
- trx->req_hdr.dat[2] = SC03MPD_UTL_V_LO(baud);
- }
- static void sc03mpd_build_cdb(sc03mpd_transaction_t* trx, uint16_t baud, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_CDB, 6);
- trx->req_hdr.dat[0] = 0x04;
- trx->req_hdr.dat[1] = 0x02;
- trx->req_hdr.dat[2] = 0x00;
- trx->req_hdr.dat[3] = 0x08;
- trx->req_hdr.dat[4] = SC03MPD_UTL_V_HI(baud);
- trx->req_hdr.dat[5] = SC03MPD_UTL_V_LO(baud);
- }
- static void sc03mpd_build_cmp(sc03mpd_transaction_t* trx, uint16_t cmpr, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_CMP, 5);
- trx->req_hdr.dat[0] = 0x01;
- trx->req_hdr.dat[1] = 0x01;
- trx->req_hdr.dat[2] = 0x12;
- trx->req_hdr.dat[3] = 0x04;
- trx->req_hdr.dat[4] = (uint8_t)cmpr;
- }
- static void sc03mpd_build_res(sc03mpd_transaction_t* trx, uint16_t resn, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_RES, 5);
- trx->req_hdr.dat[0] = 0x04;
- trx->req_hdr.dat[1] = 0x01;
- trx->req_hdr.dat[2] = 0x00;
- trx->req_hdr.dat[3] = 0x19;
- trx->req_hdr.dat[4] = (uint8_t)resn;
- }
- static void sc03mpd_build_ctr(sc03mpd_transaction_t* trx, uint16_t arg0, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg0);
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_CTR, 1);
- trx->req_hdr.dat[0] = 0x00;
- }
- static void sc03mpd_build_stp(sc03mpd_transaction_t* trx, uint16_t arg0, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg0);
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_STP, 1);
- trx->req_hdr.dat[0] = 0x03; /* in case of two images capture, this parameter should be 0x02 */
- }
- static void sc03mpd_build_len(sc03mpd_transaction_t* trx, uint16_t arg0, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg0);
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_LEN, 1);
- trx->req_hdr.dat[0] = 0x00;
- }
- static void sc03mpd_build_img(sc03mpd_transaction_t* trx, uint16_t addr, uint16_t size)
- {
- sc03mpd_init_trx(trx, SC03MPD_CMD_IMG, 12);
- trx->req_hdr.dat[ 0] = 0x00;
- trx->req_hdr.dat[ 1] = 0x0A;
- trx->req_hdr.dat[ 2] = 0x00;
- trx->req_hdr.dat[ 3] = 0x00;
- trx->req_hdr.dat[ 4] = SC03MPD_UTL_V_HI(addr);
- trx->req_hdr.dat[ 5] = SC03MPD_UTL_V_LO(addr);
- trx->req_hdr.dat[ 6] = 0x00;
- trx->req_hdr.dat[ 7] = 0x00;
- trx->req_hdr.dat[ 8] = SC03MPD_UTL_V_HI(size);
- trx->req_hdr.dat[ 9] = SC03MPD_UTL_V_LO(size);
- trx->req_hdr.dat[10] = 0x00;
- trx->req_hdr.dat[11] = 0x0A;
- }
- static void sc03mpd_build_clr(sc03mpd_transaction_t* trx, uint16_t showMode, uint16_t arg1)
- {
- SC03MPD_UTL_NUSD(arg1);
- sc03mpd_init_trx(trx, SC03MPD_CMD_CLR, 2);
- trx->req_hdr.dat[0] = 0x01;
- trx->req_hdr.dat[1] = (uint8_t)showMode;
- }
- static int32_t sc03mpd_do_transaction(sc03mpd_ifx_t* ifx, sc03mpd_transaction_t* trx, sc03mpd_cmd_builder builder, uint16_t arg0, uint16_t arg1)
- {
- builder(trx, arg0, arg1);
- uint8_t dsn = trx->req_hdr.dsn;
- uint8_t cmd = trx->req_hdr.cmd;
- uint8_t txn = sizeof(sc03mpd_req_t) + trx->req_hdr.len;
- uint8_t rxn = sizeof(sc03mpd_rep_t);
- if (ifx->sendif(ifx, trx->pkt_buf, txn) != txn)
- return VC0706_STS_ECOM;
- if (ifx->recvif(ifx, trx->pkt_buf, rxn) != rxn)
- return VC0706_STS_ECOM;
- if (trx->rep_hdr.dsn != dsn) return VC0706_STS_ECOM;
- if (trx->rep_hdr.cmd != cmd) return VC0706_STS_ECOM;
- if (trx->rep_hdr.psn != VC0706_PSN_REP ) return VC0706_STS_ECOM;
- if (trx->rep_hdr.sts != VC0706_STS_ENON) return -((int32_t)trx->rep_hdr.sts);
- uint8_t rxd = trx->rep_hdr.len;
- if (rxd > 0)
- {
- if (ifx->recvif(ifx, &trx->pkt_buf[rxn], rxd) != rxd)
- return VC0706_STS_ECOM;
- }
- return VC0706_STS_ENON;
- }
- static int32_t sc03mpd_validate_baud(uint16_t baud)
- {
- switch (baud)
- {
- case SC03MPD_BDR_9600 :
- case SC03MPD_BDR_19200 :
- case SC03MPD_BDR_38400 :
- case SC03MPD_BDR_56700 :
- case SC03MPD_BDR_115200: return 0;
- }
- return 1;
- }
- static int32_t sc03mpd_validate_ires(uint8_t ires)
- {
- switch (ires)
- {
- case SC03MPD_RES_640_480:
- case SC03MPD_RES_320_240:
- case SC03MPD_RES_160_120: return 0;
- }
- return 1;
- }
- static int32_t sc03mpd_validate_clr(uint8_t clr)
- {
- switch (clr)
- {
- case SC03MPD_CLR_AUTO:
- case SC03MPD_CLR_COLOR:
- case SC03MPD_CLR_BW: return 0;
- }
- return 1;
- }
- int32_t sc03mpd_reset(sc03mpd_ifx_t* ifx)
- {
- sc03mpd_transaction_t trx;
- if (sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_rst, 0, 0))
- return VC0706_STS_ECOM;
- // Some ASCII string follows after vc0706 response.
- uint8_t dbuf[192] = { 0, };
- int32_t nrxd = 0;
- int32_t accq = 0;
- int32_t rest = sizeof(dbuf) - 1;
- while (rest > 0)
- {
- if ((nrxd = ifx->recvif(ifx, &dbuf[accq], rest)) <= 0)
- break;
- accq += nrxd;
- rest -= nrxd;
- }
- #ifdef SHOW_RESET_RESULT
- printf("%s\n", dbuf);
- #endif
- return VC0706_STS_ENON;
- }
- int32_t sc03mpd_set_baud(sc03mpd_ifx_t* ifx, uint16_t baud, uint8_t save)
- {
- if (sc03mpd_validate_baud(baud))
- return VC0706_STS_EFMT;
- sc03mpd_transaction_t trx;
- sc03mpd_cmd_builder builder = (save)? sc03mpd_build_cdb : sc03mpd_build_bdr;
- return sc03mpd_do_transaction(ifx, &trx, builder, baud, 0);
- }
- int32_t sc03mpd_set_icmp(sc03mpd_ifx_t* ifx, uint8_t cmpr)
- {
- sc03mpd_transaction_t trx;
- return sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_cmp, cmpr, 0);
- }
- int32_t sc03mpd_set_ires(sc03mpd_ifx_t* ifx, uint8_t ires)
- {
- if (sc03mpd_validate_ires(ires))
- return VC0706_STS_EFMT;
- sc03mpd_transaction_t trx;
- return sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_res, ires, 0);
- }
- int32_t sc03mpd_get_ilen(sc03mpd_ifx_t* ifx, uint16_t* length)
- {
- sc03mpd_transaction_t trx;
- if (sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_len, 0, 0))
- return VC0706_STS_ECOM;
- *length = ((uint16_t)trx.rep_hdr.dat[2] << 8) |
- ((uint16_t)trx.req_hdr.dat[3] << 0);
- return VC0706_STS_ENON;
- }
- int32_t sc03mpd_get_idat(sc03mpd_ifx_t* ifx, uint16_t addr, uint16_t size, uint8_t* dbuf)
- {
- if (dbuf == NULL) return VC0706_STS_EINT;
- if (size == 0 ) return VC0706_STS_EINT;
- sc03mpd_transaction_t trx;
- if (sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_img, addr, size))
- return VC0706_STS_ECOM;
- int32_t nrxd = 0;
- int32_t accq = 0;
- int32_t rest = size;
- while (rest > 0)
- {
- if ((nrxd = ifx->recvif(ifx, &dbuf[accq], rest)) <= 0)
- return VC0706_STS_ECOM;
- accq += nrxd;
- rest -= nrxd;
- }
- sc03mpd_rep_t res;
- if (ifx->recvif(ifx, (uint8_t*)&res, sizeof(res)) != sizeof(res))
- return VC0706_STS_ECOM;
- if (res.psn != trx.rep_hdr.psn) return VC0706_STS_ECOM;
- if (res.dsn != trx.rep_hdr.dsn) return VC0706_STS_ECOM;
- if (res.cmd != trx.rep_hdr.cmd) return VC0706_STS_ECOM;
- if (res.sts != trx.rep_hdr.sts) return VC0706_STS_ECOM;
- if (res.len != trx.rep_hdr.len) return VC0706_STS_ECOM;
- return VC0706_STS_ENON;
- }
- int32_t sc03mpd_capture(sc03mpd_ifx_t* ifx)
- {
- sc03mpd_transaction_t trx;
- return sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_ctr, 0, 0);
- }
- int32_t sc03mpd_stop(sc03mpd_ifx_t* ifx)
- {
- sc03mpd_transaction_t trx;
- return sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_stp, 0, 0);
- }
- int32_t sc03mpd_set_clr(sc03mpd_ifx_t* ifx, uint8_t showMode)
- {
- if (sc03mpd_validate_clr(showMode))
- return VC0706_STS_EFMT;
- sc03mpd_transaction_t trx;
- return sc03mpd_do_transaction(ifx, &trx, sc03mpd_build_clr, showMode, 0);
- }
|