I've been developing the idea fully in JS, but from the outset I suspected I'd have to compile it, or perhaps bash it out in ASM.
function BiPhaseDecoder() {
// gaps
this.last_B_period = 0.0 ;
this.this_period = 0.0 ;
this.big_periods = 0.0 ;
this.small_periods = 0.0 ;
// FSM
this.in_long_gap = false ;
this.in_first_half = false ;
// booting
this.till_booted = 32 ; // arbitrary
// The bit I'm decoding
this.bit = -1 ;
// register Event
this.bitEvent = function(){};
}
// process
BiPhaseDecoder.prototype.tick = function( event_data ) {
// get the time since last crossing
this.this_period = (event_data.time - event_data.lastTime) ;
// determine if it's a long or short period
// cf: http://www.avrfreaks.net/forum/tut-pc-avr-softunderstanding-bi-phase-mark-coding
// "If it's more than 3/4 of the bit period, you've just received a zero;
// otherwise, you got half of a one."
// Note: by only ever comparing current period to long-ifyied last period, we
// can tolerate increases in speed of transmission, if gradual; and need no
// a priori data on expected rate / samps per sec.
if( (this.this_period * 4.0) > (this.last_B_period * 3.0) ) {
// this is a long period
this.last_B_period = this.this_period ;
this.in_long_gap = true ;
// get stats
this.big_periods += this.this_period ;
this.big_periods *= 0.5 ;
} else {
// otherwise a short period
this.last_B_period = this.this_period * 2.0 ; // last_B_period is always big
this.in_long_gap = false ;
// get stats
this.small_periods += this.this_period ;
this.small_periods *= 0.5 ;
} // if this_period > (3/4 * last_B_period)
// a long gap == bit 0; or two short gaps == bit 1
if( this.in_long_gap ) {
this.in_first_half = false ;
this.bit = 0 ;
} else {
if (this.in_first_half) {
this.in_first_half = false ;
this.bit = 1 ;
} else {
this.in_first_half = true ;
this.bit = -1 ; // not ready to TX yet
}
} // if in_long_gap
if( this.till_booted < 0 ) {
// emit the bit if ready
if( (this.bit >= 0) ) {
this.bitEvent( this.bit ) ;
}
} else {
// it will take some time to get a good sampling of big and small periods
this.till_booted-- ;
// keep flushing the stats till it stabilizes
this.big_periods = 0.0 ;
this.small_periods = 0.0 ;
// possibly, 'if( Math.abs( (small * 2.0) - big ) < 1e-5 ) till_booted = -1 ;'
} // if booted
} ;
Which is pretty heavy, but easier to debug. This method makes no assumptions about the short bit period, and would tolerate a 'ripple' in the transmission rate. First step would be minifying it I guess, and maybe ditching the avg. gap length I'm keeping.
I'm then pushing the 'bit' into a Uint16Array - like a LIFO - lots of shifts and carrys (probably better in ASM too) then it's just 'bitfield[4] & 0x3FFD' to find the sync word.
I didn't know about the x.y.bind(x) gotcha - thanks for that.
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
Thanks Gordon,
I've been developing the idea fully in JS, but from the outset I suspected I'd have to compile it, or perhaps bash it out in ASM.
Which is pretty heavy, but easier to debug. This method makes no assumptions about the short bit period, and would tolerate a 'ripple' in the transmission rate. First step would be minifying it I guess, and maybe ditching the avg. gap length I'm keeping.
I'm then pushing the 'bit' into a Uint16Array - like a LIFO - lots of shifts and carrys (probably better in ASM too) then it's just 'bitfield[4] & 0x3FFD' to find the sync word.
I didn't know about the x.y.bind(x) gotcha - thanks for that.