rpi-softspi
Version:
Software SPI implementation to use any Raspberry Pi pins as a SPI interface
480 lines (466 loc) • 18.1 kB
JavaScript
/*
* Copyright Armin Junge
*/
var mock = require("mock-require")
mock("rpio", {
LOW: 0,
HIGH: 1,
INPUT: "I",
OUTPUT: "O",
open: function(...args){
this.result.open.push(args)
},
close: function(...args){
this.result.close.push(args)
},
write: function(...args){
args.unshift("w")
this.result.comm.push(args)
},
read: function(...args){
args.unshift("r")
this.result.comm.push(args)
return (0xca >> this.rcounter++) & 0x01 //test byte: 11001010
},
rcounter: 0,
result: {
open: [],
close: [],
comm: []
},
reset: function(){
this.result.open = []
this.result.close = []
this.result.comm = []
this.rcounter = 0
}
})
var assert = require("assert")
var rpio = require("rpio")
var SoftSPI = require("../src/softspi.js")
describe("SoftSPI", function(){
let firstClient = new SoftSPI({
clock: 23,
miso: 21,
mosi: 19,
client: 24
})
let secondClient = new SoftSPI({
clock: 23,
miso: 21,
mosi: 19,
client: 26,
clientSelect: 1, //HIGH
mode: 3,
bitOrder: SoftSPI.LSB
})
let slave = new SoftSPI({ clock: 5 })
describe("#constructor", function(){
it("should throw an exception, because mandatory clock pin is not specified", function(){
assert.throws(() => { let spi = new SoftSPI({}) },
/Clock.*specified/)
})
it("should have correct clock pin", function(){
assert.equal(slave.clock, 5)
})
it("should have the default client select trigger", function(){
assert.equal(slave.clientSelect, 0)
})
it("should have the default mode", function(){
assert.equal(slave.mode, 0)
})
it("should have the default bit order", function(){
assert.equal(slave.bitOrder, SoftSPI.MSB)
})
})
describe("#Connection", function(){
describe("-slave", function(){
describe(".open", function(){
before(function(){
rpio.reset()
slave.open()
})
it("should have opened only the clock pin as output", function(){
let expected = [
[ 5, rpio.OUTPUT, rpio.LOW ]
]
assert.deepEqual(rpio.result.open, expected)
})
it("should be valid", function(){
assert.ok(slave.valid)
})
})
describe(".close", function(){
before(function(){
slave.close()
})
it("should have closed only the clock pin", function(){
let expected = [
[ 5 ]
]
assert.deepEqual(rpio.result.close, expected)
})
it("should be invalid", function(){
assert.ok(!slave.valid)
})
})
})
describe("-firstClient", function(){
describe(".open", function(){
before(function(){
rpio.reset()
firstClient.open()
})
it("should open the first client correct", function(){
let expected = [
[ 23, rpio.OUTPUT, rpio.LOW ],
[ 24, rpio.OUTPUT, rpio.HIGH ],
[ 19, rpio.OUTPUT, rpio.LOW ],
[ 21, rpio.INPUT ]
]
assert.deepEqual(rpio.result.open, expected)
})
it("should be valid", function(){
assert.ok(firstClient.valid)
})
})
describe(".close", function(){
before(function(){
firstClient.close()
})
it("should close the first client correct", function(){
let expected = [
[ 21 ],
[ 19 ],
[ 23 ],
[ 24 ]
]
assert.deepEqual(rpio.result.close, expected)
})
it("should be invalid", function(){
assert.ok(!firstClient.valid)
})
})
})
describe("-secondClient", function(){
before(function(){
rpio.reset()
secondClient.open()
})
it("should open the second client correct", function(){
let expected = [
[ 23, rpio.OUTPUT, rpio.HIGH ],
[ 26, rpio.OUTPUT, rpio.LOW ],
[ 19, rpio.OUTPUT, rpio.LOW ],
[ 21, rpio.INPUT ]
]
assert.deepEqual(rpio.result.open, expected)
})
it("should be valid", function(){
assert.ok(secondClient.valid)
})
after(function(){
secondClient.close()
})
})
})
describe("#write", function(){
describe("-firstClient", function(){
before(function(){
rpio.reset()
firstClient.open()
})
it("should write 0xCA, 0x00, 0xff in correct way", function(){
firstClient.write([0xca, 0x00, 0xff]) //bin: 11001010, 00000000, 11111111
let expected = [ //we walk from left to right in the byte
[ "w", 24, rpio.LOW ], //client on
/* first byte */
[ "w", 19, rpio.HIGH ], //MOSI 1st bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 2nd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 3rd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 4th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 5th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 6th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 7th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 8th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
/* second byte */
[ "w", 19, rpio.LOW ], //MOSI 1st bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 2nd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 3rd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 4th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 5th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 6th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 7th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 8th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
/* third byte */
[ "w", 19, rpio.HIGH ], //MOSI 1st bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 2nd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 3rd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 4th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 5th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 6th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 7th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 8th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "w", 23, rpio.LOW ], //clock off
/* end */
[ "w", 24, rpio.HIGH ] //client off
]
assert.deepEqual(rpio.result.comm, expected)
})
after(function(){
firstClient.close()
})
})
describe("-secondClient", function(){
before(function(){
rpio.reset()
secondClient.open()
})
it("should write 0xCA in correct way", function(){
secondClient.write([0xca]) //bin: 11001010
let expected = [ //we walk from right to left in the byte
[ "w", 26, rpio.HIGH ], //client on
[ "w", 19, rpio.LOW ], //MOSI 1st bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 2nd bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 3rd bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 4th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 5th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 6th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 7th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 8th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "w", 26, rpio.LOW ] //client off
]
assert.deepEqual(rpio.result.comm, expected)
})
after(function(){
secondClient.close()
})
})
})
describe("#read", function(){
describe("-firstClient", function(){
before(function(){
rpio.reset()
firstClient.open()
})
it("should read the reversed test byte in correct way", function(){
let bytes = firstClient.read(1)
let expected = [
[ "w", 24, rpio.LOW ], //client on
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 1st bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 2nd bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 3rd bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 4th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 5th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 6th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 7th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 8th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 24, rpio.HIGH ] //client off
]
assert.deepEqual(rpio.result.comm, expected)
assert.equal(bytes[0], 0x53) //test byte reversed: 01010011
})
after(function(){
firstClient.close()
})
})
describe("-secondClient", function(){
before(function(){
rpio.reset()
secondClient.open()
})
it("should read the test byte in correct way", function(){
let bytes = secondClient.read(1)
let expected = [
[ "w", 26, rpio.HIGH ], //client on
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 1st bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 2nd bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 3rd bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 4th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 5th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 6th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 7th bit
[ "w", 23, rpio.LOW ], //clock on
[ "w", 23, rpio.HIGH ], //clock off
[ "r", 21 ], //MISO 8th bit
[ "w", 26, rpio.LOW ] //client off
]
assert.deepEqual(rpio.result.comm, expected)
assert.equal(bytes[0], 0xca)
})
after(function(){
secondClient.close()
})
})
})
describe("#transfer", function(){
describe("-slave", function(){
it("should throw an exception, because invalidity", function(){
slave.close() //get sure it"s invalid
assert.throws( () => { slave.transfer([0xca]) },
/Not initialized/)
})
it("should throw an exception, because missing MISO", function(){
slave.open()
assert.throws( () => { slave.transfer([0xca]) }, //read = true
/No input pin defined/)
slave.close()
})
it("should throw an exception, because missing MOSI", function(){
slave.open()
assert.throws( () => { slave.transfer([0xca], false) }, //write = true
/No output pin defined/)
slave.close()
})
it("should work although there is no communication", function(){
slave.open()
let bytes = slave.transfer([0xca], false, false)
assert.equal(bytes[0], 0x00)
slave.close()
})
})
describe("-firstClient", function(){
before(function(){
rpio.reset()
firstClient.open()
})
it("should transfer test byte in correct way", function(){
let bytes = firstClient.transfer([0xca])
let expected = [ //we walk from left to right in the byte
[ "w", 24, rpio.LOW ], //client on
[ "w", 19, rpio.HIGH ], //MOSI 1st bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 1st bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 2nd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 2nd bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 3rd bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 3rd bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 4th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 4th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 5th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 5th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 6th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 6th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.HIGH ], //MOSI 7th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 7th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 19, rpio.LOW ], //MOSI 8th bit
[ "w", 23, rpio.HIGH ], //clock on
[ "r", 21 ], //MISO 8th bit
[ "w", 23, rpio.LOW ], //clock off
[ "w", 24, rpio.HIGH ] //client off
]
assert.deepEqual(rpio.result.comm, expected)
assert.equal(bytes[0], 0x53) //test byte reversed: 01010011
})
after(function(){
firstClient.close()
})
})
})
})