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

Commit

Permalink
Added extrapolation of the last received stackmat signal. Released
Browse files Browse the repository at this point in the history
fskube-android 0.0.4.
  • Loading branch information
jfly committed Sep 15, 2014
1 parent fc370b2 commit fd13bd9
Show file tree
Hide file tree
Showing 9 changed files with 1,094 additions and 757 deletions.
1 change: 0 additions & 1 deletion android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,3 @@
- Bump version number in `fskube-android/build.gradle`.
- `./gradlew uploadArchives`
- Go to https://bintray.com/jfly/maven/fskube/ to publish unpublished artifacts

2 changes: 1 addition & 1 deletion android/fskube-android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apply plugin: 'com.android.library'
apply plugin: 'maven'

version = '0.0.2'
version = '0.0.4'
group = "com.jflei"

android {
Expand Down
1,689 changes: 954 additions & 735 deletions release/fskube.js

Large diffs are not rendered by default.

42 changes: 39 additions & 3 deletions src/capi.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stdlib.h>
#include <time.h>

#include "fsk.h"
#include "digitizer.h"
Expand All @@ -12,21 +13,56 @@ LOG_HANDLE("capi")

using namespace fskube;

// Copied from http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/
timespec diff(timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}

#define NANOSECS_PER_MILLISEC 1000000
#define MILLISECS_PER_SEC 1000

class StackmatStateReceiver : public Receiver<StackmatState> {

private:
StackmatState state;
timespec timeLastStateWasReceived;
bool isRunning;

public:
bool receivedSomething;
StackmatState state;

StackmatStateReceiver() {
receivedSomething = false;
}

void receive(StackmatState state) {
LOG2("StackmatStateReceiver::receive() state.millis: %d", state.millis);
clock_gettime(CLOCK_MONOTONIC, &timeLastStateWasReceived);
isRunning = ( state.millis > this->state.millis );
receivedSomething = true;
this->state = state;
}

StackmatState getState() {
StackmatState fakeState = state;
if(isRunning) {
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
timespec delta = diff(timeLastStateWasReceived, now);
fakeState.millis += MILLISECS_PER_SEC * delta.tv_sec;
fakeState.millis += delta.tv_nsec / NANOSECS_PER_MILLISEC;
}
return fakeState;
}
};

static Demodulator demodulator;
Expand Down Expand Up @@ -86,7 +122,7 @@ bool fskube_addSample(double sample) {
// Only notify once about going idle, rather than repeatedly.
if(samplesWithoutData == samplesUntilOff) {
LOG1("seen %d samples without data, assuming stackmat is off or unlugged", samplesUntilOff);
stackmatStateReceiver.state = StackmatState();
stackmatStateReceiver.receive(StackmatState());
return true;
}
return false;
Expand All @@ -95,5 +131,5 @@ bool fskube_addSample(double sample) {

StackmatState fskube_getState() {
assert(initialized);
return stackmatStateReceiver.state;
return stackmatStateReceiver.getState();
}
38 changes: 29 additions & 9 deletions src/digitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ namespace fskube {

LOG_HANDLE("digitizer")

void DigitizerBase::setSamplesPerSecond(unsigned int samplesPerSecond) {
this->samplesPerSecond = samplesPerSecond;
}

void DigitizerBase::setBitsPerSecond(unsigned int bitsPerSecond) {
this->bitsPerSecond = bitsPerSecond;
}

Digitizer::Digitizer() {
}

Expand All @@ -14,14 +22,6 @@ Digitizer::Digitizer(unsigned int samplesPerSecond, unsigned int bitsPerSecond)
reset();
}

void Digitizer::setSamplesPerSecond(unsigned int samplesPerSecond) {
this->samplesPerSecond = samplesPerSecond;
}

void Digitizer::setBitsPerSecond(unsigned int bitsPerSecond) {
this->bitsPerSecond = bitsPerSecond;
}

void Digitizer::maybeSendCurrentBit() {
// Only fire a bit if we've seen a significant (ie: >= 1/2) of a bit.
if(samplesSeen >= samplesPerBit() / 2) {
Expand All @@ -32,11 +32,12 @@ void Digitizer::maybeSendCurrentBit() {
}

void Digitizer::receive(double sample) {
LOG4("receive(%f)", sample);
LOG4("sample: %f currentBit: %d", sample, currentBit);
if(currentBit == 0 && sample >= DIGITIZER_HIGH_WATER_MARK) {
maybeSendCurrentBit();
currentBit = 1;
} else if(currentBit == 1 && sample <= DIGITIZER_LOW_WATER_MARK) {
maybeSendCurrentBit();
maybeSendCurrentBit();
currentBit = 0;
} else {
Expand All @@ -52,4 +53,23 @@ void Digitizer::reset() {
currentBit = 0;
}

Analogizer::Analogizer() {
}

Analogizer::Analogizer(unsigned int samplesPerSecond, unsigned int bitsPerSecond) {
setSamplesPerSecond(samplesPerSecond);
setBitsPerSecond(bitsPerSecond);
reset();
}

void Analogizer::receive(bool bit) {
LOG4("bit: %d", bit);
for(int i = 0; i < samplesPerBit(); ++i) {
send(bit ? 1 : -1);
}
}

void Analogizer::reset() {
}

} // namespace fskube
27 changes: 20 additions & 7 deletions src/digitizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,40 @@ namespace fskube {
#define DIGITIZER_HIGH_WATER_MARK (0.6)
#define DIGITIZER_LOW_WATER_MARK (-0.6)

class Digitizer : public Sender<double, bool> {
private:
class DigitizerBase {
protected:
unsigned int samplesPerSecond;
unsigned int bitsPerSecond;

bool currentBit;
unsigned int samplesSeen;

inline int samplesPerBit() {
return samplesPerSecond / bitsPerSecond;
}
public:
void setSamplesPerSecond(unsigned int samplesPerSecond);
void setBitsPerSecond(unsigned int bitsPerSecond);
};

class Digitizer : public Sender<double, bool>, public DigitizerBase {
private:
bool currentBit;
unsigned int samplesSeen;
void maybeSendCurrentBit();
public:
Digitizer();
Digitizer(unsigned int samplesPerSecond, unsigned int bitsPerSecond);
void setSamplesPerSecond(unsigned int samplesPerSecond);
void setBitsPerSecond(unsigned int bitsPerSecond);
virtual void receive(double sample);
virtual void reset();
};

// The inverse of a Digitizer
class Analogizer : public Sender<bool, double>, public DigitizerBase {
public:
Analogizer();
Analogizer(unsigned int samplesPerSecond, unsigned int bitsPerSecond);
virtual void receive(bool bit);
virtual void reset();
};

} // namespace fskube

#endif // DIGITIZER_H
2 changes: 2 additions & 0 deletions src/fskube.i
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "rs232.h"
#include "stackmat.h"
#include "logging.h"
#include "capi.h"
%}

%include "receiversender.h"
Expand Down Expand Up @@ -69,3 +70,4 @@ class LOG_HANDLE(object):
%include "digitizer.h"
%include "rs232.h"
%include "stackmat.h"
%include "capi.h"
2 changes: 1 addition & 1 deletion src/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ inline bool isLogLevelEnabled(LogHandle *lh, int level) {
#define LOG(level, format, ...) \
do { \
if(isLogLevelEnabled(logHandle, level)) { \
fprintf(stderr, "%s/%d " format "\n", logHandle->name, level, ##__VA_ARGS__); \
fprintf(stderr, "%s/%d %s " format "\n", logHandle->name, level, __PRETTY_FUNCTION__, ##__VA_ARGS__); \
} \
} while(0);

Expand Down
48 changes: 48 additions & 0 deletions test/ExtrapolationTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3

import time
import unittest

import fskube
import FskTest

SAMPLE_RATE = 8000

class ExtrapolationTest(FskTest.FskTest):
def test(self):
stackmatSythesizer = fskube.StackmatSynthesizer()

rs232Synthesizer = fskube.Rs232Synthesizer()

analogizer = fskube.Analogizer()
analogizer.setSamplesPerSecond(SAMPLE_RATE)
analogizer.setBitsPerSecond(1200)

sampler = self.createCapturer(fskube.doubleReceiver)

stackmatSythesizer.connect(rs232Synthesizer)
rs232Synthesizer.connect(analogizer)
analogizer.connect(sampler)

fskube.fskube_initialize(SAMPLE_RATE)

# Send two states with incrementing times to simulate a running stackmat.
# We only extrapolate the signal when we think that the timer is running.
state = fskube.StackmatState()
state.millis = 40
stackmatSythesizer.receive(state)
state.millis = 500
stackmatSythesizer.receive(state)
for sample in sampler.data:
fskube.fskube_addSample(sample)

# Stop sending signals. Wait a little while, and verify that the signal
# is extrapolated.
lastSignalMillis = fskube.fskube_getState().millis
sleepSecs = 1
time.sleep(sleepSecs)
currentSignalMillis = fskube.fskube_getState().millis
self.assertGreaterEqual(currentSignalMillis, lastSignalMillis + sleepSecs*1000)

if __name__ == "__main__":
unittest.main()

0 comments on commit fd13bd9

Please sign in to comment.