diff --git a/F3:F303/InterfaceBoard/Debug.c b/F3:F303/InterfaceBoard/Debug.c index b19f79a..f8ad6d4 100644 --- a/F3:F303/InterfaceBoard/Debug.c +++ b/F3:F303/InterfaceBoard/Debug.c @@ -50,13 +50,18 @@ void debug_newline_only(){ RB_write(&dbgrb, (const uint8_t*)&nl, 1); } +// print by lines until there's place in USB ringbuffer void print_debug_messages(){ if(!Config_mode) return; uint8_t rcvbuf[256]; do{ - int n = RB_readto(&dbgrb, '\n', rcvbuf, 256); - if(n == 0) break; - else if(n < 0) n = -n; // partial string: longer than 256 bytes + int l = RB_datalento(&dbgrb, '\n'); + if(l < 1) break; + int freesize = USB_sendbufspace(ICFG); + if(freesize < l) break; + if(l > 256) l = 256; + int n = RB_read(&dbgrb, rcvbuf, l); + if(n < 1) break; // empty or busy USB_send(ICFG, rcvbuf, n); }while(1); } diff --git a/F3:F303/InterfaceBoard/Debug.h b/F3:F303/InterfaceBoard/Debug.h index 02ea009..aaa797b 100644 --- a/F3:F303/InterfaceBoard/Debug.h +++ b/F3:F303/InterfaceBoard/Debug.h @@ -32,6 +32,7 @@ #else #define DBG(str) #define DBGs(str) +#define DBGch(ch) #define DBGn() #define DBGpri() #endif diff --git a/F3:F303/InterfaceBoard/main.c b/F3:F303/InterfaceBoard/main.c index 2141933..55da0c0 100644 --- a/F3:F303/InterfaceBoard/main.c +++ b/F3:F303/InterfaceBoard/main.c @@ -45,8 +45,8 @@ int main(void){ USBPU_OFF(); USB_setup(); //uint32_t ctr = Tms; - usb_LineCoding lc = {9600, 0, 0, 8}; - for(int i = 0; i < 5; ++i) usart_config(i, &lc); // configure all U[S]ARTs for default data + //usb_LineCoding lc = {9600, 0, 0, 8}; + //for(int i = 0; i < 5; ++i) usart_config(i, &lc); // configure all U[S]ARTs for default data USBPU_ON(); while(1){ // Put here code working WITOUT USB connected diff --git a/F3:F303/InterfaceBoard/multiiface.bin b/F3:F303/InterfaceBoard/multiiface.bin index 80b875d..9a2c9a7 100755 Binary files a/F3:F303/InterfaceBoard/multiiface.bin and b/F3:F303/InterfaceBoard/multiiface.bin differ diff --git a/F3:F303/InterfaceBoard/multiiface.creator.user b/F3:F303/InterfaceBoard/multiiface.creator.user index 36e1fe1..cb27183 100644 --- a/F3:F303/InterfaceBoard/multiiface.creator.user +++ b/F3:F303/InterfaceBoard/multiiface.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F3:F303/InterfaceBoard/proto.c b/F3:F303/InterfaceBoard/proto.c index 08317e3..ebaee10 100644 --- a/F3:F303/InterfaceBoard/proto.c +++ b/F3:F303/InterfaceBoard/proto.c @@ -95,8 +95,7 @@ static const char* erpg(const char *str){ static void sendoverU(uint8_t ifno, char *str){ int len = strlen(str); CFGWR("try to send "); CFGWRn(str); - str[len] = '\n'; - len = usart_send(ifno, (const uint8_t*)str, len+1); + len = usart_send(ifno, (const uint8_t*)str, len); CFGWR("sent "); CFGWR(i2str(len)); CFGWR("bytes\n"); } diff --git a/F3:F303/InterfaceBoard/ringbuffer.c b/F3:F303/InterfaceBoard/ringbuffer.c index b0ffe8e..0750be2 100644 --- a/F3:F303/InterfaceBoard/ringbuffer.c +++ b/F3:F303/InterfaceBoard/ringbuffer.c @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +#include + #include "ringbuffer.h" static int datalen(ringbuffer *b){ @@ -24,7 +26,7 @@ static int datalen(ringbuffer *b){ // stored data length int RB_datalen(ringbuffer *b){ - if(b->busy) return -1; + if(!b || b->busy) return -1; b->busy = 1; int l = datalen(b); b->busy = 0; @@ -32,7 +34,7 @@ int RB_datalen(ringbuffer *b){ } static int hasbyte(ringbuffer *b, uint8_t byte){ - if(b->head == b->tail) return -1; // no data in buffer + if(!b || b->head == b->tail) return -1; // no data in buffer int startidx = b->head; if(b->head > b->tail){ // for(int found = b->head; found < b->length; ++found) @@ -51,18 +53,13 @@ static int hasbyte(ringbuffer *b, uint8_t byte){ * @return index if found, -1 if none or busy */ int RB_hasbyte(ringbuffer *b, uint8_t byte){ - if(b->busy) return -1; + if(!b || b->busy) return -1; b->busy = 1; int ret = hasbyte(b, byte); b->busy = 0; return ret; } -// poor memcpy -static void mcpy(uint8_t *targ, const uint8_t *src, int l){ - while(l--) *targ++ = *src++; -} - // increment head or tail TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ *what += n; @@ -76,9 +73,9 @@ static int read(ringbuffer *b, uint8_t *s, int len){ int _1st = b->length - b->head; if(_1st > l) _1st = l; if(_1st > len) _1st = len; - mcpy(s, b->data + b->head, _1st); + memcpy(s, b->data + b->head, _1st); if(_1st < len && l > _1st){ - mcpy(s+_1st, b->data, l - _1st); + memcpy(s+_1st, b->data, l - _1st); incr(b, &b->head, l); return l; } @@ -94,20 +91,27 @@ static int read(ringbuffer *b, uint8_t *s, int len){ * @return bytes read or -1 if busy */ int RB_read(ringbuffer *b, uint8_t *s, int len){ - if(b->busy) return -1; + if(!b || b->busy || !s || len < 1) return -1; b->busy = 1; int r = read(b, s, len); b->busy = 0; return r; } -static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ +// length of data from current position to `byte` (including byte) +static int lento(ringbuffer *b, uint8_t byte){ int idx = hasbyte(b, byte); if(idx < 0) return 0; int partlen = idx + 1 - b->head; // now calculate length of new data portion if(idx < b->head) partlen += b->length; - if(partlen > len) return -read(b, s, len); + return partlen; +} + +static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ + int partlen = lento(b, byte); + if(!partlen) return 0; + if(partlen > len) return -1; return read(b, s, partlen); } @@ -120,21 +124,29 @@ static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ * @return amount of bytes written (negative, if lenbusy) return -1; + if(!b || b->busy || !s || len < 1) return -1; b->busy = 1; int n = readto(b, byte, s, len); b->busy = 0; return n; } +int RB_datalento(ringbuffer *b, uint8_t byte){ + if(!b || b->busy) return -1; + b->busy = 1; + int n = lento(b, byte); + b->busy = 0; + return n; +} + static int write(ringbuffer *b, const uint8_t *str, int l){ int r = b->length - 1 - datalen(b); // rest length if(l > r || !l) return 0; int _1st = b->length - b->tail; if(_1st > l) _1st = l; - mcpy(b->data + b->tail, str, _1st); + memcpy(b->data + b->tail, str, _1st); if(_1st < l){ // add another piece from start - mcpy(b->data, str+_1st, l-_1st); + memcpy(b->data, str+_1st, l-_1st); } incr(b, &b->tail, l); return l; @@ -148,7 +160,7 @@ static int write(ringbuffer *b, const uint8_t *str, int l){ * @return amount of bytes written or -1 if busy */ int RB_write(ringbuffer *b, const uint8_t *str, int l){ - if(b->busy) return -1; + if(!b || b->busy || !str || l < 1) return -1; b->busy = 1; int w = write(b, str, l); b->busy = 0; @@ -157,7 +169,7 @@ int RB_write(ringbuffer *b, const uint8_t *str, int l){ // just delete all information in buffer `b` int RB_clearbuf(ringbuffer *b){ - if(b->busy) return -1; + if(!b || b->busy) return -1; b->busy = 1; b->head = 0; b->tail = 0; diff --git a/F3:F303/InterfaceBoard/ringbuffer.h b/F3:F303/InterfaceBoard/ringbuffer.h index ed2cf95..5064755 100644 --- a/F3:F303/InterfaceBoard/ringbuffer.h +++ b/F3:F303/InterfaceBoard/ringbuffer.h @@ -38,4 +38,5 @@ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len); int RB_hasbyte(ringbuffer *b, uint8_t byte); int RB_write(ringbuffer *b, const uint8_t *str, int l); int RB_datalen(ringbuffer *b); +int RB_datalento(ringbuffer *b, uint8_t byte); int RB_clearbuf(ringbuffer *b); diff --git a/F3:F303/InterfaceBoard/usart.c b/F3:F303/InterfaceBoard/usart.c index cf12189..c1a247a 100644 --- a/F3:F303/InterfaceBoard/usart.c +++ b/F3:F303/InterfaceBoard/usart.c @@ -46,7 +46,7 @@ typedef struct { // maybe DMA1ch2 would be for SPI1Rx (or SSI should be @ SPI3), in this case USART3 would be interrupt-driven // IF1[0]: USART3 APB2 72 MHz DMA1ch2 DMA1ch3 PB14 // IF2[1]: USART1 APB1 36 MHz DMA1ch4 DMA1ch5 PB0 -// IF3[2]: USART2 APB2 72 MHz DMA1ch6 DMA1ch7 PA1 +// IF3[2]: USART2 APB2 72 MHz DMA1ch7 DMA1ch6 PA1 // IF4[3]: UART4 APB2 72 MHz DMA2ch5 DMA2ch3 // IF5[4]: UART5 APB2 72 MHz - - - interrupt-driven // IF6[5]: (CAN) @@ -54,19 +54,20 @@ typedef struct { static const USART_Config UC[USARTSNO] = { [0] = {.instance = USART3, .pclk_freq = 36000000, .UIRQn = USART3_IRQn, .DIRQn = DMA1_Channel2_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel3, .dma_tx_channel = DMA1_Channel2, .TTCflag = DMA_ISR_TCIF2, .DEport = GPIOB, .DEpin = 1<<14 }, [1] = {.instance = USART1, .pclk_freq = 72000000, .UIRQn = USART1_IRQn, .DIRQn = DMA1_Channel4_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel5, .dma_tx_channel = DMA1_Channel4, .TTCflag = DMA_ISR_TCIF4, .DEport = GPIOB, .DEpin = 1<<0 }, - [2] = {.instance = USART2, .pclk_freq = 36000000, .UIRQn = USART2_IRQn, .DIRQn = DMA1_Channel7_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel6, .dma_tx_channel = DMA1_Channel7, .TTCflag = DMA_ISR_TCIF7, .DEport = GPIOB, .DEpin = 1<<1 }, + [2] = {.instance = USART2, .pclk_freq = 36000000, .UIRQn = USART2_IRQn, .DIRQn = DMA1_Channel7_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel6, .dma_tx_channel = DMA1_Channel7, .TTCflag = DMA_ISR_TCIF7, .DEport = GPIOA, .DEpin = 1<<1 }, [3] = {.instance = UART4, .pclk_freq = 36000000, .UIRQn = UART4_IRQn, .DIRQn = DMA2_Channel5_IRQn, .dma_controller = DMA2, .dma_rx_channel = DMA2_Channel3, .dma_tx_channel = DMA2_Channel5, .TTCflag = DMA_ISR_TCIF5 }, [4] = {.instance = UART5, .pclk_freq = 36000000, .UIRQn = UART5_IRQn }, // no DMA }; // buffers for DMA or interrupt-driven data management static uint8_t inbuffers[USARTSNO][DMARXBUFSZ]; -static uint16_t inbufidx[USARTSNO] = {0}; // for interrupt-driven - index of next character (also amount of received bytes) +static uint16_t inbufidx[USARTSNO] = {0}; // for interrupt-driven - index of next character (also amount of received bytes) static uint8_t outbuffers[USARTSNO][DMATXBUFSZ]; -static uint16_t outbufidx[USARTSNO] = {0}; // index of next char to transmit over interrupt -static uint16_t outbuflen[USARTSNO] = {0}; // length of data to transmit over interrupt [equal 0 if nothing to send] -static uint8_t need2send[USARTSNO] = {0}; // flags from IDLE interrupt to send data portion -static uint8_t TXrdy[USARTSNO] = {1,1,1,1,1}; // TX DMA ready +static uint16_t outbufidx[USARTSNO] = {0}; // index of next char to transmit over interrupt +static uint16_t outbuflen[USARTSNO] = {0}; // length of data to transmit over interrupt [equal 0 if nothing to send] +static uint8_t need2send[USARTSNO] = {0}; // flags from IDLE interrupt to send data portion +static uint8_t TXrdy[USARTSNO] = {1,1,1,1,1}; // TX DMA ready +static int dma_read_idx[USARTSNO] = {0}; // start of data in DMA inbuffers // there's no way to tell recipient about overfull, so we will just "eat" spare data! @@ -172,7 +173,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ R->CPAR = (uint32_t) &U->RDR; R->CMAR = (uint32_t) inbuffers[ifNo]; R->CNDTR = DMARXBUFSZ; - R->CCR = DMA_CCR_MINC | DMA_CCR_EN; // | DMA_CCR_TCIE + R->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN; // manage circular buffer in polling // enable U[S]ART DMA U->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; }else{ @@ -200,7 +201,16 @@ void usart_start(uint8_t ifNo){ const USART_Config *cfg = &UC[ifNo]; cfg->instance->CR1 |= USART_CR1_UE; NVIC_EnableIRQ(cfg->UIRQn); - if(cfg->dma_controller) NVIC_EnableIRQ(cfg->DIRQn); + if(cfg->dma_controller){ // reset Rx DMA + volatile DMA_Channel_TypeDef *R = cfg->dma_rx_channel; + dma_read_idx[ifNo] = 0; + R->CCR = 0; + R->CPAR = (uint32_t) &cfg->instance->RDR; + R->CMAR = (uint32_t) inbuffers[ifNo]; + R->CNDTR = DMARXBUFSZ; + R->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN; + NVIC_EnableIRQ(cfg->DIRQn); + } DBGch('0' + ifNo); DBG("U[S]ART started"); } @@ -213,13 +223,11 @@ void usart_stop(uint8_t ifNo){ if(ifNo >= USARTSNO || UC[ifNo].instance == NULL) return; const USART_Config *cfg = &UC[ifNo]; cfg->instance->CR1 &= ~USART_CR1_UE; - if(cfg->DEport) RX485(cfg->DEport, cfg->DEpin); - /* if(cfg->dma_controller){ NVIC_DisableIRQ(cfg->DIRQn); } NVIC_DisableIRQ(cfg->UIRQn); - */ + if(cfg->DEport) RX485(cfg->DEport, cfg->DEpin); DBGch('0' + ifNo); DBG("U[S]ART stopped"); } @@ -234,11 +242,28 @@ void usarts_process(){ if(!(cfg->instance->CR1 & USART_CR1_UE)) continue; // USART disabled if(cfg->dma_controller){ // DMA-driven // Input data + int write_idx = DMARXBUFSZ - cfg->dma_rx_channel->CNDTR; // next symbol to be written + int available = (write_idx - dma_read_idx[i] + DMARXBUFSZ) % DMARXBUFSZ; // length of data available + if(need2send[i] && available == 0) need2send[i] = 0; + if(available >= USB_TXBUFSZ || need2send[i]){ // enough data or lonely couple of bytes + // copy data in one or two chunks (wrap handling) + if(dma_read_idx[i] + available <= DMARXBUFSZ){ // head before tail + USB_send(i, &inbuffers[i][dma_read_idx[i]], available); + }else{ // head after tail - two chunks + uint32_t first = DMARXBUFSZ - dma_read_idx[i]; + USB_send(i, &inbuffers[i][dma_read_idx[i]], first); + USB_send(i, inbuffers[i], available - first); + } + DBG("USART -> USB over DMA"); + dma_read_idx[i] = write_idx; // update read pointer + } +#if 0 if(DMARXBUFSZ - cfg->dma_rx_channel->CNDTR > DMARXBUFSZ/2 || need2send[i]){ volatile DMA_Channel_TypeDef *R = cfg->dma_rx_channel; R->CCR &= ~DMA_CCR_EN; // pause DMA input transactions register int l = DMARXBUFSZ - R->CNDTR; if(l){ // have some input data -> send and restart DMA + DBG("need"); if(USB_send(i, inbuffers[i], l)){ DBG("USART -> USB over DMA"); // restart DMA only in case of succesfull sent or if failed, but have ability of buffer overfull @@ -249,6 +274,7 @@ void usarts_process(){ } R->CCR |= DMA_CCR_EN; // re-enable DMA } +#endif // Output data if(TXrdy[i]){ // ready to send new data int got = USB_receive(i, outbuffers[i], DMATXBUFSZ); @@ -308,7 +334,7 @@ void usarts_process(){ int usart_send(uint8_t ifNo, const uint8_t *data, int len){ if(ifNo >= USARTSNO || !data || len < 1) return 0; const USART_Config *cfg = &UC[ifNo]; - if(TXrdy[ifNo] == 0 || (!cfg->instance->CR1 & USART_CR1_UE)) return -1; // busy or not active + if(TXrdy[ifNo] == 0 || !(cfg->instance->CR1 & USART_CR1_UE)) return -1; // busy or not active if(len > DMATXBUFSZ) len = DMATXBUFSZ; memcpy(outbuffers[ifNo], data, len); if(cfg->dma_controller){ @@ -350,7 +376,6 @@ static void usart_isr(uint8_t ifno){ volatile USART_TypeDef *U = cfg->instance; // for every flag we should also check if it's IRQ active if((U->ISR & USART_ISR_RXNE) && (U->CR1 & USART_CR1_RXNEIE)){ // got new byte - DBG("RXNE"); if(inbufidx[ifno] == DMARXBUFSZ) (void) U->RDR; // throw away data: buffer overfull else inbuffers[ifno][ inbufidx[ifno]++ ] = U->RDR; // put new byte into buffer } @@ -358,22 +383,17 @@ static void usart_isr(uint8_t ifno){ if(U->ISR & USART_ISR_IDLE){ // try to send collected data (DMA-driven) need2send[ifno] = 1; // seems like data portion is over - try to send it U->ICR = USART_ICR_IDLECF; - DBG("IDLE"); } if((U->ISR & USART_ISR_TXE) && (U->CR1 & USART_CR1_TXEIE)){ // send next byte if need (interrupt-driven) - DBG("TXE"); if(outbuflen[ifno] > outbufidx[ifno]){ U->TDR = outbuffers[ifno][ outbufidx[ifno]++ ]; }else if(U->CR1 & USART_CR1_TXEIE){ U->CR1 &= ~USART_CR1_TXEIE; // disable interrupt: no data to send TXrdy[ifno] = 1; - DBG("TXRDY"); } } if(U->ISR & USART_ISR_TC){ // switch RS-485 to Rx after transmission complete - DBG("TC"); if(cfg->DEport){ - DBG("485 -> RX"); RX485(cfg->DEport, cfg->DEpin); U->CR1 &= ~USART_CR1_TE; U->CR1 |= USART_CR1_RE; @@ -390,7 +410,7 @@ void uart4_exti34_isr(){ usart_isr(3); } void uart5_exti35_isr(){ usart_isr(4); } // DMA Tx interrupts (to arm ready flag) -void dma1_channel2_isr(){ DBG("DMA1 done"); TXrdy[0] = 1; DMA1->IFCR = DMA_IFCR_CTCIF2; } -void dma1_channel4_isr(){ DBG("DMA2 done"); TXrdy[1] = 1; DMA1->IFCR = DMA_IFCR_CTCIF4; } -void dma1_channel6_isr(){ DBG("DMA3 done"); TXrdy[2] = 1; DMA1->IFCR = DMA_IFCR_CTCIF6; } -void dma2_channel5_isr(){ DBG("DMA4 done"); TXrdy[3] = 1; DMA2->IFCR = DMA_IFCR_CTCIF5; } +void dma1_channel2_isr(){ TXrdy[0] = 1; DMA1->IFCR = DMA_IFCR_CTCIF2; } +void dma1_channel4_isr(){ TXrdy[1] = 1; DMA1->IFCR = DMA_IFCR_CTCIF4; } +void dma1_channel7_isr(){ TXrdy[2] = 1; DMA1->IFCR = DMA_IFCR_CTCIF7; } +void dma2_channel5_isr(){ TXrdy[3] = 1; DMA2->IFCR = DMA_IFCR_CTCIF5; } diff --git a/F3:F303/InterfaceBoard/usart.h b/F3:F303/InterfaceBoard/usart.h index 1ff82b6..ad25616 100644 --- a/F3:F303/InterfaceBoard/usart.h +++ b/F3:F303/InterfaceBoard/usart.h @@ -22,11 +22,8 @@ #include "usb_dev.h" // DMA linear buffers for Rx/Tx -#define DMARXBUFSZ 128 -#define DMATXBUFSZ 128 -// ringbuffers for collected data -#define USARTRXRBSZ 256 -#define USARTTXRBSZ 256 +#define DMARXBUFSZ 512 +#define DMATXBUFSZ 512 void usart_config(uint8_t ifNo, usb_LineCoding *lc); void usart_start(uint8_t ifNo); diff --git a/F3:F303/InterfaceBoard/usb_dev.c b/F3:F303/InterfaceBoard/usb_dev.c index c063fb4..d5ff457 100644 --- a/F3:F303/InterfaceBoard/usb_dev.c +++ b/F3:F303/InterfaceBoard/usb_dev.c @@ -184,14 +184,11 @@ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ case REQ_RECIPIENT_INTERFACE: switch(req->bRequest){ case SET_LINE_CODING: - //DBG("SLC"); if(!data || !datalen) break; // wait for data - //DBG("test"); if(datalen == sizeof(usb_LineCoding)) linecoding_handler(ifno, (usb_LineCoding*)data); break; case GET_LINE_CODING: - DBG("GLC"); EP_WriteIRQ(0, (uint8_t*)&lineCoding[ifno], sizeof(lineCoding)); break; case SET_CONTROL_LINE_STATE: @@ -226,17 +223,26 @@ int USB_sendall(uint8_t ifno){ return TRUE; } +// return amount of free space in buffer +int USB_sendbufspace(uint8_t ifno){ + if(!CDCready[ifno]) return 0; + return rbout[ifno].length - RB_datalen((ringbuffer*)&rbout[ifno]); +} + // put `buf` into queue to send int USB_send(uint8_t ifno, const uint8_t *buf, int len){ - if(!buf || !CDCready[ifno] || !len) return FALSE; - if(ifno != ICFG) DBG("USB_send"); + if(!buf || !CDCready[ifno] || !len){ + return FALSE; + } uint32_t T0 = Tms; while(len){ if(Tms - T0 > DISCONN_TMOUT){ //break_handler(ifno); return FALSE; } - if(!CDCready[ifno]) return FALSE; + if(!CDCready[ifno]){ + return FALSE; + } IWDG->KR = IWDG_REFRESH; int l = RB_datalen((ringbuffer*)&rbout[ifno]); if(l < 0) continue; @@ -255,7 +261,6 @@ int USB_send(uint8_t ifno, const uint8_t *buf, int len){ } } if(buf[len-1] == '\n' && lastdsz[ifno] < 0){ - if(ifno != ICFG) DBG("send_next"); send_next(ifno); } return TRUE; @@ -279,7 +284,6 @@ int USB_putbyte(uint8_t ifno, uint8_t byte){ } // send line if got EOL if(byte == '\n' && lastdsz[ifno] < 0){ - if(ifno != ICFG) DBG("send_next"); send_next(ifno); } return TRUE; diff --git a/F3:F303/InterfaceBoard/usb_dev.h b/F3:F303/InterfaceBoard/usb_dev.h index eb9be56..3ea0e41 100644 --- a/F3:F303/InterfaceBoard/usb_dev.h +++ b/F3:F303/InterfaceBoard/usb_dev.h @@ -55,6 +55,7 @@ void linecoding_handler(uint8_t ifno, usb_LineCoding *lc); #define CFGWRn(s) do{USB_sendstr(ICFG, s); USB_putbyte(ICFG, '\n');}while(0) #define CFGn() USB_putbyte(ICFG, '\n') +int USB_sendbufspace(uint8_t ifno); int USB_sendall(uint8_t ifno); int USB_send(uint8_t ifno, const uint8_t *buf, int len); int USB_putbyte(uint8_t ifno, uint8_t byte); diff --git a/F3:F303/InterfaceBoard/version.inc b/F3:F303/InterfaceBoard/version.inc index 2f3d46b..e22d49e 100644 --- a/F3:F303/InterfaceBoard/version.inc +++ b/F3:F303/InterfaceBoard/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "110" -#define BUILD_DATE "2026-02-16" +#define BUILD_NUMBER "140" +#define BUILD_DATE "2026-02-17"