mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Add XON/XOFF flow control on Serial + USB. This is enabled by default for Serial (fix #20)
This commit is contained in:
parent
c4a52e234e
commit
b9266cdf87
@ -2,6 +2,7 @@
|
||||
Fix break inside loop inside case inside function (fix 428)
|
||||
Added fs.stat and File.seek (fix #429, fix #430)
|
||||
Allow use of DLE (char 16) on an empty line to turn echo off for *just that line*
|
||||
Add XON/XOFF flow control on Serial + USB. This is enabled by default for Serial (fix #20)
|
||||
|
||||
1v70 : Make pipe remove its drain/close listeners. Stops out of memory for repeated piping.
|
||||
Fix parseInt for values too large to go in an int (#406)
|
||||
|
||||
@ -34,6 +34,25 @@ typedef struct {
|
||||
|
||||
TxBufferItem txBuffer[TXBUFFERMASK+1];
|
||||
volatile unsigned char txHead=0, txTail=0;
|
||||
|
||||
typedef enum {
|
||||
SDS_NONE,
|
||||
SDS_XOFF_PENDING = 1,
|
||||
SDS_XON_PENDING = 2,
|
||||
SDS_XOFF_SENT = 4, // sending XON clears this
|
||||
SDS_FLOW_CONTROL_XON_XOFF = 8, // flow control enabled
|
||||
} PACKED_FLAGS JshSerialDeviceState;
|
||||
JshSerialDeviceState jshSerialDeviceStates[USARTS+1];
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void jshInitDevices() { // called from jshInit
|
||||
int i;
|
||||
jshSerialDeviceStates[0] = SDS_FLOW_CONTROL_XON_XOFF; // USB
|
||||
for (i=1;i<=USARTS;i++)
|
||||
jshSerialDeviceStates[i] = SDS_NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Queue a character for transmission
|
||||
@ -78,6 +97,18 @@ void jshTransmit(IOEventFlags device, unsigned char data) {
|
||||
|
||||
// Try and get a character for transmission - could just return -1 if nothing
|
||||
int jshGetCharToTransmit(IOEventFlags device) {
|
||||
if (DEVICE_IS_USART(device)) {
|
||||
JshSerialDeviceState *deviceState = &jshSerialDeviceStates[device-EV_USBSERIAL];
|
||||
if ((*deviceState)&SDS_XOFF_PENDING) {
|
||||
(*deviceState) = ((*deviceState)&(~SDS_XOFF_PENDING)) | SDS_XOFF_SENT;
|
||||
return 19/*XOFF*/;
|
||||
}
|
||||
if ((*deviceState)&SDS_XON_PENDING) {
|
||||
(*deviceState) = ((*deviceState)&(~(SDS_XON_PENDING|SDS_XOFF_SENT)));
|
||||
return 17/*XON*/;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char ptr = txTail;
|
||||
while (txHead != ptr) {
|
||||
if (IOEVENTFLAGS_GETTYPE(txBuffer[ptr].flags) == device) {
|
||||
@ -207,7 +238,7 @@ bool jshPopIOEventOfType(IOEventFlags eventType, IOEvent *result) {
|
||||
if (IOEVENTFLAGS_GETTYPE(ioBuffer[i].flags) == eventType) {
|
||||
*result = ioBuffer[i];
|
||||
// work back and shift all items in out queue
|
||||
unsigned char n = (unsigned char)((n+IOBUFFERMASK) & IOBUFFERMASK);
|
||||
unsigned char n = (unsigned char)((i+IOBUFFERMASK) & IOBUFFERMASK);
|
||||
while (n!=ioTail) {
|
||||
ioBuffer[i] = ioBuffer[n];
|
||||
i = n;
|
||||
@ -340,7 +371,34 @@ IOEventFlags jshFromDeviceString(const char *device) {
|
||||
|
||||
/// Set whether the host should transmit or not
|
||||
void jshSetFlowControlXON(IOEventFlags device, bool hostShouldTransmit) {
|
||||
NOT_USED(device);
|
||||
NOT_USED(hostShouldTransmit);
|
||||
if (DEVICE_IS_USART(device)) {
|
||||
JshSerialDeviceState *deviceState = &jshSerialDeviceStates[device-EV_USBSERIAL];
|
||||
if ((*deviceState) & SDS_FLOW_CONTROL_XON_XOFF) {
|
||||
if (hostShouldTransmit) {
|
||||
if (((*deviceState)&(SDS_XOFF_SENT|SDS_XON_PENDING)) == SDS_XOFF_SENT) {
|
||||
jshInterruptOff();
|
||||
(*deviceState) |= SDS_XON_PENDING;
|
||||
jshInterruptOn();
|
||||
jshUSARTKick(device);
|
||||
}
|
||||
} else { // !hostShouldTransmit
|
||||
if (((*deviceState)&(SDS_XOFF_SENT|SDS_XOFF_PENDING)) == 0) {
|
||||
jshInterruptOff();
|
||||
(*deviceState) |= SDS_XOFF_PENDING;
|
||||
jshInterruptOn();
|
||||
jshUSARTKick(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set whether to use flow control on the given device or not
|
||||
void jshSetFlowControlEnabled(IOEventFlags device, bool xOnXOff) {
|
||||
if (!DEVICE_IS_USART(device)) return;
|
||||
JshSerialDeviceState *deviceState = &jshSerialDeviceStates[device-EV_USBSERIAL];
|
||||
if (xOnXOff)
|
||||
(*deviceState) |= SDS_FLOW_CONTROL_XON_XOFF;
|
||||
else
|
||||
(*deviceState) &= ~SDS_FLOW_CONTROL_XON_XOFF;
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
#include "jsutils.h"
|
||||
#include "platform_config.h"
|
||||
|
||||
void jshInitDevices(); // called from jshInit
|
||||
|
||||
typedef enum {
|
||||
// device type
|
||||
EV_NONE,
|
||||
@ -130,4 +132,7 @@ int jshGetCharToTransmit(IOEventFlags device);
|
||||
/// Set whether the host should transmit or not
|
||||
void jshSetFlowControlXON(IOEventFlags device, bool hostShouldTransmit);
|
||||
|
||||
/// Set whether to use flow control on the given device or not
|
||||
void jshSetFlowControlEnabled(IOEventFlags device, bool xOnXOff);
|
||||
|
||||
#endif /* JSDEVICES_H_ */
|
||||
|
||||
@ -142,6 +142,7 @@ typedef struct {
|
||||
unsigned char bytesize;
|
||||
unsigned char parity;
|
||||
unsigned char stopbits;
|
||||
bool xOnXOff; // XON XOFF flow control?
|
||||
} PACKED_FLAGS JshUSARTInfo;
|
||||
|
||||
static inline void jshUSARTInitInfo(JshUSARTInfo *inf) {
|
||||
@ -151,6 +152,7 @@ static inline void jshUSARTInitInfo(JshUSARTInfo *inf) {
|
||||
inf->bytesize = DEFAULT_BYTESIZE;
|
||||
inf->parity = DEFAULT_PARITY; // PARITY_NONE = 0, PARITY_ODD = 1, PARITY_EVEN = 2 FIXME: enum?
|
||||
inf->stopbits = DEFAULT_STOPBITS;
|
||||
inf->xOnXOff = false;
|
||||
}
|
||||
|
||||
/** Set up a UART, if pins are -1 they will be guessed */
|
||||
|
||||
@ -126,7 +126,7 @@ Set this Serial port as the port for the console
|
||||
"generate" : "jswrap_serial_setup",
|
||||
"params" : [
|
||||
["baudrate","JsVar","The baud rate - the default is 9600"],
|
||||
["options","JsVar",["An optional structure containing extra information on initialising the serial port.","```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1}```","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.","Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite"]]
|
||||
["options","JsVar",["An optional structure containing extra information on initialising the serial port.","```{rx:pin,tx:pin,bytesize:8,parity:null/'none'/'o'/'odd'/'e'/'even',stopbits:1,flow:null/undefined/'none'/'xon'}```","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `UART`/`USART` markers.","Note that even after changing the RX and TX pins, if you have called setup before then the previous RX and TX pins will still be connected to the Serial port as well - until you set them to something else using digitalWrite"]]
|
||||
]
|
||||
}
|
||||
Setup this Serial port with the given baud rate and options.
|
||||
@ -179,6 +179,14 @@ void jswrap_serial_setup(JsVar *parent, JsVar *baud, JsVar *options) {
|
||||
if (jsvIsInt(v))
|
||||
inf.stopbits = (unsigned char)jsvGetInteger(v);
|
||||
jsvUnLock(v);
|
||||
|
||||
v = jsvObjectGetChild(options, "flow", 0);
|
||||
if(jsvIsUndefined(v) || jsvIsNull(v) || jsvIsStringEqual(v, "none"))
|
||||
inf.xOnXOff = false;
|
||||
else if(jsvIsStringEqual(v, "xon"))
|
||||
inf.xOnXOff = true;
|
||||
else jsExceptionHere(JSET_ERROR, "Invalid flow control: %q", v);
|
||||
jsvUnLock(v);
|
||||
}
|
||||
|
||||
jshUSARTSetup(device, &inf);
|
||||
|
||||
@ -32,6 +32,7 @@ IOEventFlags pinToEVEXTI(Pin pin) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void jshInit() {
|
||||
jshInitDevices();
|
||||
Serial.begin(DEFAULT_BAUD_RATE);
|
||||
}
|
||||
|
||||
|
||||
@ -168,6 +168,7 @@ int getch()
|
||||
|
||||
|
||||
void jshInit() {
|
||||
jshInitDevices();
|
||||
#ifndef __MINGW32__
|
||||
if (!terminal_set) {
|
||||
struct termios new_termios;
|
||||
|
||||
@ -58,6 +58,7 @@ void mbedSerialIRQ(uint32_t id, SerialIrq event) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// for non-blocking IO
|
||||
void jshInit() {
|
||||
jshInitDevices();
|
||||
systemTimeWasHigh = false;
|
||||
systemTimeHigh = 0;
|
||||
systemTime.start();
|
||||
|
||||
@ -970,6 +970,7 @@ static void jshResetSerial() {
|
||||
}
|
||||
|
||||
void jshInit() {
|
||||
jshInitDevices();
|
||||
int i;
|
||||
// reset some vars
|
||||
for (i=0;i<16;i++)
|
||||
@ -1954,6 +1955,8 @@ void *NO_INLINE checkPinsForDevice(JshPinFunction device, int count, Pin *pins,
|
||||
void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
|
||||
jshSetDeviceInitialised(device, true);
|
||||
|
||||
jshSetFlowControlEnabled(device, inf->xOnXOff);
|
||||
|
||||
if (device == EV_USBSERIAL) {
|
||||
return; // eep!
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user