Vernier EasyData: ------------------------------------------------------------------------------------------------------------------- _InitVernierDevice: 5254h: Initializes a Vernier EasyData device. Inputs: A is page of callback routine (details below). HL is address of callback routine (details below). Outputs: A is error code: 000h: success. Returns device info. 0FCh: an A cable is not plugged in? 0FDh: device was not Vernier EasyData probe. Returns device info. 0FEh: the calculator is the host and is already initialized? Returns device info. 0FFh: there was a generic error (in _InitializeUSBDevice, called internally). Returns carry flag set if problems (A is non-zero). _KillVernierDevice: 5257h: 5311h: Kills a Vernier EasyData device. Outputs: A is error code: 000h: success. Returns device info. Returns carry flag set if problems (but there won't be). _SendVernierCommand: 525Ah: Sends a command to a connected Vernier EasyData device. Inputs: HL is address of send structure. Outputs: A is error code: 000h: success. Returns device info. 0FFh: unknown or device is not peripheral. Returns carry flag set if problems (A is non-zero). Send structure is as follows: DW wOutputBuffer ;pointer to 8-byte buffer containing data to send DB bFlag ;1 on send attempt, 0 on successful send, 0FFh on error DB bCallbackPage ;page of callback routine DW wCallbackAddress ;address of callback routine The callback routine should check bFlag to see what happened. 0FFh means there was some sort of error, zero means it successfully sent the 8-byte packet. _EnableVernierReads: 525Dh: Initializes the calculator to receive data from the connected Vernier EasyData device. Inputs: HL is address of receive structure. Set to 0 to NAK probe's send attempts (appear busy). Outputs: A is error code: 000h: success. Returns device info. 0FFh: unknown, device is not peripheral, or passed-in structure address is zero. Returns carry flag set if problems (A is non-zero). This receives 8 bytes at a time. Receive structure is as follows: DW wInputBuffer ;pointer to 8-byte buffer to store input data DB bFlag ;1 on receive attempt, 0 on successful read, 0FFh on error DB bCallbackPage ;page of callback routine DW wCallbackAddress ;address of callback routine The callback routine should check bFlag to see what happened. 0FFh means there was some sort of error, zero means it successfully read 8 bytes. _DisableVernierReads: 5260h: Stops the calculator from being able to receive data from the connected Vernier EasyData device. Outputs: A is error code: 000h: success. Returns device info. Returns carry flag set if problems (but there won't be). The calculator will NAK any attempts by the device to send data (so it appears as busy). Device information is (sometimes) returned from these routines: BC: vendor ID HL: product ID DE: release number Vernier EasyData Callback: This is called at various times during initialization or kill. B=1 is always passed. (9C28h) is an indicator about the current state: 1: explicit initialization with _InitializeUSB device or similar is occurring. 2: ? 3: ? 4: ? 5: ? 6: ? ------------------------------------------------------------------------------------------------------------------- Calculator<->Calculator: ------------------------------------------------------------------------------------------------------------------- _InitializeUSBDevice: 5290h: Initializes the USB device as either host or peripheral. Kills the USB device and returns carry flag set if anything is wrong (including trying to connect to non-compatible device (anything other than an 84+, 84+SE, ViewScreen, or EasyData probe). This seems designed to work when acting as peripheral, too, though I'm not sure it really does anything. Destroys all. _KillUSBDevice: 5293h: Kills a connected USB peripheral. Inputs: Reset 6,(iy+41h) to not completely kill it. Destroys A. _SendUSBData: 50F2h: Sends USB data as either host or peripheral. Inputs: DE is number of bytes. Outputs: HL is pointer to memory in "zone 1" (pages 83h\82h swapped in last two banks). Returns carry flag set if anything went wrong. There are no routines to read/write memory in zone 1. Do it yourself. Destroys all. When the interrupt detects data to be read, it will set dataReady,(iy+USBflags2) and zero out (9C27h) (number of bytes left to receive, except for zero to start with). When this bit is set, receive the data until it is no longer set. Unfortunately, there is no USB receive entry point, but you can use the code below from the OS to reproduce it: ReceiveUSBData: Receives USB data as either host or peripheral. Inputs: HL is address of buffer to receive bytes in memory. B is the expected number of bytes to receive. Outputs: C is the number of actual received bytes. HL points after the received bytes, for successive calls. The maximum amount of bytes you can receive at once with this routine is 64. Keep calling it until dataReady,(iy+USBflag2) is reset. Carry flag is returned if there are any problems. USBflags2 equ 41h dataReady equ 5 ReceiveUSBData: ld a,b or a ret z ld a,40h cp b ret c ld a,b ld (9C80h),a ld a,(9C27h) or a jr z,$F cp b jr nc,$F ld b,a ld (9C80h),a $$: in a,(8Fh) bit 2,a jr z,calcIsPeripheral xor a out (5Bh),a ld a,(9C27h) or a jr nz,receiveHost ld a,1 out (8Eh),a ld a,21h out (9Ah),a xor a in a,(9Ah) ld a,8 out (93h),a xor a in a,(93h) ld a,0FFh out (89h),a xor a out (95h),a in a,(89h) ld a,0A1h out (8Bh),a in a,(94h) bit 2,a jr nz,inputError bit 6,a jr nz,inputError ld a,1 out (5Bh),a ld a,(9C27h) or a jr nz,receiveHost ld a,1 out (8Eh),a in a,(94h) in a,(96h) receiveHost: push af ld a,(9C80h) ld b,a ld c,0 receiveHostLoop: in a,(0A1h) ld (hl),a inc hl inc c djnz receiveHostLoop ld a,1 ld (8Eh),a in a,(94h) bit 2,a jr nz,P1inputError bit 6,a jr nz,P1inputError pop af sub c ld (9C27h),a set dataReady,(iy+USBflags2) ret nz ld a,1 out (8Eh),a ld a,21h out (9Ah),a ld a,8 out (93h),a xor a in a,(93h) ld a,0Eh out (89h),a xor a out (95h),a res dataReady,(iy+USBflags2) xor a ld (9C27h),a res 0,(iy+USBflags2) ld a,20h out (94h),a ld a,1 out (5Bh),a ret P1inputError: pop af inputError: res 2,(iy+40h) scf receiveDone: ei ld a,1 out (5Bh),a res 0,(iy+USBflags2) ret calcIsPeripheral: ld a,2 out (8Eh),a in a,(94h) bit 6,a jr z,$F and 0DFh out (94h),a pop af B_CALL KillUSBDevice jr inputError $$: ld a,(9C27h) or a jr nz,$F in a,(96h) push af ld c,0 receivePeriphLoop: in a,(0A2h) ld (hl),a inc hl inc c djnz receivePeriphLoop ld a,2 out (8Eh),a pop af sub c ld (9C27h),a ret nz xor a ld (9C27h),a in a,(94h) and 0FEh out (94h),a res dataReady,(iy+USBflags2) ld a,0A1h out (8Bh),a jr receiveDone