;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 bsf 0x13,bt ;bit for strobe bcf 0b,7 ;dont want interupts call outsr ;clock it out call lildly ;let it burn in bsf 0b,7 ;re-enable interupts bcf 0x13,bt ;so next outsr clears it endm ORG 0x0000 GOTO main ORG 0x0004 ;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 movwf 0c ;save 'W' in reg file 0c swapf 3,w ;grab the flags movwf 0d ;in reg 'd' ;should now be safe to continue! bsf 5,0 ;say we are busy ;read both ports to get byte of data rrf 5,w ;read port a shifting data down one andlw 0f ;only keep bottom bits movwf 0x16 ;keep incomming data here rrf 6,w ;read port b shifting down one andlw 0f ;wipe out extraneous bits movwf 0x17 ;waste another register swapf 0x17,w ;get 'b' data lower into upper W iorwf 0x16,f ;or top bits into data ;bit pattern from host now in 0x16 incf 0e,f ;increment our count of bytes ;clock data into thermal head movlw 08 ;for 8 bits movwf 0x17 ;better keep count of it clkhd: rlf 0x16,f ;rotate it thru carry bsf 0x12,4 ;set data high btfss 3,0 ;check the carry flag bcf 0x12,4 ;clear data if required call outsr bsf 0x12,5 ;clock that bit in call outsr bcf 0x12,5 ;drop clock again call outsr decfsz 0x17,f ;have we finished loop yet ? goto 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 movlw 0xc0 ;try 192 ;216 max bytes per line 1728 bits subwf 0e,w ;check max against our byte count btfss 3,2 ;the same? result of zero? goto 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. bsf 0x12,6 ;latch bit for thermal head call outsr ;send- no one else better be using it bcf 0x12,6 ;put back call outsr ;send that to goto exint ;leave int handler continue: ;tell host we are no longer busy, get next byte bcf 5,0 ;bring BSY low ;and fall thru to exit :) exint: ;now restore to before interupt swapf 0d,w ;put flags back in order in W movwf 3 ;stickem bick in flags swapf 0c,f ;flip saved W swapf 0c,w ;flip it back into W bcf 0b,1 ;clear INTF flag so we can get more RETFIE main ;thermal printer control program 192 dpi 9 inch 1728 pixels ;need to set up direction bits for ports ;and set initial pin levels movlw 0 ;pullups and interrupt on neg edge option ;set options movlw 0ff movf 5,f ;set all pins high on port a movlw 0fe ;RA0 as output tris 5 ;porta as input except RA0 movlw 01f ;make bits 6,7 &5 low movf 6,f movlw 01f ;port b 5,6,7 as output tris 6 ;make it so ! movlw 08 ;specify which phase to start on movwf 0x15 ;store it somewhere safe clrf 0e ;zero byte count for head movlw 00 ;phases off clk,lat,data, strb off movwf 0x12 ;data for shift reg 1 movlw 00 ;all strobes off (low) movwf 0x13 ;data for shift reg 2 call outsr ;set all pins high except for stepper movlw 0x90 ;enable RB0 and GIE interupt bits movwf 0b ;interupts now turned on! bcf 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 movlw 0xc0 ;try 192 ;216 max bytes per line 1728 bits subwf 0e,w ;check max against our byte count btfss 3,2 ;the same? result of zero? goto mloop ;no not yet keep waiting clrf 0e ;Ok we've spotted the head full ;need to strobe head drivers bsf 0x12,7 ;strb1 bcf 0xb,7 ;turn off interupts call outsr ;Fire! call lildly ;let it burn! bsf 0b,7 ;re-enable interupts bcf 0x12,7 ;ok thats done strobe 0 strobe 1 strobe 2 strobe 3 strobe 4 strobe 5 strobe 6 strobe 7 bcf 0b,7 ;turn off interupts call outsr ;yay! all strobes Fired! bcf 5,0 ;ok we aren't busy any more bsf 0b,7 ;re-enable interupts call papadv ;move paper on to next line goto 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! addwf 02,f ;ok now its going to jump :) nop ;err dont expect zero ?!?! retlw p8 ;return with phase 8 retlw p7 ;coz we are counting down retlw p6 ;remember... see next routine! retlw p5 retlw p4 retlw p3 retlw p2 retlw 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 movlw 0f0 ;prep mask bcf 0b,7 ;diable interupts andwf 0x12,f ;nock off bottom bits movf 0x15,w ;grab our phase number into W call phlook iorwf 0x12,f ;new pattern now set bsf 0b,7 ;ints re-enabled decf 0x15,f ;get next phase number btfsc 3,2 ;did we hit zero? goto recount ;yep need to reload the counter bcf 0b,7 ;turn off interupts coz of (outsr) call outsr ;jump to out put new phase bsf 0b,7 ;turn on interupts again return ;and go back recount: movlw 08 ;we hit zero reset it back to 8 movwf 0x15 ;use it next time round bcf 0b,7 ;clear interupt enable call outsr ;I know its just below us bsf 0b,7 ;but tis only way to keep return ;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. movlw 08 ;for 8 bits movwf 0x14 ;better keep count of it shiftbits: rrf 0x12,f ;rotate it thru carry bsf 6,7 ;set data high btfss 3,0 ;check the carry flag bcf 6,7 ;clear data if required bsf 6,6 ;clock that bit in bcf 6,6 ;drop clock again decfsz 0x14,f ;have we finished loop yet ? goto shiftbits ;guess not rrf 0x12,f ;preserve the data, shift the carry ;now we have finished one byte lets do the other movlw 08 ;for 8 bits movwf 0x14 ;better keep count of it shiftbitsagain: rrf 0x13,f ;rotate it thru carry bsf 6,7 ;set data high btfss 3,0 ;check the carry flag bcf 6,7 ;clear data if required bsf 6,6 ;clock that bit in bcf 6,6 ;drop clock again decfsz 0x14,f ;have we finished loop yet ? goto shiftbitsagain ;guess not rrf 0x13,f ;preserve the data, shift the carry ;now we have really finished clocking bits bsf 6,5 ;bring up the strobe line bcf 6,5 ;and LATCH it return ;back to where ever. lildly movlw lilloop movwf 0x11 goto reload bigdly MOVLW bigloop MOVWF 0x11 reload MOVLW innerloop MOVWF 0x10 inloop NOP DECFSZ 0x10 , f GOTO inloop DECFSZ 0x11 , f GOTO reload RETURN ORG 0X2000 DATA 00 DATA 00 DATA 00 DATA 00 ORG 0x2007 DATA 0x19 ;fuse settings org 0x2100 ;data 00 ;data 00 ;data 00 END
Interested: