CHAPTER 9

 

Nuts and Bolts

We have talked a lot about functional blocks, but there is a lot of reused code which is common to all modules, the nuts and bolts which make the program possible and hold it together!

We must include in these categories two areas about which we have said very little.

 

Math routines

All of the basic routines for hexadecimal maths

are freely available on the internet. They come in a multitude of shapes, 4 , 8, 16,24,32…bit.

There are just two little problems. Many of them aren’t what you want and, many of them are theoretical, and hard to put into assembler code ( a euphemism for maybe they never have worked).

Another more subtle problem is that some work with the example figures but not with others…. Gulp!!!

We need routines that work with all figures inside the bit range required.

So you can imagine that this was a long process narrowing down what was available and what was required.

Fortunately in the PICLIST. COM, you will find the routines that I have used and many others, which also work, but whose operation is a bit too subtle to be included in this SIMPLE first time code effort.

 

LOGIC routines

These have been kept to a minimum . Basically the Bike computer uses

An EQUAL TEST, which is the xorwf instruction. STATUS, Z

A less than equal =< coupled with greater than > test

Which use these instructions e.g. subwf dtothi,w followed by btfsc STATUS,C

These, AND MANY MORE, are well explained in the articles in PICLIST.COM.

 

Conversion routines

The three main types that had to be invented were converting

  1. HEX to DECIMAL
  2. HEX FRACTIONS to DECIMAL FRACTIONS
  3. NUMBER SCALING

 

 

HEX to DECIMAL

This we have already discussed h2d in previous paragraphs but the basic routine is used in the three calculation modules for, SPEED, DISTANCE and AVERAGE SPEED.

You should be able to follow the conversion routines after a little bit of study. The notes in each routine to say where you are in the process are abundant.

HEX FRACTIONS to DECIMAL FRACTIONS

This merely is an extension of the previous routines with a little bit of reasoning to change hex remainder and fractions into decimal fractions.

The fraction routines are needed because the pics don’t handle directly fractions, so they have to be changed into whole numbers by suitable multiplication.

NUMBER SCALING

We do a lot of multiplication and division in the three main calculations for Speed, Distance and Average Speed.

But we have a practical 16bit number limit. The numbers can’t be bigger than 65536.

If they are, then we need to add more registers, and probably bigger calculation routines able to handle more than 16bits. So I decided to try and stay as far as possible within the 16bit routines.

In some places you divide and the result of the division has to be multiplied by another number. For example 2000.

So you divide your first two numbers. The result is say ten.

Then the next operation has no problem because 10 x 2000 is 20000 which is< 65536.

However if the first division had given as a result 300, then we have a problem.

300 x 2000 = 600000 way above the limit of 65536 we need to scale somewhere.

The scale factor here would be about 20. But this is one of those things that is best seen following the steps the code takes , say in the SPEED block.

Basically the number is tested for size and divided down until its product with a reference number is smaller than 65536. But as we said above, follow the steps taken in the actual code block to see how the scaling is done to solve a specific application problem.

 

LCD Setup, Signalling and data transfer routines

The LCD itself has on board a complex controller chip whose job is to interface with a uController, in this case our 16F84A and steer the incoming data messages to the correct position for display.

There are two basic operation modes; 4 bit and 8 bit. Most applications seem to use the 4 bit mode as it will free 4 lines of a uController to do other things.

The data is strobed into the LCD using appropriate signals on the E and RS lines. The protocols are also time sensitive. They have to be as long as the minimum times quoted on the LCD data sheets. Here lies a problem.

The LCD chosen is very popular. It has many clones. SOME of the clones need EVEN longer times. This means that the typical DELAYS programmed could be insufficient.

Before anything can be displayed, the LCD needs to be initialised. This is a really slow process taking about 50 to 100ms. The number of times the routines are repeated during the initiation sequences seems a little exaggerated but it has to be that way to get the LCD up and running, it is exactly what the manufacturers spell out on their data sheets.

Each command or data interchange between the PIC and the LCD has it’s corresponding minimum time. These have all to be scrupulously observed or the process fails.

That is the reason why there are so many different time blocks within the delay module plus some additional ones for other tests.

All of the routines can be found on the PICLIST.COM site. I take my hat off to whoever sat down and worked them out first time round, a really heroic and Herculean task.

 

Automatic menu (2)

The operation of Automatic menu was explained previously under the heading of that name when we were looking at the Flow Chart.

However this was one of two possibilities in the original project, the other, manual function selection needed two push buttons plus the corresponding code so that was dropped as the PIC was running out of space.

There is nothing special about the way the menu presents the three main features. Their combinations features to the LCD can be changed if you prefer. For example, maybe you would like to see at once Average Speed and Total distance, or maybe Speed and total distance.

There are many combinations possible. Of course if you do change then don’t forget to follow through into each module that is being used to see that there is no other unwanted effects.

 

Bike3.asm

We can now study the complete program which is called bike3.asm

With the help of the previous Flow Chart which shows the sequence of major functional blocks of the program, and reading through the code below, it should now be possible to understand, hopefully fairly easily, how the code blocks have been cobbled together.

Made to implement the basic equation we started out with.

Speed = Distance /Time.

 

 

 

 

 

 

 

 

;----------------------------------------------------------------------;

; bike3.asm Combines: Time , Dist, Av velocity, Inst Vel

; Fred Maher 1st March 2002

; BASIC BICYCLE COMPUTER WITH THESE FUNCTIONS

;----------------------------------------------------------------------;

; 1 Trip Time HRS:MIN:SEC

; 2 Trip Dist 000km 00m

; 3 Trip AvSpd 00.00km/hr

; 4 Speed 00.00km/hr

 

 

;---------------------------------------------------------------------

;------- HEADER ----------

;---------------------------------------------------------------------

; LCD MESSAGES

; position at beginning of 1st line col 0 movlw H'80

; position at beginning of second line movlw H'C0'

LIST P=16F84 ; 16F84 Runs at 4.096 MHz

INCLUDE "p16f84A.inc"

__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON

ERRORLEVEL -224 ; suppress annoying message because of tris

ERRORLEVEL -302 ; suppress message because of page change

; Define Information

#DEFINE RS PORTA, 2

#DEFINE E PORTA, 3

;#DEFINE TOGGLESW PORTB, 6 ; not used at the moment

;#DEFINE LED PORTB, 5

; Macro

;---------------------------------------------------------------

CBLOCK 0CH ; from 0C to 4F = 67

;---------------------------------------------------------------

; MATH ROUTINES

; 16 X16 Mult , --> 32

; mah mal x mbh mbl = mq4 mq3 mq2 mq1 ( mq4 highest)

mq4

mq3

mq2

mq1

mbh

mbl

mah

mal

; 16 / 16 Div --> 16

denlo

denhi

numlo

numhi

rmdrlo

rmdrhi

reshi

reslo

;temp also used in nybble

; Addition 16+16 out max 65536 (no carry)

; Subtraction q1_16-q2_16 out r_16; neg numbers not allowed

q1hi

q1lo

q2hi

q2lo

rhi

rlo

;------------ Distance -----------------------

dtotlo ; total trip distance in metres

dtothi ; dtothi/lo hold a max of 65km 536m,

dtothi2 ; with this added max now 16777km

dist54 ; corrects +2m every 54m (27x2.0747 =56)

dm

dm10

dm100

dm1000

dm10000

dm100000

;------------ Average velocity Vav -------------------

;vavhi

;vavlo

;divrat

;stemphi ;second info passed to stemphi/lo

;stemplo

;dtemphi ;dist info passed to dtemphi/lo

;dtemplo

m

m10

m100

m1000

;--------- Time and trip time --------------------

;

sectotlo ; total trip seconds

sectothi ; max 65536 = aprox 18hrs

sec ; seconds digit

sec10 ; 10's of second digit

min ; minutes digit

min10 ; 10's of minutes digit

hr ; hours digit

hr10 ; 10's of hours digit

oldsec ; holds last value of sec

cntmsec ; count ms

TMR18 ; TMR0 217* TMR18 18 = 1 SEC

;---- isr interrupt service routine push pop -------

w_temp ; W isr var

status_temp ; STATUS isr var

fsr_temp ; FSR isr var

; --------- Instantaneous Velocity Vin --------------------

vinhi

vinlo

sectemp

oldtemp

totmslo

totmshi

totms2lo

totms2hi

mshi

mslo

spdflg ; 1st pass =0 2nd pass =1, diff is time between pulses

;-------- Miscellaneous ------------------

temp ; a temporary used in divide and nybble

count

menu

ENDC ; end of definition block

;-------------------------------------------------------------------

ORG 0 ; start at location 0

goto main ; jump over to main routine

ORG 4

goto Isr ; jump to interrupt routine

 

;----------------------------------------------------------------------;

; The Main routine ;

;----------------------------------------------------------------------;

; -------- THE MAIN MODULES ---------

; Isr stores elapsed TRIP time and generates hr:min:sec

; Disptime TRIP time, to max 99:59:59

; Dist Calculates total TRIP distance

; Dispdist TRIP distance to a max of 999km 999m

; Velav Average velocity, Totdist/totsecs max 99km/hr

; Dispvav Average TRIP speed up to 99.99 km/hr

; Velocity Speed from 2m/(time diff of pulse2-pulse1)

; Dispd Speed up to 99.99km/hr

; NOTE. Speed is your calculated velocity every second

; -------- more to come??? NO, running out of space ---------

 

;-----------------------------------------------------------------------

; M A I N

;-----------------------------------------------------------------------

 

main:

call Init ; Initialize ports, set up timer

call Initlcd ; Initialize the LCD DUMMY

Initend:

;------------------------------------------------------------------

; Changesec Changewhlpulse wait for interrupts from newsec or newwheelpulse

; -----------------------------------------------------------------

clrf menu ; initially set to 0 menu loop

clrf spdflg ; Initially = 0 2nd = sub for time from zero

; every new sec, set to zero

; CHANGESEC LOOPS TILL SEC CHANGES

;clrw ;DUMMY

;xorwf sec,w ;DUMMY

;btfsc STATUS,2 ;DUMMY

;incf sec,f ;DUMMY

Changesec: ;loops checking new sec and new wheel pulse

movf oldsec, w

xorwf sec,w

; if equal, w= 0 and Z bit=1

btfsc STATUS,2 ; test Z bit

goto Changesec ; no change, loop

movf sec,w ; sec has increased, update

movwf oldsec ; sec and oldsec are = again

incf menu,f ; increases menu every sec

; Note1, sectotlo/hi are updated every sec in ISR module

; Note2, Decimal time also created in ISR module

; but time display for LCD controlled from

; the automatic menu below

call Disptime ;TRIP time, will appear on LCD top line

Changewhp: ; 1st detected wheelpulse starts menu sequence

clrf PORTB

bcf PORTB,5 ; start with green LED off

loop:

btfss PORTB, 4 ;(PUT BTFSC FOR TEST); i/p hi,?DUMMY

goto loop ; not yet

; i/p hi detected

;green LED flashes with every wheel pulse

bsf PORTB, 5 ; LED on

; wait a while to make sure switch has

; settled

movlw D'10' ; wait about 10 msec

call nmsec

btfsc PORTB, 4 ; will be lo (0) when finished

goto $ -1 ; still low

; now must wait a make sure bouncing stopped

movlw D'10' ; 10 milliseconds

call nmsec

; and check again

btfsc PORTB, 4 ; if set, not finished

goto $ -5 ; still hi start debounce wait again

Tp1: ; green LED ready for next wheel pulse

bcf PORTB,5 ; i.e. LED off

movf PORTB,w ; reading to clear

; AUTOMATIC MENU: (LCD Top line always time)

; --------------

; menu selects at 10sec intervals in rotation

; Speed menu 1 to 10

; Dist ance menu 11 to 20

; Velav Avg vel menu 21 to 30

; MENU 0 TO 10

; as speed ( Speed) is stand alone, no sense in calculating it

; if it is not going to be displayed when menu is >10.

; BUT if SPEED AVERAGING IS TO BE USED, kill off the lines below that bypass

; the SPEED calc module

Menucheck:

movlw 0x0A ;check menu > 10 (to meet >10 AND =<20)

subwf menu,w

btfss STATUS,C ;compare with 10

goto $+2 ;menucount =< 10 not yet got to 11 jump to Speed

goto Distblk

call Speed ; Calculates instant speed,(time between pulses)

movlw 0x0A ; DUMMY, was movlw 0xA

subwf menu,w

btfss STATUS,C ;compare with 10

call Spdflgcheck ;menucount =< 10 ; also see 0-1 spdflg

goto Distblk

Spdflgcheck:

clrw

xorwf spdflg,w

btfsc STATUS,Z

call Dispd ;menucount =< 10 AND spdflg =1

Return

Distblk:

call Dist ;menucount > 10 skip Dispd update Dist

 

; MENU 11 TO 20

movlw 0x0A ;check menu > 10 (to meet >10 AND =<20)

subwf menu,w

btfss STATUS,C ;compare with 10

goto $+5 ;menucount =< 10 not yet got to 11 jump to velav

movlw 0x14

subwf menu,w

btfss STATUS,C ;compare with 20

call Dispdist ;menucount =< 20

call Velav ;menucount > 20 skip dispdist update Velav

; MENU 20 TO 30

movlw 0x14 ;check menu > 20 (to meet >20 AND =<30)

subwf menu,w

btfss STATUS,C ;compare with 20

goto $+5 ;menucount =< 20 not yet got to 21 jump to NEXT

movlw 0x1E

subwf menu,w

btfss STATUS,C ;compare with 30

call Dispvav ;menucount =< 30

movlw 0x1F ;if it has reached 31 reset menu, before return

xorwf menu,w

btfss STATUS,Z

goto $ +2 ; not 31 goto changewhp1 direct

clrf menu ; is 31, reset menu before changewhp1

Menuend:

; before changewhp jump, check that sec has not updated

; if it has , jump back to changesec routine

movf oldsec, w

xorwf sec,w ; if equal, w= 0 and Z bit=1

btfsc STATUS,2 ; test Z bit

goto Changewhp ; no sec change, check whpulse change

goto Changesec ; a new sec starts measurements

; loop while NOT newsec

; ---------------------------------------------------------------

; End Main

; ----------------------------------------------------------------

 

 

 

;----------------------------------------------------------------------;

; ISR, increments TMR0 by 1 every 256 µsec. Basically just ;

; reset the INTCON and TMR0 bits. The FSR,w, STATUS push pop kept ;

;----------------------------------------------------------------------;

Isr:

movwf w_temp ; save W

swapf STATUS,W ; save status

movwf status_temp ; without changing flags

swapf FSR,W ; save FSR

movwf fsr_temp ; without changing flags

;256us * 217 * 18 = 0.999936 sec.

;1hr_err = 0.23sec or 1 sec in 4hr

;The time loop starts with TMR0 loaded with (256-217)=39 After 217

;steps interrupt is set, TMR0 rolls to zero and the TMR18 inc +1

movlw D'39' ;39 = 0x27

movwf TMR0

incf TMR18,f

movlw D'18' ; DUMMY18 = 0x12

xorwf TMR18,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 18 so pop stack and return to main

Firstsec:

clrf TMR18 ; is 18. set TMR18 to zero and INC sec

incf sec,f ; also inc sectot (eventually lo and hi)

incf sectotlo,f ; check sectot lo 00->inc hi

clrw

xorwf sectotlo,w ; if equal, w= 0 and Z bit=1

btfsc STATUS,2

incf sectothi,f ; increases every 256 x sectotlo

movlw 0xA ; check if =10

xorwf sec,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 10 so pop stack and return to main

clrf sec ; is 10. set sec to zero and inc sec10

incf sec10,f

movlw 0x6 ; = 0x6

xorwf sec10,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 6 so pop stack and return to main

 

clrf sec10 ; is 6. set sec10 to zero and INC min

incf min,f

movlw 0xA ; check if =10

xorwf min,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 10 so pop stack and return to main

clrf min ; is 10. set sec to zero and inc min10

incf min10,f

movlw 0x6 ;= 0x6

xorwf min10,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 6 so pop stack and return to main

clrf min10 ; is 6. set min10 to zero and INC hr

incf hr,f

movlw 0xA ;check if =10

xorwf hr,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 10 so pop stack and return to main

clrf hr ; is 10. set hr to zero and inc hr10

incf hr10,f

movlw 0xA ;= 10

xorwf hr10,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto restore ; NOT 10 so pop stack and return to main

clrf sec ; is ten (99hr 59min 59sec +1sec) we are at MAX

clrf sec10 ;all reset to zero and start again

clrf min

clrf min10

clrf hr

clrf hr10

clrf TMR18

clrf oldsec

goto restore

restore:

swapf status_temp,W ; get original status back

movwf STATUS ; into status register

swapf fsr_temp,W ; get original fsr back

movwf FSR ; into status register

swapf w_temp,f ; old no flags trick again

swapf w_temp,W ; to restore W

bcf INTCON,T0IF ; clear the TMR0 interrupt flag

retfie ; finished, reset GIE

;----------------------------------------------------------------------;

; Initialize the ports ;

;----------------------------------------------------------------------;

Init:

clrf PORTA

clrf PORTB

movlw B'00000000' ; Porta all outputs

tris PORTA

movlw B'01010000' ; 7o 6i-Wire 5o-LED 4i-multivib,

tris PORTB ; 0to3lcd

 

movlw B'00000111' ; opt pull-ups enabled

; opt prescaler assigned to TMR18

; opt prescaler set to 1:256

option ; opt rolls over each 125th second

movlw 0 ; zero out all registers

clrf m

clrf m10

clrf m100

clrf m1000

clrf dm

clrf dm10

clrf dm100

clrf dm1000

clrf dm10000

clrf dm100000

clrf totmshi

clrf totmslo

clrf totms2hi

clrf totms2lo

clrf dist54

clrf hr10

clrf hr

clrf min10

clrf min

clrf oldsec

clrf sec10

clrf sec

clrf sectotlo

clrf dtotlo

clrf dtothi

clrf sectotlo

clrf sectothi

clrf TMR18 ; when this reaches 18, 1 sec has elapsed

; TMR0 has to start at 256-217 :39, so that the first rollover

; with prescaler 256, happens in 217*256us =0.055552sec

; The TMR18 incs each roll and after 18 1 sec has elapsed

movlw 0x27 ; D39

movwf TMR0 ; set to D39 217 counts later 256,

; TMR0 resets and inc TMR18 in Isr loop

clrf INTCON ; START WITH ALL AT 0

; movlw B'10100000' ; GIE set T0IE set, T0IF cleared

movlw B'10100000' ; Set:GIE,T0IE,RBIE Clrd:T0IF,RBIF

movwf INTCON ; ready to detect interrupts in ISR

return

;----------------------------------------------------------------------;

; Initialize the LCD ;

;----------------------------------------------------------------------;

Initlcd:

movlw D'40'

call nmsec ; Wait 40 msecs before Reset

bcf RS ; send an 8 bit instruction

movlw 0x03 ; Reset Command

call NybbleOut ; Send the Nybble

call Dlay5 ; Wait 5 msecs before Sending Again

call EStrobe

call Dlay160 ; Wait 160 usecs before Sending 2nd Time

call EStrobe

call Dlay160 ; Wait 160 usecs before Sending 3rd Time

bcf RS ; send an 8 bit instruction

movlw 0x02 ; Set 4 Bit Mode

call NybbleOut

call Dlay160

movlw 0x028 ; 4 bit, 2 Line, 5x7 font

call SendINS

movlw 0x010 ; display shift off

call SendINS

movlw 0x001 ; Clear the Display RAM

call SendINS

call Dlay5 ; Note, Can take up to 4.1 msecs

movlw 0x006 ; increment cursor

call SendINS

movlw 0x00C ; display on cursor off

call SendINS

return

;----------------------------------------------------------------------;

; Send the character in W out to the LCD ;

;----------------------------------------------------------------------;

SendASCII

addlw '0' ; Send nbr as ASCII character

SendCHAR: ; Send the Character to the LCD

movwf temp ; Save the temporary Value

swapf temp, w ; Send the High Nybble

bsf RS ; RS = 1

call NybbleOut

movf temp, w ; Send the Low Nybble

bsf RS

call NybbleOut

return

;-------------------------------------------------------------

; ES strobe

;-------------------------------------------------------------

EStrobe: ; Strobe the "E" Bit

bsf E

bcf E

return

;----------------------------------------------------------------------;

; Send an instruction in W out to the LCD ;

;----------------------------------------------------------------------;

SendINS: ; Send the Instruction to the LCD

movwf temp ; Save w

swapf temp, w ; send Hi Nybble

bcf RS ; RS to 0

call NybbleOut

movf temp, w ; Send Lo Nybble

bcf RS

call NybbleOut

return

;----------------------------------------------------------------------;

; Send the nibble in W out to the LCD ;

;----------------------------------------------------------------------;

NybbleOut: ; Send a Nybble to the LCD

movwf PORTB

call EStrobe ; Strobe out the LCD Data

bsf E

call Dlay160 ; delay for 160 usec

return

;----------------------------------------------------------------------;

; Output the message on the LCD ;

;----------------------------------------------------------------------;

OutMessage1:

movwf FSR ; Point at first letter

OutLoop:

movf FSR, w ; Get pointer into W

incf FSR, f ; Set up for next letter

call Dispmsg1 ; Get character to output

iorlw 0 ; At the End of the Message?

btfsc STATUS, Z ; Skip if not at end

return ; Yes - Equal to Zero

call SendCHAR ; Output the ASCII Character

goto OutLoop ; Get the next character

;----------------------------------------------------------------------;

; Data for message to be output ;

;----------------------------------------------------------------------;

Dispmsg1: ; Message to Output

addwf PCL, f ; Output the Characters

dt "Bike Computer", 0

Dispmsg2: ; Message to Output

addwf PCL, f ; Output the Characters

dt "Dist", 0

Dispmsg3:

addwf PCL,f ; message to output

dt " Av speed:",0 ; output characters

;----------------------------------------------------------------------;

; time delay routines ;

;----------------------------------------------------------------------;

;Note . The original application needed precise times from the delay code that

; follows. But the Simple Bike application does NOT use the routines for

; any CRITICAL time measurement.

Dlay160:

movlw D'41' ; delay about 160 usec

micro4:

addlw H'FF' ; subtract 1 from 'W'

btfss STATUS,Z ; skip when you reach zero

goto micro4 ; more loops

return

Dlay5:

movlw 5 ; delay for 5 milliseconds

goto $ + 2

msec250:

movlw D'250' ; delay for 250 milliseconds

; --- N millisecond delay routine ---

nmsec:

movwf cntmsec ; delay for N (you put in W) millisec

msecloop:

movlw D'254' ; load takes .9765625 microsec

call micro4 ; by itself CALL takes ...

; about 1ms

nop ; 1usec

decfsz cntmsec, f ; .98 skip not taken, else 1.95

goto msecloop ; 1.95 here: total ~1000 / loop

return ; final time through ~999 to here

; overhead in and out ignored

; this block is functional for tests, but not used in bike

Dlay1sec: ; this is a marker routine to see where

call msec250 ; the prg is at.

; bsf LED

call msec250 ;flash led on portb pin6

;bcf LED

call msec250

; bsf LED

call msec250 ; finishes with green led lit

return

;----------------------------------------------------------------------;

; Display the Time ;

;----------------------------------------------------------------------;

Disptime:

movlw H'80' ; position at beginning of first line

call SendINS

movf hr10, W ; tens of hours

call SendASCII

movf hr, W ; hours

call SendASCII

movlw ":"

call SendCHAR

movf min10, W ; tens of minutes

call SendASCII

movf min, W ; minutes

call SendASCII

movlw ":"

call SendCHAR

movf sec10, W ; tens of seconds

call SendASCII

movf sec, W ; seconds

call SendASCII

movlw " "

call SendCHAR ; the h m s really not needed

movlw "h"

call SendCHAR

movlw "m"

call SendCHAR

movlw "s"

call SendCHAR

movlw " "

call SendCHAR

Dispend:

RETURN

;----------------------------------------------------

; End of display time

;----------------------------------------------------

 

;----------------------------------------------------------------------;

; Display the Distance , (trip distance at moment) ;

;----------------------------------------------------------------------;

Dispdist:

movlw H'C0' ; position at beginning of second line

call SendINS

movf dm100000, W ; 0 of 065km 536m

call SendASCII

movf dm10000, W ; 6 of 065km 536m

call SendASCII

movf dm1000, W ; 5 of 065km 536m

call SendASCII

movlw "k" ; k of 065km 536m

call SendCHAR

movlw "m" ; m of 065km 536m

call SendCHAR

movlw " " ; " " of 065km 536m

call SendCHAR

movf dm100,W ; 5 of 065km 536m

call SendASCII

movf dm10,W ; 3 of 065km 536m

call SendASCII

movf dm, W ; 6 of 065km 536m

call SendASCII

movlw "m" ; m of 065km 536m

call SendCHAR

movlw " " ; " "

call SendCHAR

movlw "D" ; "D "

call SendCHAR

movlw "i" ; " i"

call SendCHAR

movlw "s" ; "s "

call SendCHAR

movlw "t" ; " t"

call SendCHAR

movlw " " ; " " ( to wipe screen)

call SendCHAR

Distend:

RETURN

;

;---------------------------------------------------------------------*

; Multiplication 16x16 Out32

;---------------------------------------------------------------------*

Mult16x16:

clrf mq4

clrf mq3

clrf mq2

clrf mq1

bsf mq2, 7

Mu1:

rrf mah, f

rrf mal, f

skpc

goto Mu2

movf mbl, w

addwf mq3, f

movf mbh, w

skpnc

incfsz mbh, w

addwf mq4, f

Mu2:

rrf mq4, f

rrf mq3, f

rrf mq2, f

rrf mq1, f

skpc

goto Mu1

Endmult16:

clrf mbh

clrf mbl

clrf mah

clrf mal

Return

;---------------------------------------------------------------------*

; End Multiplication 16x16 Out32

;---------------------------------------------------------------------*

;---------------------------------------------------------------------*

; New routine Division 16/16 Out 16

; ---------------------------------------------------------------------*

; Finally:- Result 000AH in reshi/lo, remainder 0096H in rmdrhi/lo

; so, checking end of division A=10 and 96H/E1H= 150/225 =0.666 OK

Div:

call D_divS ; remainder in Rmdr.

Divend:

nop

return

D_divS:

call setup

clrf rmdrhi

clrf rmdrlo

dloop:

bcf STATUS,C

rlf reslo, f

rlf reshi, f

rlf rmdrlo, f

rlf rmdrhi, f

movf denhi,w

subwf rmdrhi,w ;check if a>c

btfss STATUS,Z

goto nochk

movf denlo,w

subwf rmdrlo,w ;if msb equal then check lsb

nochk:

btfss STATUS,C ;carry set if c>a

goto nogo

movf denlo,w ;c-a into c

subwf rmdrlo, f

btfss STATUS,C

decf rmdrhi, f

movf denhi,w

subwf rmdrhi, f

bsf STATUS,C ;shift a 1 into b (result)

nogo:

rlf numlo,f

rlf numhi,f

decfsz temp, f ;loop untill all bits checked

goto dloop

setup:

movlw .16 ; for 16 shifts

movwf temp

movf numhi,w ;move Num to Res

movwf reshi

movf numlo,w

movwf reslo

clrf numhi

clrf numlo

retlw 0

;--------------------------End Div 16 by 16----------------------------

 

 

return

;---------------------------------------------------------------------*

; END DIVISION 16/16 OUT 16

;---------------------------------------------------------------

;---------------------------------------------------------------------*

; START Addition 16-16 OUT 16

;---------------------------------------------------------------

Add: ; R = q1 + q2

movf q1lo, W

addwf q2lo, W

movwf rlo

movf q1hi, W

btfsc STATUS, C

addlw .1 ; If A Carry Occurred, Add 1

addwf q2hi, W

movwf rhi

;clrf q1hi ; added this to stop next user summing;

;clrf q1lo

;clrf q2hi

;clrf q2lo

Return

;---------------------------------------------------------------------*

; END Addition 16-16 OUT 16

;---------------------------------------------------------------

 

 

;---------------------------------------------------------------------*

; START Subtraction 16-16 OUT 16

;---------------------------------------------------------------

Sub: ; R = q1 - q2

movf q2lo, W

subwf q1lo, W ; W = q1lo - q2lo

movwf rlo

btfss STATUS, C

Goto Borrow

Goto Sub1

Borrow:

Decf q1hi, F

Sub1:

movf q2hi, W

subwf q1hi, W ; W = q1hi - q2hi

movwf rhi

Return

;---------------------------------------------------------------

; END Subtraction 16-16 OUT 16

;---------------------------------------------------------------

 

 

 

 

 

;---------------------------------------------------------------

; Dist = counting wheel pulses

;---------------------------------------------------------------

Dist: ; whlcirc = 2.0747, for initial test =2

;

; movlw 0x2 ; <-- don't forget, this is just for 26"wheel

; movwf whlcirc ; start count at 0 and inc till same as whlcirc

; (range will be 1 to 4 m)

clrf count ; count can be 2 or 4 in this 26" case

Whloop: ; although the distance pulses ( in this example) jump in steps of 2m

; the m counter has to increase in 1's to catch the

; decimal rollover from 10 to 0

; so count, here, is stepped from 0 to 2 (whlcirc)

; Also, when the dist54 var increases 54m, COUNT adds an extra 2m

; to the hex and decimal totals, before resetting to zero.

; Note that as dist54 is in the loop it will also receive

; the 2m increase so it really counts to 56 (54 +2).

movlw 0x2 ; wheel circumference of 26 inch

xorwf count,w ; if equal, w= 0 and Z bit=1

btfsc STATUS,2 ; test Z bit

goto DistanceEnd ; they are the same, so jump distanceEnd and return

goto Mcount ; NOT yet = whlcirc, so inc mcount by 1 and return

Mcount: ; Distance to decimal for display , i/p m, o/p 000km 000m

; starts with m, m10, m100, m1000 , m10000, m100000 = 0

; Later correct m every 54m (add 2m ???? )

incf dm,f

movlw D'10'

xorwf dm,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Mcountend ; NOT 0 so return

clrf dm

incf dm10,f

movlw D'10'

xorwf dm10,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Mcountend ; NOT 0 so return

clrf dm10

incf dm100,f

movlw D'10'

xorwf dm100,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Mcountend ; NOT 0 so return

clrf dm100

incf dm1000,f

movlw D'10'

xorwf dm1000,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Mcountend ; NOT 0 so return

clrf dm1000

incf dm10000,f

movlw D'10'

xorwf dm10000,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Mcountend ; NOT 0 so return

clrf dm10000

incf dm100000,f

movlw D'10'

xorwf dm100000,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Mcountend ; NOT 0 so return

clrf dm ; is distmax, reset to 0

clrf dm10

clrf dm100

clrf dm1000

clrf dm10000

clrf dm100000

goto Mcountend ; see if whpl update is now finished

 

 

Mcountend: ;update the hex counters dtot /lo/hi/hi2

incf dtotlo,f

clrw

xorwf dtotlo,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Dtotend ; dtotlo NOT 0

incf dtothi,f ; add 1, dtotlo is 0

clrw

xorwf dtothi,w ; if equal, w= 0 and Z bit=1

btfss STATUS,2 ; test Z bit

goto Dtotend ; dtothi NOT 0

incf dtothi2,f ; add 1, dtothi is 0

Dtotend:

movlw D'54'

movwf numhi ; not in use here, use to store 54

movf dist54,w

subwf numhi,w

btfsc STATUS,C

goto Noextra ; dist54=< 53, don't freeze COUNT

movlw D'56' ; dist54>53 add 2 extra counts

movwf numhi ; not in use here to store 56

movf dist54,w

subwf numhi,w

btfsc STATUS,C

goto Extra ; dist54=< 56, freeze COUNT

clrf dist54

goto Noextra

 

 

Noextra:

incf dist54,f

incf count,f

goto Whloop

Extra: ; an extra loop BUT count is NOT increased

incf dist54,f

goto Whloop

DistanceEnd: ; All conversion loops have executed and

; only left to display in decimal, when selected

;

return ; BACK TO MAIN

;--------------------------------------------------------------------------

; End of Trip Distance calculation Module

;--------------------------------------------------------------------------

 

;----------------------------------------------------------

; Calculate Average velocity from Velav = totdist/totsec

;-----------------------------------------------------------

; 1st time round distto = 0 and sectot =0.

; Disttot lo/hi zero is prob OKbut test sec=0. If zero return

Velav:

clrw

xorwf sectotlo,w

btfss STATUS,Z

goto Spdstart ; not 0, onto Avspeed calc

clrw ; lo was 0, but hi byte may not be

xorwf sectothi,w

btfss STATUS,Z

goto Spdstart ; was not 0, onto Avspeed calc

;incf sectotlo,f ; DUMMY

;goto Spdstart ; DUMMY

return ; was also 0, abort module wait for sec inc

; to slow down the number of whpul in the test we add Dummies

Spdstart: ; for test delay incf sec and sectot, gives 7.2km/hr

;incf sec,f ; DUMMY

;incf sectotlo,f ; DUMMY

;Lpstart:

movlw 0x07 ; 1800 comp hi bytes

subwf dtothi,w

btfsc STATUS,C

goto Divratio ; dtothi is > 1800hi and needs dividing

; we suppose that the hibyte test is sufficient,

; it may not be true. e.g hi's the same but lo's diff

; pass dtot to m1000,m100

movf dtothi,w ; dtothi <1800

movwf m1000

movf dtotlo,w

movwf m100 ; m1000,m100 hold dtothi/lo ( no div needed)

movf sectothi,w

movwf m10

movf sectotlo,w

movwf m ; m10,m hold sectothi/lo ( no div needed)

; note, this is dtot to m1000,m100 not needing division

goto Ratend ; if divratio is needed, then m1000,m100 is used there

Divratio: ; enter variables and 1800

movf dtothi,w

movwf numhi

movf dtotlo,w

movwf numlo

movlw 0x07

movwf denhi

movlw 0x08

movwf denlo

call Div

incf reslo,w ; reslo holds INT of Divratio +1

movwf count ; not used at the moment

movf dtothi,w ; divide dtothi/lo by count

movwf numhi

movf dtotlo,w

movwf numlo

clrf denhi

movf count,w ; e.g. D 37

movwf denlo

call Div ; we need parking space for results, REuse the m1000 etc

movf reshi,w

movwf m1000 ;

movf reslo,w

movwf m100 ; m1000, m100 =dtot/count

; repeat for sectot

movf sectothi,w

movwf numhi

movf sectotlo,w

movwf numlo

clrf denhi

movf count,w ; e.g D 37

movwf denlo

call Div

movf reshi,w

movwf m10

movf reslo,w

movwf m ; m10, m =sectot/count

Ratend:

; WE CAN NOW DO DTOT/SECTOT x3.6 as we have SCALED TO AVOID OVERFLOW

; m1000,m100 x 36 (top line)

; Vav= ------------------------- = Average speed in km/hr

; m10,m x 10 (bottom line) ; 36(24H), 10(AH)

movf m1000,w ; MULT dtot, top line, by 24H

movwf mah

movf m100,w

movwf mal

clrf mbh

movlw 0x24

movwf mbl

call Mult16x16 ; ( store top line result in the same variables)

movf mq2,w

movwf m1000

movf mq1,w

movwf m100 ; dtot x 36

movf m10,w ; MULT sectot, bottom line, by AH

movwf mah

movf m,w

movwf mal

clrf mbh

movlw 0xA

movwf mbl

call Mult16x16 ; ( store bottom line result in the same variables)

movf mq2,w

movwf m10

movf mq1,w

movwf m ; sectot x 10

Tp3:

; As we are reusing variables, trying to show where the results to here are being held

; m1000,m100

; We now have as Average speed ----- --------- km/hr

; m10,m

;the AVERAGE SPEED AT LAST

movf m1000,w ; dtotx36/sectotx10

movwf numhi

movf m100,w

movwf numlo

movf m10,w

movwf denhi ; needed below for decimal place

movf m,w

movwf denlo ; needed below for decimal place

call Div

; denhi/lo can chanfge as the div routine reuses bits

; so we reestablish previous denom values before losing

movf m10,w

movwf denhi

movf m,w

movwf denlo ; we can now write over m and m10

movf reshi,w ;will be zero

;(bikes don't exceed 256km/hr normally)

movf reslo,w ; reuse variables m10 INT and later m FRAC

movwf m10 ;we have integer part of Vav Average speed

; rmdrhi/lo holds decimal fraction.we will only use 1 decimal place.

; so mult the rmdrhi,lo x10 before dividing by denhi/lo

movf rmdrhi,w ; mult top by 10

movwf mah

movf rmdrlo,w

movwf mal ; rmdr in tot storage

clrf mbh

movlw 0xA

movwf mbl

call Mult16x16 ; rmdrhi,lo x 10

; top line is now mq2,mq1 ( nothing in mq4,mq3)

; Bottom line..remember we already have loaded

; the denominator above which says

; " needed below for decimal place"

Tp4:

movf mq2,w ;rmdrhi,w

movwf numhi

movf mq1,w ;rmdrlo,w

movwf numlo

call Div ; div for the decimal( just 1 place), in reslo

; reshi,reslo holds decimal place results

; m10+m are av speed as INT+DEC but in hex

; now change to decimal.

; m10 and m are going to be wiped, but there is no

;divide routine so for INT +FRAC we use reshi reslo

movf m10,w

movwf reshi ; OK? yes reshi +reslo = INT+FRAC in hex, convert

Vavh2d:

clrf m

clrf m10

clrf count

Vavloh2d: ; m is 2nd dec, use m10

movf count,w

xorwf reslo,w

btfsc STATUS,Z

goto Vavloend

incf count,f

incf m10,f

movlw 0xA

xorwf m10,w

btfss STATUS,Z

goto Vavloh2d

clrf m10

incf m,f

goto Vavloh2d

Vavloend:

clrf m100

clrf m1000

clrf count

Vavhih2d:

movf count,w

xorwf reshi,w

btfsc STATUS,Z

goto Vavhiend

incf count,f

incf m100,f

movlw 0xA

xorwf m100,w

btfss STATUS,Z

goto Vavhih2d

clrf m100

incf m1000,f

goto Vavhih2d

Vavhiend: ; We have Vav as: INT m1000,m100 and FRAC m10,m with Frac

Vavend:

nop

return

 

;----------------------------------------------------------------------;

; Display the Average velocity ;

;----------------------------------------------------------------------;

Dispvav:

movlw H'C0' ; position at beginning of second line

call SendINS

movf m1000, W ; x0 tens of km

call SendASCII

movf m100,W ; 0x ones of km

call SendASCII

movlw "." ; "." punto decimal

call SendCHAR

movf m10,W ; "0.x0" decimal

call SendASCII

movf m, W ; "0.0x" decimal

call SendASCII

movlw "k" ; k

call SendCHAR

movlw "m" ; m

call SendCHAR

movlw "/" ; /

call SendCHAR

movlw "h" ; h

call SendCHAR

movlw "r" ; r

call SendCHAR

movlw " " ; " "

call SendCHAR

movlw "V" ; V

call SendCHAR

movlw "e" ; e

call SendCHAR

movlw "l" ; l

call SendCHAR

movlw "A" ; A

call SendCHAR

movlw "v" ; v

call SendCHAR

movlw "g" ; g

call SendCHAR

movlw " " ; " "

call SendCHAR

Dispvavend:

Return ; to change seconds for next second

;--------------END OF AV SPEED-------------------

 

 

 

 

 

 

 

; ---------------------------------------------------------------

; Instantaneous Speed

;-----------------------------------------------------------------

; Previous time values are subtracted from the present

; sec, TMR18, TMR0 values.

; This time difference is the time between

; wheel pulses. This in turn for 26" wheel is a distance of 2.0747m

; is covered in totms

; ---------------------------------------------------------------

; Instantaneous Speed

;-----------------------------------------------------------------

; Note sec can only move between 0 and 9, 10 is a new 0

; We start by reading sec, TMR18, TMR0 TO GET START TIME

Speed:

Spdflg0: ; FIRST TIMEwith spdflg=0, second time with spdflg=1

; First time captures timezero 0 in ms in totms

clrw

xorwf spdflg,w

btfss STATUS ,Z

goto Spdflg1 ; spdflg is not 0, this is the second time

call Summs

movf mshi,w

movwf totmshi

movf mslo,w

movwf totmslo

incf spdflg,f ; (spdflg = 1 for SECOND TIME)

return ;jump back to main menu

Summs: ; this routine is common to the first and second time

movf sec,w ; spdflg = 0

movwf mbl ; sec can only be in range 0 to 9

clrf mbh

movlw 0x03 ; 1000 = 03E8

movwf mah

movlw 0xE8 ; 1000 = 03E8

movwf mal

call Mult16x16 ;

movf mq2,w ; hi byte

movwf mshi

movf mq1,w ; lo byte

movwf mslo

movf TMR18,w

movwf mal

clrf mah

movlw D'56'

movwf mbl

clrf mbh

call Mult16x16 ; after themult we add

movf mshi,w

movwf q1hi

movf mslo,w

movwf q1lo

movf mq2,w

movwf q2hi

movf mq1,w

movwf q2lo

call Add

movf rhi,w

movwf mshi

movf rlo,w

movwf mslo ; sum (sec +TMR18)

;TMR0 is a little more complex as we have to subtract39

; before we can calculate ms in TMR0

movf TMR0,w

movwf q1lo

clrf q1hi

movlw D'39'

movwf q2lo

clrf q2hi

call Sub

movf rlo, w

movwf numlo

clrf numhi

movlw 0x4

movwf denlo

clrf denhi

call Div

movf mshi,w

movwf q1hi

movf mslo,w

movwf q1lo

movf reshi,w

movwf q2hi

movf reslo,w

movwf q2lo

call Add

movf rhi,w

movwf mshi

movf rlo,w

movwf mslo ; ( SEC +TMR18+ TMR0) in ms mshi/lo

RETURN ; Summs

Summsend:

 

Spdflg1: ; SECOND TIME is with spdflg =1

; Second time captures timezero to 2nd Pulse

; in ms, store in totms2

; for test we add 250ms to simulate time between

; wheel pulses

; 250ms delay

;movlw D'63' ; DUMMY FOR TEST

;call nmsec ; DUMMY FOR TEST

call Summs

movf mshi,w ;

movwf totms2hi ;

movf mslo,w ;

movwf totms2lo ;

 

; totms2 should be larger than totms,however if totms2 has just rolled,

; then add 10000 to tot2

Testtot2:

movf totms2hi,w

subwf totmshi,w

btfss STATUS,C ;compare for greater

goto Diffms ;totms2 > totms no add 10000 needed

movlw 0xA ;totms2 < totms, add 10000, hex 2710

movlw 0x27

movwf q1hi

movlw 0x10

movwf q1lo

movf totms2hi,w

movwf q2hi

movf totms2lo,w

movwf q2lo

call Add ; tot2 +10000

movf rhi,w

movwf totms2hi

movf rlo,w

movwf totms2lo ; tot2 = tot2+10000

 

Diffms:

 

; sub (tot2-tot1)for time between wheel pulses

movf totms2hi,w ;

movwf q1hi

movf totms2lo,w

movwf q1lo

movf totmshi,w

movwf q2hi

movf totmslo,w

movwf q2lo

call Sub ; result is time diff, stored in rhi, rlo

tp2:

; we are almost ready to divide dist/time for speed

; complete equation is dist/time x3.6

; to avoid as far as possible fractions we multiply before divide

; but this time, better divide first.

; 2000 36 <--- this is more than 65536

; ---- x --------

; denhi/lo 10 ( denhi/lo is sub result rhi/lo)

; so we can divide by 10 and x by 36 ( always,)

; so top line is simply 7200.

; we finally have 7200/(denhi/lo) , SPEED IN HEX

 

movf rhi,w

movwf denhi

movf rlo,w

movwf denlo ; denom is time in hex

movlw 0x1C ; 7200, hex 1C20

movwf numhi

movlw 0x20 ; 7200, hex 1C20

movwf numlo

call Div

; the result , res, is more than 1

;and a remainder rmdr/den

;we now have 6 free variables

; mshi/lo for INT hex speed lo is enough

; totmshi/lo

; totms2hi/lo

;we will reuse to convert from hex to decimal

movf reslo,w

movwf mshi ; INT part of hex speed ( hi, because FRAC will be in lo)

;we will only use 1 decimal of

;the hex speed remainder, so 1st rmdrx10

; so next calculation is

; 10 x rmdrhi/lo

; ---------------

; denhi/lo

movf rmdrhi,w

movwf mah

movf rmdrlo,w

movwf mal

clrf mbh

movlw 0x0A

movwf mbl

call Mult16x16 ;( ten times top)

movf mq2,w

movwf numhi

movf mq1,w

movwf numlo ; the den is previously loaded so divide for

; decimal part of speed ( still in hex)

call Div ; we only use 1 decimal, so just use lo of Div result

movf reslo,w

movwf mslo ; FRAC of speed in hex

; now convert speed to decimal form

; i.e. mshi, mslo --> 99.9 km/hr

Spdh2d:

clrf m

clrf m10

clrf m100

clrf m1000

clrf count

 

Spdlo:

movf count,w

xorwf mslo,w

btfsc STATUS,Z

goto Spdhicnt

incf count,f

incf m10,f

movlw 0xA

xorwf m10,w

btfss STATUS,Z

goto Spdlo

clrf m10

incf m,f

goto Spdlo

Spdhicnt:

clrf m100

clrf m1000

clrf count

Spdhi:

movf count,w

xorwf mshi,w

btfsc STATUS,Z

goto Spdhiend

incf count,f

incf m100,f

movlw 0xA

xorwf m100,w

btfss STATUS,Z

goto Spdhi

clrf m100

incf m1000,f

goto Spdhi

Spdhiend:; We have filled m1000,m100 with INT and m10,m with Frac, of Vin.

; Note we only need m10 ( 1 decimal place)

clrf spdflg ; reset to 0 for next pair of pulses

 

 

 

 

 

 

; incf spdflg,f ; (spdflg = 1 for SECOND TIME)

return

; ---------------------------------------------------------------**

; End of Instantaneous Speed

; ---------------------------------------------------------------**

 

 

Dispd:

;----------------------------------------------------------------------;

; Display the Instantaneous Speed (Speed) ;

;----------------------------------------------------------------------;

movlw H'C0' ; position at beginning of second line

call SendINS

 

movf m1000, W ; x0 tens of km

call SendASCII

movf m100,W ; 0x ones of km

call SendASCII

movlw "." ; "." punto decimal

call SendCHAR

movf m10,W ; "0.x0" decimal

call SendASCII

movf m, W ; "0.0x" decimal

call SendASCII

movlw "k" ; k

call SendCHAR

movlw "m" ; m

call SendCHAR

movlw "/" ; /

call SendCHAR

movlw "h" ; h

call SendCHAR

movlw "r" ; r

call SendCHAR

movlw " " ; " "

call SendCHAR

movlw "S" ; S

call SendCHAR

movlw "p" ; p

call SendCHAR

movlw "e" ; e

call SendCHAR

movlw "e" ; e

call SendCHAR

movlw "d" ; d

call SendCHAR

Dispdend:

Return ; to change seconds for next second

;--------------END OF Inst SPEED-------------------

end

;-----------------------------------------------------

; bike computer program end ....enjoy

;-----------------------------------------------------

 

 

; WORK IN HAND

; CLEAN UP SPEED, readout still a little jumpy,

; can try integrating but need more space. Next version

; Coventions used in the program text.

;Variables all small letters , exceptions, those defined

; by microchip. e.g. STATUS

;Labels: First letter always a Capital, exceptions imported

; routines

; Test points. These have a comment DUMMY, the value of the code

; has/had been changed for testing or simulating. If YOU want

;to polish these points should be useful for value changes

; example. In ISR the D'18' value to reach a sec is very slow.

;Use for test , say 2, and you get going about 10 times faster.

;Also LCD INIT: can be bypassed to debug quicker

 

;----------------------------------------------------------------------------------------------------

; End of the Simple Bike Computer

;----------------------------------------------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The END Product the HEX file

 

If you have managed to read to here, through all that has been written, then you certainly have determination.

Well " getting here" is the moment when you have mastered all the steps in writing the PIC assembler source code. Getting here also means you can do all the manual side as well for many future projects.

But maybe the most satisfaction is obtained by taking the final code version

and then burning it into the PIC to make your Bike Computer a reality,….not just a bit of theory.

Ah I almost forgot, here is the Bike3.asm squeezed into the END PRODUCT of our toil.

Bike3. hex

:020000000528D1

:080008004C289220BD20CB0121

:10001000C80138083206031909283208B800CB0A8B

:100020002E2186018612061A132886160A302221EE

:10003000061A18280A302221061A182886120608DD

:100040000A304B02031C25283028CB220A304B02F1

:10005000031C2B20302803014806031970230800D5

:10006000C4210A304B02031C392814304B02031CF4

:100070004B21122214304B02031C42281E304B022B

:10008000031CA4221F304B06031D4728CB01380850

:100090003206031911280928BB00030EBC00040E08

:1000A000BD0027308100BA0A12303A06031D8A28A3

:1000B000BA01B20AB00A030130060319B10A0A30C4

:1000C0003206031D8A28B201B30A06303306031D27

:1000D0008A28B301B40A0A303406031D8A28B40101

:1000E000B50A06303506031D8A28B501B60A0A305E

:1000F0003606031D8A28B601B70A0A303706031DE3

:100100008A28B201B301B401B501B601B701BA0141

:10011000B8018A283C0E83003D0E8400BB0E3B0EC6

:100120000B11090085018601003065005030660022

:10013000073062000030AC01AD01AE01AF01A60195

:10014000A701A801A901AA01AB01C301C201C50110

:10015000C401A501B701B601B501B401B801B301ED

:10016000B201B001A201A301B001B101BA0127306F

:1001700081008B01A0308B0008002830222105115E

:100180000330EB201F21E0201A21E0201A21051165

:100190000230EB201A212830E3201030E320013018

:1001A000E3201F210630E3200C30E3200800303E1E

:1001B000C900490E0515EB2049080515EB2008007C

:1001C000851585110800C900490E0511EB20490865

:1001D0000511EB2008008600E02085151A21080093

:1001E00084000408840AF920003803190800D82084

:1001F000F1288207423469346B3465342034433447

:100200006F346D3470347534743465347234003442

:1002100082074434693473347434003482072034E0

:100220004134763420347334703465346534643446

:100230003A3400342930FF3E031D1B2908000530E5

:100240002229FA30B900FE301B210000B90B232906

:100250000800212121212121212108008030E320D3

:100260003708D7203608D7203A30D8203508D7208D

:100270003408D7203A30D8203308D7203208D72086

:100280002030D8206830D8206D30D8207330D82066

:100290002030D8200800C030E3202B08D7202A08BF

:1002A000D7202908D7206B30D8206D30D8202030B7

:1002B000D8202808D7202708D7202608D7206D3037

:1002C000D8202030D8204430D8206930D82073304E

:1002D000D8207430D8202030D82008008C018D011F

:1002E0008E018F018E17920C930C031C7D2911082F

:1002F0008D0710080318100F8C078C0C8D0C8E0CBA

:100300008F0C031C73299001910192019301080045

:100310008B2100000800A6219901980103109B0D74

:100320009A0D980D990D15081902031D99291408A5

:100330001802031CA22914089802031C990315082B

:1003400099020314960D970DC90B8E291030C90020

:1003500017089A0016089B009701960100340800C0

:100360001D081F07A1001C080318013E1E07A0005E

:1003700008001F081D02A100031CBF29C0299C03FF

:100380001E081C02A0000800CA0102304A06031918

:10039000112AA60A0A302606031DF329A601A70A78

:1003A0000A302706031DF329A701A80A0A302806E8

:1003B000031DF329A801A90A0A302906031DF32900

:1003C000A901AA0A0A302A06031DF329AA01AB0AC9

:1003D0000A302B06031DF329A601A701A801A901D4

:1003E000AA01AB01F329A20A03012206031DFE297B

:1003F000A30A03012306031DFE29A40A3630970031

:100400002508170203180C2A383097002508170210

:1004100003180F2AA5010C2AA50ACA0AC529A50A8C

:10042000C529080003013006031D1B2A03013106FC

:10043000031D1B2A0800073023020318282A23085B

:10044000AF002208AE003108AD003008AC004B2AE6

:100450002308970022089600073095000830940082

:1004600088211B0ACA0023089700220896009501DC

:100470004A08940088211A08AF001B08AE00310812

:1004800097003008960095014A08940088211A08C0

:10049000AD001B08AC002F0892002E0893009001BD

:1004A000243091006E210E08AF000F08AE002D0819

:1004B00092002C08930090010A3091006E210E08E2

:1004C000AD000F08AC002F0897002E0896002D08ED

:1004D00095002C08940088212D0895002C08940084

:1004E0001A081B08AD001908920018089300900123

:1004F0000A3091006E210E0897000F08960088219F

:100500002D089A00AC01AD01CA014A081B06031967

:10051000922ACA0AAD0A0A302D06031D852AAD01AA

:10052000AC0A852AAE01AF01CA014A081A060319AE

:10053000A22ACA0AAE0A0A302E06031D952AAE0167

:10054000AF0A952A00000800C030E3202F08D7200A

:100550002E08D7202E30D8202D08D7202C08D720C1

:100560006B30D8206D30D8202F30D8206830D8207C

:100570007230D8202030D8205630D8206530D8208E

:100580006C30D8204130D8207630D8206730D82041

:100590002030D820080003014806031D122BD62264

:1005A0004608C3004708C200C80A08003208910084

:1005B000900103309200E83093006E210E08C600CF

:1005C0000F08C7003A08930092013830910090015B

:1005D0006E2146089C0047089D000E089E000F08EB

:1005E0009F00B0212008C6002108C70001089D0017

:1005F0009C0127309F009E01B92121089600970198

:10060000043094009501882146089C0047089D000D

:100610001A089E001B089F00B0212008C600210870

:10062000C7000800D6224608C5004708C400450890

:100630004302031C292B0A3027309C0010309D00F8

:1006400045089E0044089F00B0212008C5002108ED

:10065000C40045089C0044089D0043089E004208D1

:100660009F00B92120089500210894001C309700B4

:100670002030960088211B08C6001908920018082F

:10068000930090010A3091006E210E0897000F0828

:10069000960088211B08C700AC01AD01AE01AF0177

:1006A000CA014A08470603195E2BCA0AAD0A0A3076

:1006B0002D06031D512BAD01AC0A512BAE01AF012C

:1006C000CA014A08460603196E2BCA0AAE0A0A3046

:1006D0002E06031D612BAE01AF0A612BC801080075

:1006E000C030E3202F08D7202E08D7202E30D82066

:1006F0002D08D7202C08D7206B30D8206D30D8207B

:100700002F30D8206830D8207230D8202030D82020

:100710005330D8207030D8206530D8206530D820AC

:060720006430D82008003F

:02400E00F13F80

:00000001FF

 

CONCLUSION

Just a final word about the the skills we have learned up to here-

We said in the introduction, that most people maintain the hardest part of working with ucontrollers is writing the source code.

So we decided to start with the "easy" part, the hardware.

However after learning how to make our own PCB maybe we don’t agree.

The people who say the hardware is EASY, either lead a very secluded life (someome else does the layout, makes the PCB etc ), or perhaps they have never even thought that such things exist.

Then the source code side is the easier? No, simply it is different activity which can be as formidable as the hardware integration we have learned.

A final thought. Computer get faster and faster,... thanks to ?

Yes, you guessed it.. thanks to ongoing hardware improvements.

The factor which limits the computer today 2002 is the need to connect the bits together inside the computer box. It is now very important to consider and design the PCB, in the high speed parts, using microstrip technology.