;Printing routines include "settings.inc" include "ti83plus.inc" include "equates.inc" include "usb8x.inc" SEGMENT Main GLOBALS ON EXTERN IPutS,IGetKey,IPutS11,DispHexA,DispHexHL,LDL_startPrintJob,PCL_startPrintJob,PCL_sendData,PCL_stopPrintJob,LDL_stopPrintJob EXTERN LDL_ejectPage Var PrintInPipe,1 ; 1; Var PrintOutPipe,1 ; 1; Var PrintAlternate,1 ; 1; Var PrintInterface,1 ; 1; PrinterInit: ;Initializes the printer ;Input: None ;Output: Returns C if problems ;Uses tempSwapArea and OP6 as temporary RAM ;Should work where printer interface is on different interface (alternate 00), but STALLs for some reason ;Works when printer interface is on different alternate (interface 00) ld hl,tempSwapArea ld bc,256 B_CALL MemClear U_CALL HostInit ld a,errPrintInit ret c ld hl,SetInterface ld de,tempSwapArea ld bc,8 ldir ld de,PrintCallback U_CALL SetCallBack ld b,1 U_CALL ConfigureDevice ld hl,tempSwapArea+8 ld b,descConfig U_CALL ReadDescriptor ld hl,tempSwapArea+8 ld b,descInterface U_CALL FindDescriptor jr piLoop $$: ld hl,(OP6) ld b,descInterface call myFindDescriptor piLoop: ret c ld (OP6),hl inc hl inc hl ld a,(hl) ld (PrintInterface),a inc hl ld a,(hl) ld (PrintAlternate),a inc hl ld a,(hl) ld (OP6+3),a inc hl ld a,(hl) cp 07h jr nz,$B inc hl ld a,(hl) cp 01h jr nz,$B inc hl ld a,(hl) ; cp 01h ; jr z,$F cp 02h jr nz,$B $$: ld a,(PrintAlternate) ld (tempSwapArea+2),a ld a,(PrintInterface) ld (tempSwapArea+4),a ld hl,tempSwapArea ld b,0 U_CALL SendControlData ret c ld hl,(OP6) call mySetupPipe ret c ld a,(OP6+3) dec a ret z ld hl,(OP6) ld b,descEndpoint call myFindDescriptor mySetupPipe: ld b,descEndpoint call myFindDescriptor ret c inc hl inc hl ld b,(hl) inc hl inc hl ld d,(hl) srl d srl d srl d jr nz,$F inc d $$: ld a,b bit 7,b res 7,b ld c,pipeBulk jr nz,$F ld hl,PrintOutPipe ld (hl),b U_CALL SetupOutPipe ret $$: ld (PrintInPipe),a U_CALL SetupInPipe ret $$: inc hl ld a,(hl) cp b dec hl ret z or a scf ret z myFindDescriptor: ld d,0 ld e,(hl) add hl,de jr $B SendSoftReset: ;Sends soft reset command to printer, flushing all STALL conditions and leaving configuration intact ;Input: None ;Output: Returns C if problems ;Uses tempSwapArea as temporary RAM scf ret ;this function screws up sometimes, for some reason ld hl,SoftReset ld de,tempSwapArea push de ld bc,8 ldir ld a,(PrintInterface) ld (tempSwapArea+4),a pop hl ld b,0 U_CALL SendControlData ret nc ld hl,BadSoftReset ;USB 1.0 spec incorrectly documented this and some devices expect it push hl ld de,tempSwapArea ld bc,8 ldir ld a,(PrintInterface) ld (tempSwapArea+4),a pop hl ld b,0 U_CALL SendControlData ret GetPrinterStatus: ;Gets paper and error status of printer ;Input: None ;Output: A is flags byte ; Bit 0: Set means no error ; Bit 1: Set means printer selected ; Bit 2: Set means paper tray is empty ; Returns C if problems ;Usess tempSwapArea as temporary RAM ;These codes should not be trusted as a printer ; returns the default "no error, paper and printer ready" if real status cannot be determined ld hl,GetPortStatus ld de,tempSwapArea push de ld bc,8 ldir ld a,(PrintInterface) ld (tempSwapArea+5),a pop hl ld b,1 push de U_CALL SendControlData pop de ret c ld a,(de) srl a srl a srl a ; or a ret GetPrinterCapabilities: ;Gets printer name and model information as well as supported protocols (page description languages) ;Input: HL points to place to store zero-terminated table of supported protocols/PDLs ; DE points to place to store ID string ;Output: Buffers are filled appropriately ; C set if problems ;Uses appData and ramCode as temporary RAM ld (appData),hl ld (appData+2),de ld hl,appData+12 ld bc,512 B_CALL MemClear ld hl,GetDeviceID ld de,appData+4 push de ld bc,8 ldir ld a,(PrintAlternate) ld (appData+8),a ld a,(PrintInterface) ld (appData+9),a pop hl ld de,appData+12 ld b,2 U_CALL SendControlData ret c ld hl,appData+10 ld de,appData+13 ld a,(de) ld b,a ld (hl),a ld hl,appData+4 dec de push de U_CALL SendControlData ret c pop hl ;capabilities string is at HL => appData+12, start parsing inc hl ;skip size bytes inc hl getcap_parse: xor a cp (hl) jr z,getcap_done ld de,sMfg call cmpstrings ld de,appData+256 jr z,getcap_copy ld de,sManufacturer call cmpstrings ld de,appData+256 jr z,getcap_copy ld de,sModel call cmpstrings ld de,appData+384 jr z,getcap_copy ld de,sMdl call cmpstrings ld de,appData+384 jr z,getcap_copy ld de,sCommandSet call cmpstrings ld de,(appData) jr z,getcap_copy ld de,sCmd call cmpstrings ld de,(appData) jr z,getcap_copy $$: ld a,(hl) inc hl cp ';' jr nz,$B jr getcap_parse getcap_done: ;combine strings and store in buffers ld hl,appData+256 ld de,(appData+2) $$: ld a,(hl) or a jr z,$F ld (de),a inc hl inc de or a jr $B $$: ld a,'/' ld (de),a inc de ld hl,appData+384 $$: ld a,(hl) ld (de),a inc hl inc de or a jr nz,$B xor a ld (de),a ld hl,(appData) getcap_PDLs: ld a,(hl) ld b,a cp ',' jr nz,$F xor a $$: ld (hl),a inc hl ld a,b or a jr nz,getcap_PDLs ld (hl),a ret getcap_copy: ld a,':' $$: cp (hl) inc hl jr nz,$B $$: ld a,(hl) cp ';' jr z,$F ld (de),a inc hl inc de jr $B $$: xor a ld (de),a inc hl jr getcap_parse cmpstrings: push de push hl call cmpstrings_sub pop hl pop de ret cmpstrings_sub: ld a,(de) or a ret z cp (hl) ret nz inc hl inc de jr cmpstrings_sub sManufacturer: DB "MANUFACTURER:",0 sMfg: DB "MFG:",0 sCommandSet: DB "COMMAND SET:",0 sCmd: DB "CMD:",0 sModel: DB "MODEL:",0 sMdl: DB "MDL:",0 IsLanguageSupported: ;Returns whether printer driver supports specified page description language ;Input: HL points to zero-terminated PDL string ;Output: C set if language not supported ;Destroys A, DE ld de,sLangTable IsPrinterCompatible: ;Returns whether connected printer supports specified page description language ;Input: HL points to zero-terminated PDL string ; DE points to zero-terminated table of supported PDLs (from GetPrinterCapabilities) ;Output: C set if language not supported ;Destroys A ils_loop: ld a,(de) or a scf ret z call cmpstrings jr z,ils_good $$: ld a,(de) inc de or a jr nz,$B jr ils_loop ils_good: or a ret sLangTable: sPCL: DB "PCL",0 sLDL: DB "LDL",0 DB 0 StartPrintJob: ;Starts print job ;Input: None ;Output: Printer job started ; Returns C if problems ld hl,saveSScreen ld de,tempSwapArea call GetPrinterCapabilities ld de,saveSScreen ld hl,sPCL call IsPrinterCompatible jr nc,SPJ_PCL ld de,saveSScreen ld hl,sLDL call IsPrinterCompatible ret c ;LDL start print job call LDL_startPrintJob scf ret SPJ_PCL: call PCL_startPrintJob scf ret PrintData: ;Prints data passed to it ;Input: HL points to data to send ; BC is number of bytes to send ;Output: Data printed ;Returns C if problems ;This is the high-level "do the printing" function push hl push bc ld hl,saveSScreen ld de,tempSwapArea call GetPrinterCapabilities ld de,saveSScreen ld hl,sPCL call IsPrinterCompatible jr nc,sendPJ_PCL ld de,saveSScreen ld hl,sLDL call IsPrinterCompatible pop bc pop hl ret c ;LDL send print data call LDL_ejectPage scf ret sendPJ_PCL: pop bc pop hl call PCL_sendData scf ret SendPrintData: ;Sends data directly to the printer ;Input: HL points to data to send ; BC is number of bytes to send ;Output: Data is sent to printer ; Returns C if problems ;Destroys appData ld de,appData push bc ldir pop bc ld hl,appData ld b,c ld a,(PrintOutPipe) ld c,a U_CALL SendData ret ReceivePrintData: ;Receives data directly from printer ;Input: None ;Output: Data received ;Returns C if problems ld a,(PrintInPipe) ld b,a U_CALL ReqData ret StopPrintJob: ;Stops print job and prints any pages in buffer ;Input: None ;Output: Printer job stopped and pages are printed ; Returns C if problems ld hl,saveSScreen ld de,tempSwapArea call GetPrinterCapabilities ld de,saveSScreen ld hl,sPCL call IsPrinterCompatible jr nc,StopPJ_PCL ld de,saveSScreen ld hl,sLDL call IsPrinterCompatible ret c ;LDL stop print job call LDL_stopPrintJob scf ret StopPJ_PCL: call PCL_stopPrintJob scf ret PrintCallback: ld hl,sCallback call IPutS ret sCallback: DB "Callback called!",0 ;for some reason SetInterface: DB 01h,11,00h,00h,00h,00h,00h,00h GetPortStatus: DB 10100001b,1,0,0,0,0,1,0 BadSoftReset: DB 00100011b,2,0,0,0,0,0,0 SoftReset: DB 00100001b,2,0,0,0,0,0,0 GetDeviceID: DB 10100001b,0,0,0,0,0,2,0