Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Separated fskube.h into fsk.h, rs232.h, and stackmat.h. This lets each
Browse files Browse the repository at this point in the history
use their own log handle.
  • Loading branch information
jfly committed May 23, 2014
1 parent 7c2b54b commit f5ca82b
Show file tree
Hide file tree
Showing 11 changed files with 2,006 additions and 1,981 deletions.
32 changes: 15 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ SRC := src
RELEASE := release
CXX := clang++
CFLAGS := -Wall -std=c++11 -Wno-c++11-narrowing
INC := -I/usr/include/python3.3m -I/usr/include/python3.2 -I$(SRC)
PYTHON_INC := -I/usr/include/python3.3m -I/usr/include/python3.2
INC := -I$(SRC)

PYTHONWRAPPER_OBJS := $(BLD)/fskube.o $(BLD)/fskube_wrap.o $(BLD)/logging.o
FSKUBE_SRCS := $(BLD)/fsk.cpp $(BLD)/rs232.cpp $(BLD)/stackmat.cpp $(BLD)/logging.cpp
FSKUBE_OBJS := $(FSKUBE_SRCS:.cpp=.o)
PYTHONWRAPPER_OBJS := $(FSKUBE_OBJS) $(BLD)/fskube_wrap.o

# Create BLD and RELEASE directory if necessary
$(shell mkdir -p $(BLD) $(RELEASE))

.PHONY: all py js jsmin check clean serve release

default: $(BLD)/fskube.o
default: $(FSKUBE_OBJS)

all: default py js jsmin

Expand All @@ -29,7 +32,7 @@ jsmin: $(BLD)/fskube.min.js
-include $(PYTHONWRAPPER_OBJS:.o=.d)

$(BLD)/_fskube.so: $(PYTHONWRAPPER_OBJS)
$(CXX) -shared $(CFLAGS) $(INC) $^ -o $@
$(CXX) -shared $^ -o $@

$(RELEASE)/fskube.js: $(BLD)/fskube.js
cp $^ $@
Expand All @@ -48,23 +51,18 @@ $(BLD)/%.cpp: $(SRC)/%.cpp
.PRECIOUS: $(BLD)/%.cpp

$(BLD)/%.o: $(BLD)/%.cpp
$(CXX) -c -fPIC $(CFLAGS) $(INC) $< -o $@
$(CXX) -MM -MT $(BLD)/$*.o $(CFLAGS) $(INC) $< > $(BLD)/$*.d
$(CXX) -c -fPIC $(CFLAGS) $(INC) $(PYTHON_INC) $< -o $@
$(CXX) -MM -MT $(BLD)/$*.o $(CFLAGS) $(INC) $(PYTHON_INC) $< > $(BLD)/$*.d

# These targets don't actually depend on fskube.o, but they
# should get remade whenever fskube.o is remade, so it's listed
# as a dependency.
$(BLD)/fskube.py $(BLD)/fskube_wrap.cpp $(BLD)/fskube_wrap.h: $(BLD)/fskube.o $(SRC)/fskube.i
$(BLD)/fskube.py $(BLD)/fskube_wrap.cpp $(BLD)/fskube_wrap.h: $(FSKUBE_SRCS) $(SRC)/fskube.i
swig -builtin -python -c++ -o $(BLD)/fskube_wrap.cpp $(SRC)/fskube.i

# Similar trick as above: fskube.js doesn't actually depend on
# fskube.o/logging.o, but every time fskube.o/logging.o gets remade,
# fskube.js should be remade as well.
$(BLD)/fskube.js: $(BLD)/fskube.o $(BLD)/logging.o $(SRC)/embind.cpp $(SRC)/wrap_c.js
em++ $(CFLAGS) --bind $(SRC)/embind.cpp $(SRC)/fskube.cpp $(SRC)/logging.cpp -s EXPORTED_FUNCTIONS="['_getLogLevels', '_setLogLevels']" --post-js $(SRC)/wrap_c.js -o $@
# Similar dependency trick as above.
$(BLD)/fskube.js: $(FSKUBE_SRCS) $(SRC)/embind.cpp $(SRC)/wrap_c.js
em++ $(CFLAGS) $(INC) --bind $(SRC)/embind.cpp $(FSKUBE_SRCS) -s EXPORTED_FUNCTIONS="['_getLogLevels', '_setLogLevels']" --post-js $(SRC)/wrap_c.js -o $@

$(BLD)/fskube.min.js: $(BLD)/fskube.o $(BLD)/logging.o $(SRC)/embind.cpp $(SRC)/wrap_c.js
em++ --bind $(SRC)/embind.cpp $(SRC)/fskube.cpp $(SRC)/logging.cpp -s EXPORTED_FUNCTIONS="['_getLogLevels', '_setLogLevels']" --closure 1 -O3 --post-js $(SRC)/wrap_c.js -o $@
$(BLD)/fskube.min.js: $(FSKUBE_SRCS) $(SRC)/embind.cpp $(SRC)/wrap_c.js
em++ $(CFLAGS) $(INC) --bind $(SRC)/embind.cpp $(FSKUBE_SRCS) -s EXPORTED_FUNCTIONS="['_getLogLevels', '_setLogLevels']" --post-js $(SRC)/wrap_c.js -o $@ --closure 1 -O3

check: py
PYTHONPATH=$(BLD) python3 -m unittest discover -s test/ -p *Test.py
Expand Down
3,413 changes: 1,700 additions & 1,713 deletions release/fskube.js

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/embind.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <emscripten/bind.h>
#include "fskube.h"
#include "fsk.h"
#include "rs232.h"
#include "stackmat.h"
#include "logging.h"

using namespace emscripten;
Expand Down
189 changes: 2 additions & 187 deletions src/fskube.cpp → src/fsk.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#include <assert.h>
#include <math.h>
#include <cmath>
#include "fskube.h"
#include "fsk.h"
#include "logging.h"

namespace fskube {

LOG_HANDLE("fskube")
LOG_HANDLE("fsk")

Modulator::Modulator(FskParams fsk) : fsk(fsk) {
reset();
Expand Down Expand Up @@ -190,188 +189,4 @@ void Demodulator::addFrequencyHalfSeen(unsigned int frequency) {
}
}

Rs232or::Rs232or() {}

void Rs232or::receive(int data) {
if(data < 0) {
// Send our "idle" signal (low) for a good little while.
for(int j = 0; j < 8*3; j++) {
send(0);
}
return;
} else {
// start signal (high)
send(1);

// send bits of char, least significant first (little endian)
for(int i = 0; i < 8; i++) {
bool bit = (data >> i) & 1;
send(bit);
}

// stop signal (low)
send(0);
}
}

DeRs232or::DeRs232or() {
reset();
}

void DeRs232or::reset() {
waitingForStart = true;
idleCount = 0;
inProgressChar = 0;
}

void DeRs232or::receive(bool b) {
if(waitingForStart) {
if(b == 1) {
waitingForStart = false;
nthBit = 0;
} else {
idleCount++;
send(-1); // -1 means idle
}
return;
}

if(nthBit == 8) {
// We've filled up inProgressChar. We expect this next bit to be a
// stop signal (low). If it isn't, we drop it.
if(b == 0) {
send(inProgressChar);
} else {
LOG1("Throwing away incomplete character %d", inProgressChar);
}
waitingForStart = true;
idleCount = 0;
inProgressChar = 0;
}

inProgressChar |= (b << nthBit);
nthBit++;
}


StackmatSynthesizer::StackmatSynthesizer() {}

#define MILLIS_PER_MINUTE (60*1000)
#define MILLIS_PER_SECOND (1000)
#define MILLIS_PER_DECISECOND (100)
#define MILLIS_PER_CENTISECOND (10)

void StackmatSynthesizer::receive(StackmatState state) {
send(state.commandByte);

int checksum = 64;
int millis = state.millis;

// minutes
int minutes_digit = millis / MILLIS_PER_MINUTE;
millis %= MILLIS_PER_MINUTE;
checksum += minutes_digit;
send('0' + minutes_digit);

// seconds
int seconds = millis / MILLIS_PER_SECOND;
millis %= MILLIS_PER_SECOND;

int dekaseconds_digit = seconds / 10;
checksum += dekaseconds_digit;
send('0' + dekaseconds_digit);

int seconds_digit = seconds % 10;
checksum += seconds_digit;
send('0' + seconds_digit);

// decimal
int deciseconds_digit = millis / MILLIS_PER_DECISECOND;
millis = millis % MILLIS_PER_DECISECOND;
checksum += deciseconds_digit;
send('0' + deciseconds_digit);

int centiseconds_digit = millis / MILLIS_PER_CENTISECOND;
millis = millis % MILLIS_PER_CENTISECOND;
checksum += centiseconds_digit;
send('0' + centiseconds_digit);

if(state.generation == 3) {
int milliseconds_digit = millis;
checksum += milliseconds_digit;
send('0' + milliseconds_digit);
}

// checksum
send(checksum);

// LF
send('\n');

// CR
send('\r');

// idle
send(-1);
}

StackmatInterpreter::StackmatInterpreter() {
reset();
}

void StackmatInterpreter::reset() {
receivedBytesLength = 0;
}

void StackmatInterpreter::receive(int byte) {
LOG2("StackmatInterpreter::receive(%d)", byte);
if(byte < 0) {
// idle received, parse collected characters
switch(receivedBytesLength) {
case GEN2SIGNAL_BYTES:
case GEN3SIGNAL_BYTES: {
StackmatState state;
if(receivedBytesLength == GEN2SIGNAL_BYTES) {
state.generation = 2;
} else if(receivedBytesLength == GEN3SIGNAL_BYTES) {
state.generation = 3;
} else {
assert(false);
}
state.commandByte = receivedBytes[0];

state.millis = 0;
state.millis += (receivedBytes[1] - '0') * MILLIS_PER_MINUTE;

int seconds = 10 * (receivedBytes[2] - '0') + (receivedBytes[3] - '0');
state.millis += seconds * MILLIS_PER_SECOND;
state.millis += (receivedBytes[4] - '0') * MILLIS_PER_DECISECOND;
state.millis += (receivedBytes[5] - '0') * MILLIS_PER_CENTISECOND;
if(state.generation == 3) {
state.millis += (receivedBytes[6] - '0');
}

send(state);
receivedBytesLength = 0;
break;
}
default:
LOG1("Throwing away partial signal of %d bytes" , receivedBytesLength);
break;
}
return;
}

if(receivedBytesLength >= LARGESTSIGNAL_BYTES) {
// Uh oh. We've received more bytes than can possibly comprise
// a stackmat signal. We should have seen an idle by now.
// We have nothing better to do than to throw away what we've seen so far.
LOG1("Throwing away run on signal");
reset();
return;
}

receivedBytes[receivedBytesLength++] = byte;
}

} // namespace fskube
60 changes: 3 additions & 57 deletions src/fskube.h → src/fsk.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef FSKUBE_H
#define FSKUBE_H
#ifndef FSK_H
#define FSK_H

#include "receiversender.h"

Expand Down Expand Up @@ -69,60 +69,6 @@ class Demodulator : public Sender<double, bool> {
void flush();
};

// Convert bytes <-> bits via 8-N-1
// See http://en.wikipedia.org/wiki/8-N-1

class Rs232or : public Sender<int, bool> {
public:
Rs232or();
virtual void receive(int data);
};

class DeRs232or : public Sender<bool, int> {
private:
bool waitingForStart;
unsigned int idleCount;

unsigned char inProgressChar;
unsigned int nthBit;
public:
DeRs232or();
virtual void receive(bool b);
void reset();
};

// Convert bytes <-> StackmatState's according to the stackmat protocol
// See http://hackvalue.de/hv_atmel_stackmat

#define GEN2SIGNAL_BYTES 9
#define GEN3SIGNAL_BYTES 10
#define LARGESTSIGNAL_BYTES GEN3SIGNAL_BYTES

struct StackmatState {
unsigned int millis;
unsigned int generation;
unsigned char commandByte;
bool operator==(StackmatState& o) const {
return millis == o.millis && generation == o.generation && commandByte == o.commandByte;
}
};

class StackmatSynthesizer : public Sender<StackmatState, int> {
public:
StackmatSynthesizer();
virtual void receive(StackmatState s);
};

class StackmatInterpreter : public Sender<int, StackmatState> {
private:
int receivedBytes[LARGESTSIGNAL_BYTES];
int receivedBytesLength;
public:
StackmatInterpreter();
void reset();
virtual void receive(int byte);
};

} // namespace fskube

#endif // FSKUBE_H
#endif // FSK_H
13 changes: 8 additions & 5 deletions src/fskube.i
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
%array_class(bool, boolArray);

%{
/* Includes the header in the wrapper code */
#include "fskube.h"
#include "fsk.h"
#include "rs232.h"
#include "stackmat.h"
#include "logging.h"
%}

/* Parse the header file to generate wrappers */
%include "receiversender.h"
%include "logging.h"

%copyctor fskube::StackmatState;

/* It looks like this is causing issues on swig 2 =(
/*
It looks like this is causing issues on swig 2 =(
%typemap(directorin) fskube::StackmatState {
// Simulate C style pass by value semantics by constructing a new StackmatState object
// on the heap and letting python's garbage collector manage the object. If we don't do this,
Expand Down Expand Up @@ -60,4 +61,6 @@ class LOG_HANDLE(object):
%template(stackmatstateReceiver_intSender) fskube::Sender<fskube::StackmatState, int>;
%template(intReceiver_stackmatstateSender) fskube::Sender<int, fskube::StackmatState>;

%include "fskube.h"
%include "fsk.h"
%include "rs232.h"
%include "stackmat.h"
2 changes: 1 addition & 1 deletion src/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ static unsigned int nextLogHandleId = 0;
#define MAX_LOG_HANDLE_DESC_LENGTH (MAX_LOG_HANDLE_LENGTH + 1 + (MAX_LOG_LEVEL + 1))
static char logLevels[MAX_LOG_HANDLES * (MAX_LOG_HANDLE_DESC_LENGTH + 1) + 1];

const char *LOGGING_ENV_VAR = "FSKUBE_LOGGING";
static const char *LOGGING_ENV_VAR = "FSKUBE_LOGGING";

void readLogLevels(LogHandle *lh) {
// First, disable all log levels
Expand Down
Loading

0 comments on commit f5ca82b

Please sign in to comment.