;From: andrew.mcmeikan at mitswa.com.au ;be carefull when assembling ;there is a lookup table that MUST NOT cross a ;256 byte boundry ---- CHECK IT LIST P=16C84, F=INHX8M ;thermal printer controler innerloop = 0ff lilloop = 01 bigloop =0ff strobe macro bt SETB $13.bt ;bit for strobe CLRB 0b.7 ;dont want interupts CALL outsr ;clock it out CALL lildly ;let it burn in SETB 0b.7 ;re-enable interupts CLRB $13.bt ;so next outsr clears it endm ORG $0000 JMP main ORG $0004 ;entry occurs in here when host pulls strobe signal low ;to indicate data that requires printing ;useing this int routine occupies two levels of stack ;one for the return address and one for outsr's return ;centronics pinouts ; pin 1 strobe is connected to RB0 ; pin 2 data1 " " RA1 ; pin 3 data2 " " RA2 ; pin 4 data3 " " RA3 ; pin 5 data4 " " RA4 ; pin 6 data5 " " RB1 ; pin 7 data6 " " RB2 ; pin 8 data7 " " RB3 ; pin 9 data8 " " RB4 ; pin10 ack " " Cap from BSY this dips low ; when want next byte ; pin11 busy is connected to RA0 High= offline ; pin12 Paper out is connected to photocell High=no paper ;pins 19 to 30 are signal grounds GND ; pin31 INT is connected to RESET (via diode) ; and is used to initialize printer MOV 0c, W ;save 'W' in reg file 0c MOV W, <>3 ;grab the flags MOV 0d, W ;in reg 'd' ;should now be safe to continue! SETB 5.0 ;say we are busy ;read both ports to get byte of data MOV W, >>5 ;read port a shifting data down one AND W, #0f ;only keep bottom bits MOV $16, W ;keep incomming data here MOV W, >>6 ;read port b shifting down one AND W, #0f ;wipe out extraneous bits MOV $17, W ;waste another register MOV W, <>$17 ;get 'b' data lower into upper W OR $16, W ;or top bits into data ;bit pattern from host now in 0x16 INC 0e ;increment our count of bytes ;clock data into thermal head MOV W, #08 ;for 8 bits MOV $17, W ;better keep count of it clkhd: RL $16 ;rotate it thru carry SETB $12.4 ;set data high SB 3.0 ;check the carry flag CLRB $12.4 ;clear data if required CALL outsr SETB $12.5 ;clock that bit in CALL outsr CLRB $12.5 ;drop clock again CALL outsr DECSZ $17 ;have we finished loop yet ? JMP clkhd ;guess not ;no point doing the extra shift as we are just ;throwing the data away once it is in the head ;if byte count=max then lets latch and let the main routine ; print it MOV W, #$c0 ;try 192 ;216 max bytes per line 1728 bits MOV W, 0e-w ;check max against our byte count SB 3.2 ;the same? result of zero? JMP continue ;no its ok, head not full yet ;need to latch thermal head ; We do not not lower busy here ;as main routine will do so once it has reset ;the counter. SETB $12.6 ;latch bit for thermal head CALL outsr ;send- no one else better be using it CLRB $12.6 ;put back CALL outsr ;send that to JMP exint ;leave int handler continue: ;tell host we are no longer busy, get next byte CLRB 5.0 ;bring BSY low ;and fall thru to exit :) exint: ;now restore to before interupt MOV W, <>0d ;put flags back in order in W MOV 3, W ;stickem bick in flags SWAP 0c ;flip saved W MOV W, <>0c ;flip it back into W CLRB 0b.1 ;clear INTF flag so we can get more ;*** WARNING: SX saves/restores W, STATUS, and FSR automatically. ; RETFIE RETI main ;thermal printer control program 192 dpi 9 inch 1728 pixels ;need to set up direction bits for ports ;and set initial pin levels MOV W, #0 ;pullups and interrupt on neg edge MOV !OPTION, W ;set options MOV W, #0ff TEST 5 ;set all pins high on port a MOV W, #0fe ;RA0 as output ;*** WARNING: TRIS expanded in two instructions. Check if previous instruction is a skip instruction. ; tris 5 ;porta as input except RA0 ;porta as input except RA0 MOV W, #01f ;make bits 6,7 &5 low TEST 6 MOV W, #01f ;port b 5,6,7 as output ;*** WARNING: TRIS expanded in two instructions. Check if previous instruction is a skip instruction. ; tris 6 ;make it so ! ;make it so ! MOV W, #08 ;specify which phase to start on MOV $15, W ;store it somewhere safe CLR 0e ;zero byte count for head MOV W, #00 ;phases off clk,lat,data, strb off MOV $12, W ;data for shift reg 1 MOV W, #00 ;all strobes off (low) MOV $13, W ;data for shift reg 2 CALL outsr ;set all pins high except for stepper MOV W, #$90 ;enable RB0 and GIE interupt bits MOV 0b, W ;interupts now turned on! CLRB 5.0 ;say we are not busy p1=8;9 ;1 p2=4;8 ;3 ;ok here are definitions of how the shift registers are wired p3=2;0c;2 ; ok on 0x12 bit0 stepper phase A p4=1;4 ;6 ; bit1 " " B p5=8;6 ;4 ; bit2 " " C p6=4;2 ;0c ; bit3 " " D p7=2;3 ;8 ; bit4 Data for thermal head p8=1;1 ;9 ; bit5 Clock for thermal Head ; bit6 Latch for thermal head ; bit7 strobe 1 for thermal head ; 0x13 bit0 to bit7 rest of strobes for head mloop: ;this is the loopy bit of main ;we sit in here till we get a full head ;then we reset the counter, send an ack to the host ;print the line out and advance the paper, then we sit until ;the head is full again :) ;first check if the head is full MOV W, #$c0 ;try 192 ;216 max bytes per line 1728 bits MOV W, 0e-w ;check max against our byte count SB 3.2 ;the same? result of zero? JMP mloop ;no not yet keep waiting CLR 0e ;Ok we've spotted the head full ;need to strobe head drivers SETB $12.7 ;strb1 CLRB $b.7 ;turn off interupts CALL outsr ;Fire! CALL lildly ;let it burn! SETB 0b.7 ;re-enable interupts CLRB $12.7 ;ok thats done strobe 0 strobe 1 strobe 2 strobe 3 strobe 4 strobe 5 strobe 6 strobe 7 CLRB 0b.7 ;turn off interupts CALL outsr ;yay! all strobes Fired! CLRB 5.0 ;ok we aren't busy any more SETB 0b.7 ;re-enable interupts CALL papadv ;move paper on to next line JMP mloop ;lets go back and see if another ;line is ready yet phlook: ;this routine looks up the value for a particular phase ;important that this lookup resides within a 256 byte block ;as PCL is directly modified. if called with value grater ;than 8 ,will cause who knows what kind of crash! ADD 02, W ;ok now its going to jump :) NOP ;err dont expect zero ?!?! RETW #p8 ;return with phase 8 RETW #p7 ;coz we are counting down RETW #p6 ;remember... see next routine! RETW #p5 RETW #p4 RETW #p3 RETW #p2 RETW #p1 SLEEP ;coz its all gone wrong if it ;gets here or past! ;check the listing to be sure ;it fits between page boundries! papadv: ;this routine is to activate a paper advance one step ;it will use register #15 to keep track of which ;point in the phase cycle it is MOV W, #0f0 ;prep mask CLRB 0b.7 ;diable interupts AND $12, W ;nock off bottom bits MOV W, $15 ;grab our phase number into W CALL phlook OR $12, W ;new pattern now set SETB 0b.7 ;ints re-enabled DEC $15 ;get next phase number SNB 3.2 ;did we hit zero? JMP recount ;yep need to reload the counter CLRB 0b.7 ;turn off interupts coz of (outsr) CALL outsr ;jump to out put new phase SETB 0b.7 ;turn on interupts again RET ;and go back recount: MOV W, #08 ;we hit zero reset it back to 8 MOV $15, W ;use it next time round CLRB 0b.7 ;clear interupt enable CALL outsr ;I know its just below us SETB 0b.7 ;but tis only way to keep RET ;the interupts rightly enabled outsr: ;this routine takes bytes at 0x12 and 0x13 ;and clocks them out onto the shift registers ;shift registers accessed on port b bits 5,6 & 7 ;bit 6 as clock - clocks data on POSITIVE edge ;bit 7 as data - non inverted ;bit 5 as strobe - latches data on NEGATIVE edge ; we are sending lsb first ie bit# 1 on shift register ; output pin #8 ; sending byte at address 0x12 first then 0x13 ; this puts 0x12 on the last shift register in line ;uses reg # 14 to keep count of bits ;since this code is NON-RE-ENTERENT, do NOT call it ;while interupts are enabled, coz the int handler ;calls this routine to access the thermal head. MOV W, #08 ;for 8 bits MOV $14, W ;better keep count of it shiftbits: RR $12 ;rotate it thru carry SETB 6.7 ;set data high SB 3.0 ;check the carry flag CLRB 6.7 ;clear data if required SETB 6.6 ;clock that bit in CLRB 6.6 ;drop clock again DECSZ $14 ;have we finished loop yet ? JMP shiftbits ;guess not RR $12 ;preserve the data, shift the carry ;now we have finished one byte lets do the other MOV W, #08 ;for 8 bits MOV $14, W ;better keep count of it shiftbitsagain: RR $13 ;rotate it thru carry SETB 6.7 ;set data high SB 3.0 ;check the carry flag CLRB 6.7 ;clear data if required SETB 6.6 ;clock that bit in CLRB 6.6 ;drop clock again DECSZ $14 ;have we finished loop yet ? JMP shiftbitsagain ;guess not RR $13 ;preserve the data, shift the carry ;now we have really finished clocking bits SETB 6.5 ;bring up the strobe line CLRB 6.5 ;and LATCH it RET ;back to where ever. lildly MOV W, #lilloop MOV $11, W JMP reload bigdly MOV W, #bigloop MOV $11, W reload MOV W, #innerloop MOV $10, W inloop NOP DECSZ $10 JMP inloop DECSZ $11 JMP reload RET ORG $2000 DATA 00 DATA 00 DATA 00 DATA 00 ORG $2007 DATA 0x19 ;fuse settings ORG $2100 ;data 00 ;data 00 ;data 00 END