diff --git a/F1:F103/Canon_managing_device/Readme.md b/F1:F103/Canon_managing_device/Readme.md index e6dfea7..4f77f30 100644 --- a/F1:F103/Canon_managing_device/Readme.md +++ b/F1:F103/Canon_managing_device/Readme.md @@ -1,36 +1,68 @@ # Canon lens management. -Management of some Canon Lens. +Management of some Canon Lens. Checked: EF85, EF200 and EF400. + +[Documentation about first "crack" methods](https://github.com/eddyem/canon-lens). ## Pinout -* PA4 - lens detect (zero active); -* PA5,6,7 - SPI SCK, MISO, MOSI; -* PA10 - USB DP pullup (zero active); +* PA4 - lens detect (low active); +* PA5,6,7 - SPI SCK, MISO (should have external pullup), MOSI; +* PA8 - enable lens power (high active); +* PA9 - !OC - overcurrent detected (low active); +* PA10 - USB DP pullup (low active); * PA11,12 - USB DM, DP; * PA13,14 - SWD IO, CLK; * PB8,9 - CAN Rx,Tx; * PC13 - USB/CAN (solder jumper to turn on CAN instead of USB, zero - CAN). -Protocol have a string form, each string ends with '\n'. You should wait an answer for previous command before sending next, -or have risk to miss all the rest commands in one packet. +## USB commands +Protocol have a string form, each string ends with '\n'. You should wait an answer for previous command before sending next, or have risk to miss all the rest commands in one packet. -## USB commands: +### Base commands -0 - move to smallest foc value (e.g. 2.5m) -1 - move to largest foc value (e.g. infinity) -d - open/close diaphragm by 1 step (+/-), open/close fully (o/c) (no way to know it current status) -f - get focus state or move it to given relative position -h - turn on hand focus management -i - get lens information -l - get lens model -r - get regulators' state - debugging commands: -F - change SPI flags (F f val), f== l-LSBFIRST, b-BR [18MHz/2^(b+1)], p-CPOL, h-CPHA -G - get SPI status -I - reinit SPI -R - software reset -S - send data over SPI -T - show Tms value +> **0** move to smallest foc value (e.g. 2.5m) +> **1** move to largest foc value (e.g. infinity) +> **a** move focus to given ABSOLUTE position or get current value (without number) + +> **d** open/close diaphragm by 1 step (+/-), open/close fully (o/c) (no way to know it current status) + +> **f** move focus to given RELATIVE position + +> **h** turn on hand focus management + +> **i** get lens information + +> **l** get lens model + +> **r** get regulators' state + +### Debugging or configuration commands + +> **A** set (!0) or reset (0) autoinit + +> **C** set CAN speed (25-3000 kbaud) + +> **D** set CAN ID (11 bit) + +> **E** erase full flash storage + +> **F** change SPI flags (F f val), f== l-LSBFIRST, b-BR [18MHz/2^(b+1)], p-CPOL, h-CPHA + +> **G** get SPI status + +> **I** reinit SPI + +> **L** 'flood' message (same as `S` but every 250ms until next command) + +> **P** dump current config + +> **R** software reset + +> **S** send data over SPI + +> **T** show Tms value + +> **X** save current config to flash diff --git a/F1:F103/Canon_managing_device/canon.c b/F1:F103/Canon_managing_device/canon.c index 32c1871..b2c2e69 100644 --- a/F1:F103/Canon_managing_device/canon.c +++ b/F1:F103/Canon_managing_device/canon.c @@ -82,9 +82,9 @@ static int canon_read(uint8_t cmd, uint8_t zeroz){ return TRUE; } -// get current F value +// get current F value by stepper pos static uint16_t getfocval(){ - if(!canon_read(CANON_GETDIAL, 2)) return BADFOCVAL; + if(!canon_read(CANON_GETSTPPOS, 3)) return BADFOCVAL; uint16_t F = (buf[1] << 8) | buf[2]; return (F - Fdelta); } @@ -116,10 +116,10 @@ static void canon_writeu8(uint8_t cmd, uint8_t u){ buf[0] = cmd; buf[1] = u; SPI_transmit(buf, 2); }*/ -static int canon_writeu16(uint8_t cmd, uint16_t u){ +int canon_writeu16(uint8_t cmd, uint16_t u){ *((uint32_t*)buf) = 0; - buf[0] = cmd; buf[1] = u >> 8; buf[2] = u & 0xff; - if(3 != SPI_transmit(buf, 3)) return FALSE; + buf[0] = cmd; buf[1] = u >> 8; buf[2] = u & 0xff; buf[3] = 0; + if(4 != SPI_transmit(buf, 4)) return FALSE; return TRUE; } @@ -128,7 +128,7 @@ static void canon_poll(){ ready = 0; // wait no more than 1s uint32_t Tstart = Tms; - while(Tms - Tstart < 1000){ + while(Tms - Tstart < POLLING_TIMEOUT){ IWDG->KR = IWDG_REFRESH; if(!canon_read(CANON_POLL, 1)){ continue; @@ -150,7 +150,7 @@ void canon_init(){ inistate = INI_ERR; state = LENS_ERR; if(!canon_read(CANON_ID, 31)){ - DBG("Can't read ID\n"); + DBG("Error sending starting sequence\n"); return; } DBG("turn on power\n"); @@ -299,6 +299,7 @@ void canon_proc(){ inistate = INI_READY; state = LENS_READY; errctr = 0; + canon_sendcmd(CANON_FOCBYHANDS); break; case F_ERR: ++errctr; @@ -350,8 +351,9 @@ int canon_diaphragm(char command){ return 0; } +// move focuser @ absolute position val (or show current F if val < 0) int canon_focus(int16_t val){ - if(!ready) return 1; + if(!ready || inistate != INI_READY) return 1; if(val < 0){ USB_send("Fsteps="); USB_send(u2str(getfocval())); USB_send("\n"); }else{ @@ -365,14 +367,15 @@ int canon_focus(int16_t val){ return 1; } val -= curF; - if(!canon_writeu16(CANON_FOCMOVE, val)) return 1; + if(!canon_writeu16(CANON_FOCMOVE, val)) return 3; } canon_poll(); return 0; } +// send simplest command int canon_sendcmd(uint8_t cmd){ - if(!ready || !canon_read(cmd, 0)) return 1; + if(!ready || !canon_read(cmd, 1)) return 1; canon_poll(); return 0; } @@ -383,7 +386,7 @@ int canon_asku16(uint8_t cmd){ USB_send("par="); USB_send(u2str((buf[1] << 8) | buf[2])); USB_send("\n"); - canon_poll(); + //canon_poll(); return 0; } @@ -392,7 +395,7 @@ int canon_getinfo(){ USB_send("Info="); for(int i = 1; i < 7; ++i){ USB_send(u2hexstr(buf[i])); USB_send(" "); } - canon_poll(); + //canon_poll(); USB_send("\n"); return 0; } diff --git a/F1:F103/Canon_managing_device/canon.h b/F1:F103/Canon_managing_device/canon.h index 34ab8de..fb90277 100644 --- a/F1:F103/Canon_managing_device/canon.h +++ b/F1:F103/Canon_managing_device/canon.h @@ -28,18 +28,37 @@ // connection timeout (100ms): do nothing until this timeout #define CONN_TIMEOUT (100) +// polling timeout - 2.5s +#define POLLING_TIMEOUT (2500) + // pause after error before next reinit #define REINIT_PAUSE (5000) // waiting for starting moving - 0.25s #define MOVING_PAUSE (250) +// interval of canon_proc calls (10ms) +#define CANONPROC_INTERVAL (9) + +// `flooding` interval (250ms) +#define FLOODING_INTERVAL (249) + // answer for cmd "POLL" #define CANON_POLLANS (0xaa) // bad focus value - 32767 #define BADFOCVAL (0x7fff) +// flags of 0x90 (144) command: +// Manual focus active +#define CANON_MF_FLAG (0x0080) +// focus dial is active +#define CANON_DA_FLAG (0x2000) +// manual focus is on some edge of range +#define CANON_DE_FLAG (0x0010) +// focus dial moving +#define CANON_DM_FLAG (0x0004) + // maximal typedef enum{ @@ -55,11 +74,15 @@ typedef enum{ CANON_DIAPHRAGM = 0x13, // open/close diaphragm by given (int8_t) value of steps CANON_FOCMOVE = 0x44, // move focus dial by given amount of steps (int16) CANON_FOCBYHANDS= 0x5e, // turn on focus move by hands (to turn off send 4,5 or 6) - CANON_GETINFO = 0x80, // get information + CANON_DIALPOS0 = 0x6b, // DIALPOSx - something like current transfocator dial (limb) position (not stepper!) + CANON_DIALPOS1 = 0x6c, + CANON_DIALPOS2 = 0x6d, + CANON_DIALPOS3 = 0x6e, + CANON_GETINFO = 0x80, // get information (bytes 0-1 - model, bytes 2-3 - minF, bytes 4-5 - maxF) CANON_GETREG = 0x90, // get regulators' state - CANON_GETMODEL = 0xa0, // get lens (e.g. 200 == LX200) - CANON_GETDIAL = 0xc0, // get focus dial position in steps - CANON_GETFOCM = 0xc2, // get focus position in meters (not for all lenses) + CANON_GETMODEL = 0xa0, // get current lens focus (e.g. 200 == LX200) + CANON_GETSTPPOS = 0xc0, // get focus dial position in steps + CANON_GETFOCM = 0xc2, // get focus position in meters (not for all lenses): Fm = 2.5*b[1] + b[2]/100; Fm previous = next 2 bytes } canon_commands; typedef enum{ @@ -90,5 +113,6 @@ int canon_diaphragm(char command); int canon_focus(int16_t val); int canon_sendcmd(uint8_t cmd); int canon_asku16(uint8_t cmd); +int canon_writeu16(uint8_t cmd, uint16_t u); int canon_getinfo(); uint16_t canon_getstate(); diff --git a/F1:F103/Canon_managing_device/canonusb.bin b/F1:F103/Canon_managing_device/canonusb.bin index 4dd4a16..94352dc 100755 Binary files a/F1:F103/Canon_managing_device/canonusb.bin and b/F1:F103/Canon_managing_device/canonusb.bin differ diff --git a/F1:F103/Canon_managing_device/kicad/Canon_manage/Canon_manage_sch.pdf b/F1:F103/Canon_managing_device/kicad/Canon_manage/Canon_manage_sch.pdf index 800bb57..c6d733b 100644 Binary files a/F1:F103/Canon_managing_device/kicad/Canon_manage/Canon_manage_sch.pdf and b/F1:F103/Canon_managing_device/kicad/Canon_manage/Canon_manage_sch.pdf differ diff --git a/F1:F103/Canon_managing_device/main.c b/F1:F103/Canon_managing_device/main.c index 6792667..b2b84b1 100644 --- a/F1:F103/Canon_managing_device/main.c +++ b/F1:F103/Canon_managing_device/main.c @@ -67,11 +67,10 @@ int main(void){ IWDG->KR = IWDG_REFRESH; char *txt = NULL; usb_proc(); - if((txt = get_USB())){ - const char *ans = parse_cmd(txt); - if(ans) USB_send(ans); - } - if(Tms - SPIctr > 10){ // not more than once per 10ms + txt = get_USB(); + const char *ans = parse_cmd(txt); // call it even for NULL (if `flood` is running) + if(ans) USB_send(ans); + if(Tms - SPIctr > CANONPROC_INTERVAL){ // not more than once per 10ms SPIctr = Tms; canon_proc(); } diff --git a/F1:F103/Canon_managing_device/proto.c b/F1:F103/Canon_managing_device/proto.c index c05ced3..a84ad74 100644 --- a/F1:F103/Canon_managing_device/proto.c +++ b/F1:F103/Canon_managing_device/proto.c @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#include + #include "canon.h" #include "flash.h" #include "hardware.h" @@ -160,22 +162,23 @@ const char* helpmsg = "https://github.com/eddyem/stm32samples/tree/master/F1-nolib/Canon_managing_device build#" BUILD_NUMBER " @ " BUILD_DATE "\n" "0 - move to smallest foc value (e.g. 2.5m)\n" "1 - move to largest foc value (e.g. infinity)\n" - "a - set (!0) or reset (0) autoinit\n" + "a - move focus to given ABSOLUTE position or get current value (without number)\n" "d - open/close diaphragm by 1 step (+/-), open/close fully (o/c) (no way to know it current status)\n" - "f - move focus to given ABSOLUTE position or get current value (without number)\n" + "f - move focus to given RELATIVE position\n" "h - turn on hand focus management\n" "i - get lens information\n" "l - get lens model\n" "r - get regulators' state\n" "\t\tdebugging/conf commands:\n" + "A - set (!0) or reset (0) autoinit\n" "C - set CAN speed (25-3000 kbaud)\n" "D - set CAN ID (11 bit)\n" "E - erase full flash storage\n" "F - change SPI flags (F f val), f== l-LSBFIRST, b-BR [18MHz/2^(b+1)], p-CPOL, h-CPHA\n" "G - get SPI status\n" "I - reinit SPI\n" + "L - 'flood' message (same as `S` but every 250ms until next command)\n" "P - dump current config\n" - "s - get state\n" "R - software reset\n" "S - send data over SPI\n" "T - show Tms value\n" @@ -195,6 +198,41 @@ static void add2buf(const char *s){ *bptr = 0; } + +#define SPIBUFSZ (64) +// buffer for SPI sending +static uint8_t spibuf[SPIBUFSZ]; +static int spibuflen; // length of spibuf +// put user data into buffer +static int initspibuf(const char *buf){ + uint32_t D; + spibuflen = 0; + do{ + const char *nxt = getnum(buf, &D); + if(buf == nxt) break; + buf = nxt; + if(D > 0xff){ + USB_send("Number should be from 0 to 0xff\n"); + return 0; + } + spibuf[spibuflen++] = (uint8_t)D; + }while(spibuflen < SPIBUFSZ); + return spibuflen; +} +static void sendspibuf(){ + if(spibuflen < 1) return; + uint8_t buf[SPIBUFSZ]; + memcpy(buf, spibuf, spibuflen); + if(spibuflen == SPI_transmit((uint8_t*)buf, (uint8_t)spibuflen)){ + USB_send("Got SPI answer: "); + for(int i = 0; i < spibuflen; ++i){ + if(i) USB_send(", "); + USB_send(u2hexstr(buf[i])); + } + USB_send("\n"); + }else USB_send("Failed to send SPI buffer\n"); +} + static void errw(int e){ if(e){ add2buf("Error with code "); @@ -225,10 +263,20 @@ const char *inimsgs[INI_S_AMOUNT+1] = { [INI_S_AMOUNT] = "wrong state" }; const char *parse_cmd(const char *buf){ - //uint32_t u3; + static uint32_t lastFloodTime = 0; + if(lastFloodTime && (Tms - lastFloodTime > FLOODING_INTERVAL)){ + sendspibuf(); + lastFloodTime = Tms ? Tms : 1; + } + if(!buf || *buf == 0) return NULL; + lastFloodTime= FALSE; initbuf(); if(buf[1] == '\n' || !buf[1]){ // one symbol commands switch(*buf){ + case 'a': + case 'f': + errw(canon_focus(-1)); + break; case '-': flashstorage_init(); break; @@ -238,9 +286,6 @@ const char *parse_cmd(const char *buf){ case '1': errw(canon_sendcmd(CANON_FMAX)); break; - case 'f': - errw(canon_focus(-1)); - break; case 'i': errw(canon_getinfo()); break; @@ -272,25 +317,7 @@ const char *parse_cmd(const char *buf){ default: add2buf("unknown"); } - break; - case 'h': - errw(canon_sendcmd(CANON_FOCBYHANDS)); - break; - case 'I': - add2buf("Reinit SPI"); - spi_setup(); - canon_init(); - break; - case 'P': - dump_userconf(); - return NULL; - break; - case 'R': - USB_send("Soft reset\n"); - NVIC_SystemReset(); - break; - case 's': - add2buf("state="); + add2buf("\nstate="); uint16_t s = canon_getstate(); uint8_t idx = s & 0xff; if(idx > LENS_S_AMOUNT) idx = LENS_S_AMOUNT; @@ -300,6 +327,23 @@ const char *parse_cmd(const char *buf){ if(idx > INI_S_AMOUNT) idx = INI_S_AMOUNT; add2buf(inimsgs[idx]); break; + case 'h': + errw(canon_sendcmd(CANON_FOCBYHANDS)); + break; + case 'I': + USB_send("Reinit SPI\n"); + spi_setup(); + canon_init(); + return NULL; + break; + case 'P': + dump_userconf(); + return NULL; + break; + case 'R': + USB_send("Soft reset\n"); + NVIC_SystemReset(); + break; case 'T': add2buf("Tms="); add2buf(u2str(Tms)); @@ -314,10 +358,20 @@ const char *parse_cmd(const char *buf){ newline(); return stbuf; } - uint32_t D = 0, N = 0; + uint32_t D = 0; + int16_t neg; char *nxt; switch(*buf++){ // long messages - case 'a': + case 'a': // move focus to absolute position + buf = omit_spaces(buf); + neg = 1; + if(*buf == '-'){ ++buf; neg = -1; } + nxt = getnum(buf, &D); + if(nxt == buf) add2buf("Need number"); + else if(D > 0x7fff) add2buf("From -0x7fff to 0x7fff"); + else errw(canon_focus(neg * (int16_t)D)); + break; + case 'A': nxt = getnum(buf, &D); if(nxt != buf){ if(D) the_conf.autoinit = 1; @@ -329,14 +383,17 @@ const char *parse_cmd(const char *buf){ nxt = omit_spaces(buf); errw(canon_diaphragm(*nxt)); break; - case 'f': // move focus + case 'f': // move focus to relative position buf = omit_spaces(buf); - int16_t neg = 1; + neg = 1; if(*buf == '-'){ ++buf; neg = -1; } nxt = getnum(buf, &D); if(nxt == buf) add2buf("Need number"); else if(D > 0x7fff) add2buf("From -0x7fff to 0x7fff"); - else errw(canon_focus(neg * (int16_t)D)); + else{ + if(canon_writeu16(CANON_FOCMOVE, neg * (int16_t)D)) add2buf(OK); + else add2buf(FAIL); + } break; case 'C': nxt = getnum(buf, &D); @@ -382,40 +439,32 @@ const char *parse_cmd(const char *buf){ } add2buf("SPI_CR1="); add2buf(u2hexstr(SPI_CR1)); break; + case 'L': + if(0 == initspibuf(buf)){ + USB_send("Enter data bytes\n"); + return NULL; + } + USB_send("OK, activated\n"); + sendspibuf(); + lastFloodTime = Tms ? Tms : 1; + return NULL; + break; case 'S': // use stbuf here to store user data - do{ - nxt = getnum(buf, &D); - if(buf == nxt) break; - buf = nxt; - if(D > 0xff){ - USB_send("Number should be from 0 to 0xff\n"); - return NULL; - } - stbuf[N++] = (uint8_t)D; - if(N == STBUFSZ) break; - }while(1); - if(N == 0){ + if(0 == initspibuf(buf)){ USB_send("Enter data bytes\n"); return NULL; } USB_send("Send: "); - for(uint32_t i = 0; i < N; ++i){ + for(int i = 0; i < spibuflen; ++i){ if(i) USB_send(", "); - USB_send(u2hexstr(stbuf[i])); + USB_send(u2hexstr(spibuf[i])); } - USB_send("\n... "); - if(N == SPI_transmit((uint8_t*)stbuf, (uint8_t)N)){ - USB_send("OK\nGot SPI answer: "); - for(int i = 0; i < (int)N; ++i){ - if(i) USB_send(", "); - USB_send(u2hexstr(stbuf[i])); - } - USB_send("\n"); - }else USB_send("Failed\n"); + USB_send("\n"); + sendspibuf(); return NULL; break; default: - return buf; + return --buf; } newline(); return stbuf; diff --git a/F1:F103/Canon_managing_device/version.inc b/F1:F103/Canon_managing_device/version.inc index b43005f..3e517d1 100644 --- a/F1:F103/Canon_managing_device/version.inc +++ b/F1:F103/Canon_managing_device/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "93" -#define BUILD_DATE "2023-03-15" +#define BUILD_NUMBER "103" +#define BUILD_DATE "2023-03-17"