Skip to content

Commit

Permalink
Use Stream and Print classes for input and output
Browse files Browse the repository at this point in the history
Instead of keeping pin numbers and output handler functions and deciding
on the fly where to send any printed bytes, now a Print* is kept,
greatly simplifying sbp() and friends. Additionally, output can now also
be redirected to an arbitrary Print object by calling setOutputHandler.

Similarly, for the input a Stream* is kept. This allows users of the
library to select any of the available serial port or any other Stream
object to use as the main console. This allows for example to use an
Ethernet client, without needing the bitlash library to understand every
particular ethernet library available (as long as it implements the
Stream interface).
  • Loading branch information
matthijskooijman committed Jan 29, 2014
1 parent 20b4752 commit e91dd2a
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 108 deletions.
18 changes: 11 additions & 7 deletions src/bitlash-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,10 @@ numvar doCommand(char *cmd) {
}


void initBitlash(unsigned long baud) {

#if defined(TINY_BUILD)
beginSerial(9600);
#else
beginSerial(baud);
#endif
void initBitlash(Stream& stream) {
blconsole = &stream;
if (!bloutdefault)
blout = bloutdefault = &stream;

#if defined(ARM_BUILD)
eeinit();
Expand All @@ -76,3 +73,10 @@ void initBitlash(unsigned long baud) {
initlbuf();
}

void initBitlash(unsigned long baud) {
#if defined(TINY_BUILD)
baud = 9600;
#endif
DEFAULT_CONSOLE.begin(baud);
initBitlash(DEFAULT_CONSOLE);
}
4 changes: 2 additions & 2 deletions src/bitlash-cmdline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void initlbuf(void) {
prompt();

// flush any pending serial input
while (serialAvailable()) serialRead();
while (blconsole->read() >= 0) /* nothing */;
}


Expand Down Expand Up @@ -197,7 +197,7 @@ void doCharacter(char c) {
void runBitlash(void) {

// Pipe the serial input into the command handler
if (serialAvailable()) doCharacter(serialRead());
if (blconsole->available()) doCharacter(blconsole->read());

// Background macro handler: feed it one call each time through
runBackgroundTasks();
Expand Down
8 changes: 4 additions & 4 deletions src/bitlash-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,16 @@ numvar func_bitwrite(void) { reqargs(3); return arg3 ? func_bitset() : func_bitc

numvar func_getkey(void) {
if (getarg(0) > 0) sp((char *) getarg(1));
while (!serialAvailable()) {;} // blocking!
return (numvar) serialRead();
while (!blconsole->available()) {;} // blocking!
return (numvar) blconsole->read();
}

numvar func_getnum(void) {
numvar num = 0;
if (getarg(0) > 0) sp((char *) getarg(1));
for (;;) {
while (!serialAvailable()) {;} // blocking!
int k = serialRead();
while (!blconsole->available()) {;} // blocking!
int k = blconsole->read();
if ((k == '\r') || (k == '\n')) {
speol();
return num;
Expand Down
133 changes: 72 additions & 61 deletions src/bitlash-serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
#ifndef DEFAULT_OUTPIN
#define DEFAULT_OUTPIN 0
#endif
byte outpin = DEFAULT_OUTPIN; // output pin

#ifdef SOFTWARE_SERIAL_TX

Expand All @@ -52,10 +51,40 @@ byte outpin = DEFAULT_OUTPIN; // output pin
#ifndef NUMPINS
#define NUMPINS 32 // default to Arduino Diecimila/168..328
#endif
int bittime[NUMPINS]; // bit times (1000000/baud) per pin, 0 = uninitialized

// set output back to 'stdout' ;)
void resetOutput(void) { outpin = DEFAULT_OUTPIN; }
void resetOutput(void) { blout = bloutdefault; }

// TX-only minimal software serial implementation
class SoftwareSerialTX : public Print {
public:
uint8_t pin;
static uint16_t bittime[NUMPINS]; // bit times (1000000/baud) per pin, 0 = uninitialized

// bit whack a byte out the port designated by 'outpin'
virtual size_t write(uint8_t c) {
const uint16_t bt = bittime[this->pin];
char bits = 8; // 8 data bits
digitalWrite(this->pin, LOW);
delayMicroseconds(bt);
while (bits--) {
//if ((c & 1) == 0) digitalWrite(outpin, LOW);
//else digitalWrite(outpin, HIGH);
digitalWrite(this->pin, c & 1);
delayMicroseconds(bt);
c >>= 1;
}
digitalWrite(this->pin, HIGH);
delayMicroseconds(bt<<1);
return 1;
}


};

uint16_t SoftwareSerialTX::bittime[];

SoftwareSerialTX sstx;

void chkpin(char pin) {
// TODO: fix this warning re: comparison
Expand All @@ -65,59 +94,47 @@ void chkpin(char pin) {
numvar setBaud(numvar pin, unumvar baud) {
chkpin(pin);

//#ifndef SOFTWARE_SERIAL_TX
if (pin == DEFAULT_OUTPIN) {
beginSerial(baud);
DEFAULT_CONSOLE.begin(baud);
return 0;
}
//#endif

#ifdef ALTERNATE_OUTPIN
else if (pin == ALTERNATE_OUTPIN) {
Serial1.begin(baud);
return 0;
}
#endif

bittime[pin] = (1000000/baud) - clockCyclesToMicroseconds(50);
Serial.println(baud);
sstx.bittime[pin] = (1000000/baud) - clockCyclesToMicroseconds(50);
Serial.println(sstx.bittime[pin]);
pinMode(pin, OUTPUT); // make it an output
digitalWrite(pin, HIGH); // set idle
delayMicroseconds(bittime[pin]); // let it quiesce
return bittime[pin];
delayMicroseconds(sstx.bittime[pin]); // let it quiesce
return sstx.bittime[pin];
}

void setOutput(byte pin) {
chkpin(pin);
outpin = pin;

#ifdef HARDWARE_SERIAL_TX
// skip soft baud check for the hardware uart
if (outpin != DEFAULT_OUTPIN)
#endif
if (pin == DEFAULT_OUTPIN) {
blout = blconsole;
return;
}

#ifdef ALTERNATE_OUTPIN
if (outpin != ALTERNATE_OUTPIN)
if (pin == ALTERNATE_OUTPIN) {
blout = &Serial1;
return;
}
#endif

// set the softserial baud if it's not already set
if (!bittime[outpin]) setBaud(pin, DEFAULT_SECONDARY_BAUD);
if (!sstx.bittime[pin]) setBaud(pin, DEFAULT_SECONDARY_BAUD);
sstx.pin = pin;
blout = &sstx;
}

// bit whack a byte out the port designated by 'outpin'
void whackabyte(unsigned char c) {
int bt = bittime[outpin];
char bits = 8; // 8 data bits
digitalWrite(outpin, LOW);
delayMicroseconds(bt);
while (bits--) {
//if ((c & 1) == 0) digitalWrite(outpin, LOW);
//else digitalWrite(outpin, HIGH);
digitalWrite(outpin, c & 1);
delayMicroseconds(bt);
c >>= 1;
}
digitalWrite(outpin, HIGH);
delayMicroseconds(bt<<1);
}
#endif // SOFTWARE_SERIAL_TX


Expand All @@ -129,16 +146,29 @@ void whackabyte(unsigned char c) {
//
serialOutputFunc serial_override_handler;

class PrintToFunction : public Print {
public:
serialOutputFunc func = NULL;
virtual size_t write(uint8_t c) { func (c); return 1; }
};

PrintToFunction overrideTarget;

byte serialIsOverridden(void) {
return serial_override_handler != 0;
return bloutdefault != blconsole;
}

void setOutputHandler(serialOutputFunc newHandler) {
serial_override_handler = newHandler;
overrideTarget.func = newHandler;
blout = bloutdefault = &overrideTarget;
}

void setOutputHandler(Print& newHandler) {
blout = bloutdefault = &newHandler;
}

void resetOutputHandler(void) {
serial_override_handler = 0;
blout = bloutdefault = blconsole;
}

#endif
Expand All @@ -150,31 +180,12 @@ void resetOutputHandler(void) {
//
// this is a pinchpoint on output. all output funnels through spb.
//
#if defined(HARDWARE_SERIAL_TX) || defined(SOFTWARE_SERIAL_TX)
void spb(char c) {
#ifdef HARDWARE_SERIAL_TX
if (outpin == DEFAULT_OUTPIN) {

#ifdef SERIAL_OVERRIDE
if (serial_override_handler) (*serial_override_handler)(c);
else
#endif
serialWrite(c);
return;
}
#endif
#ifdef ALTERNATE_OUTPIN
if (outpin == ALTERNATE_OUTPIN) { Serial1.print(c); return; }
#endif
#ifdef SOFTWARE_SERIAL_TX
whackabyte(c);
#endif
blout->write(c);
}
void sp(const char *str) { while (*str) spb(*str++); }
void speol(void) { spb(13); spb(10); }
#else
// handle no-serial case
#endif

void sp(const char *str) { blout->print(str); }
void speol(void) { blout->println(); }


void printIntegerInBase(unumvar n, uint8_t base, numvar width, byte pad) {
Expand Down Expand Up @@ -229,8 +240,8 @@ void chkbreak(void) {

// check serial input stream for ^C break
void chkbreak(void) {
if (serialAvailable()) { // allow ^C to break out
if (serialRead() == 3) { // BUG: this gobblesnarfs input characters! - need serialPeek()
if (blconsole->available()) { // allow ^C to break out
if (blconsole->read() == 3) { // BUG: this gobblesnarfs input characters! - need serialPeek()
msgpl(M_ctrlc);
longjmp(env, X_EXIT);
}
Expand Down
49 changes: 15 additions & 34 deletions src/bitlash.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@

#define ARDUINO_BUILD 1

#define beginSerial Serial.begin
#define serialAvailable Serial.available
#define serialRead Serial.read
#define serialWrite Serial.write
#define DEFAULT_CONSOLE SERIAL_PORT_MONITOR

#include "Arduino.h"
#define prog_char char PROGMEM
Expand All @@ -124,9 +121,10 @@
#define MINIMUM_FREE_RAM 50

#else
// TODO: More non-Arduino stuff
#define HIGH 1
#define LOW 0
#endif // HIGH: arduino build
#endif // Arduino build


///////////////////////////////////////////////////////
Expand All @@ -141,18 +139,6 @@
#if defined(__AVR_ATmega644P__)
#define SANGUINO

//void beginSerial(unsigned long baud) { Serial.begin(baud); }
//char serialAvailable(void) { return Serial.available(); }
//char serialRead(void) { return Serial.read(); }
//void serialWrite(char c) { return Serial.print(c); }

#ifndef beginSerial
#define beginSerial Serial.begin
#define serialAvailable Serial.available
#define serialRead Serial.read
#define serialWrite Serial.print
#endif

// Sanguino has 24 digital and 8 analog io pins
#define NUMPINS (24+8)

Expand All @@ -179,13 +165,6 @@
//
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define MEGA 1
#endif

#if defined(MEGA)
#define beginSerial Serial.begin
#define serialAvailable Serial.available
#define serialRead Serial.read
#define serialWrite Serial.print

// MEGA has 54 digital and 16 analog pins
#define NUMPINS (54+16)
Expand All @@ -203,11 +182,6 @@

#if defined(__AVR_ATmega64__)

#define beginSerial Serial1.begin
#define serialAvailable Serial1.available
#define serialRead Serial1.read
#define serialWrite Serial1.print

#define NUMPINS (53)
#endif

Expand All @@ -222,12 +196,7 @@
#undef MINIMUM_FREE_RAM
#define MINIMUM_FREE_RAM 20
#define NUMPINS 6
//#undef HARDWARE_SERIAL_TX
#undef SOFTWARE_SERIAL_TX
//#define SOFTWARE_SERIAL_TX 1

//#include "usbdrv.h"

#endif // TINY_BUILD


Expand Down Expand Up @@ -456,6 +425,18 @@ void cmd_print(void);
numvar func_printf_handler(byte, byte);


// The Print object where the print command goes right now
Print *blout;

// The Print object where the print command normally goes (e.g. when not
// redirected with print #10: "foo"
Print *bloutdefault;

// The Stream where input is read from and print writes to when there is
// not output handler set.
Stream *blconsole;


/////////////////////////////////////////////
// bitlash-taskmgr.c
//
Expand Down

0 comments on commit e91dd2a

Please sign in to comment.