pxt-common-packages
Version:
Microsoft MakeCode (PXT) common packages
242 lines (201 loc) • 7.19 kB
text/typescript
namespace pxsim {
export enum PinFlags {
Unused = 0,
Digital = 0x0001,
Analog = 0x0002,
Input = 0x0004,
Output = 0x0008,
Touch = 0x0010
}
export class Pin {
constructor(public id: number) { }
touched = false;
value = 0;
period = 0;
servoAngle = 0;
mode = PinFlags.Unused;
pitch = false;
pull = 0; // PullDown
eventMode = 0;
used: boolean = false;
servoContinuous: boolean;
setValue(value: number) {
// value set from the simulator
const old = this.value;
this.value = value;
const b = board();
if (b && this.eventMode == DAL.DEVICE_PIN_EVENT_ON_EDGE && old != this.value)
b.bus.queue(this.id, this.value > 0 ? DAL.DEVICE_PIN_EVT_RISE : DAL.DEVICE_PIN_EVT_FALL);
}
digitalReadPin(): number {
this.mode = PinFlags.Digital | PinFlags.Input;
return this.value > 100 ? 1 : 0;
}
digitalWritePin(value: number) {
const b = board();
this.mode = PinFlags.Digital | PinFlags.Output;
const v = this.value;
this.value = value > 0 ? 1023 : 0;
runtime.queueDisplayUpdate();
}
setPull(pull: number) {
this.pull = pull;
switch(pull) {
case 2 /*PinPullMode.PullDown*/: this.value = 0; break;
case 1 /*PinPullMode.PullUp*/: this.value = 1023; break;
default: this.value = Math_.randomRange(0, 1023); break;
}
}
analogReadPin(): number {
this.mode = PinFlags.Analog | PinFlags.Input;
return this.value || 0;
}
analogWritePin(value: number) {
const b = board();
this.mode = PinFlags.Analog | PinFlags.Output;
const v = this.value;
this.value = Math.max(0, Math.min(1023, value));
runtime.queueDisplayUpdate();
}
analogSetPeriod(micros: number) {
this.mode = PinFlags.Analog | PinFlags.Output;
this.period = micros;
runtime.queueDisplayUpdate();
}
servoWritePin(value: number) {
this.analogSetPeriod(20000);
this.servoAngle = Math.max(0, Math.min(180, value));
runtime.queueDisplayUpdate();
}
servoSetContinuous(continuous: boolean) {
this.servoContinuous = continuous;
}
servoSetPulse(pinId: number, micros: number) {
// TODO
}
isTouched(): boolean {
this.mode = PinFlags.Touch | PinFlags.Analog | PinFlags.Input;
return this.touched;
}
onEvent(ev: number, handler: RefAction) {
const b = board();
switch (ev) {
case DAL.DEVICE_PIN_EVT_PULSE_HI:
case DAL.DEVICE_PIN_EVT_PULSE_LO:
this.eventMode = DAL.DEVICE_PIN_EVENT_ON_PULSE;
break;
case DAL.DEVICE_PIN_EVT_RISE:
case DAL.DEVICE_PIN_EVT_FALL:
this.eventMode = DAL.DEVICE_PIN_EVENT_ON_EDGE;
break;
default:
return;
}
b.bus.listen(this.id, ev, handler);
}
}
export class SerialDevice {
private baudRate: number;
private rxBuffer: RefBuffer;
private txBuffer: RefBuffer;
constructor(public tx: pins.DigitalInOutPin, public rx: pins.DigitalInOutPin, private id: number) {
this.baudRate = 115200;
this.setRxBufferSize(64);
this.setTxBufferSize(64);
}
setTxBufferSize(size: number) {
this.txBuffer = control.createBuffer(size);
}
setRxBufferSize(size: number) {
this.rxBuffer = control.createBuffer(size);
}
read(): number {
return -1;
}
readBuffer(): RefBuffer {
const buf = control.createBuffer(0);
return buf;
}
writeBuffer(buffer: any) {
}
setBaudRate(rate: number) {
this.baudRate = rate;
}
redirect(tx: pins.DigitalInOutPin, rx: pins.DigitalInOutPin, rate: number) {
this.tx = tx;
this.rx = rx;
this.baudRate = rate;
}
onEvent(event: number, handler: RefAction) {
pxsim.control.internalOnEvent(this.id, event, handler);
}
onDelimiterReceived(delimiter: number, handler: RefAction): void {
// TODO
}
}
export class SPI {
frequency: number;
mode: number;
constructor(public mosi: pins.DigitalInOutPin, public miso: pins.DigitalInOutPin, public sck: pins.DigitalInOutPin) {
this.frequency = 250000;
this.mode = 0;
}
write(value: number) {
return 0;
}
transfer(command: RefBuffer, response: RefBuffer) {
}
setFrequency(frequency: number) {
this.frequency = frequency;
}
setMode(mode: number) {
this.mode = mode;
}
}
export class I2C {
constructor(public sda: pins.DigitalInOutPin, public scl: pins.DigitalInOutPin) {
}
readBuffer(address: number, size: number, repeat?: boolean): RefBuffer {
return control.createBuffer(0);
}
writeBuffer(address: number, buf: RefBuffer, repeat?: boolean): number {
return 0;
}
}
export interface EdgeConnectorProps {
pins: number[];
servos?: {
[name: string]: number;
}
}
export class EdgeConnectorState {
pins: Pin[];
private _i2cs: I2C[] = [];
private _spis: SPI[] = [];
private _serials: SerialDevice[] = [];
constructor(public props: EdgeConnectorProps) {
this.pins = props.pins.map(id => id != undefined ? new Pin(id) : null);
}
public getPin(id: number) {
return this.pins.filter(p => p && p.id == id)[0] || null
}
createI2C(sda: pins.DigitalInOutPin, scl: pins.DigitalInOutPin) {
let ser = this._i2cs.filter(s => s.sda == sda && s.scl == scl)[0];
if (!ser)
this._i2cs.push(ser = new I2C(sda, scl));
return ser;
}
createSPI(mosi: pins.DigitalInOutPin, miso: pins.DigitalInOutPin, sck: pins.DigitalInOutPin) {
let ser = this._spis.filter(s => s.mosi == mosi && s.miso == miso && s.sck == sck)[0];
if (!ser)
this._spis.push(ser = new SPI(mosi, miso, sck));
return ser;
}
createSerialDevice(tx: pins.DigitalInOutPin, rx: pins.DigitalInOutPin, id: number): SerialDevice {
let ser = this._serials.filter(s => s.tx == tx && s.rx == rx)[0];
if (!ser)
this._serials.push(ser = new SerialDevice(tx, rx, id));
return ser;
}
}
}