please dont rip this site

Massmind news letter, Feburary 2003

First, this issue is late and is devoded to my father, James C. Newton, who passed away this month. He was the best of fathers and the worst of fathers (as we all are) and I will miss him dearly. If you have any good code you don't mind shareing, for goodness sake, send it to me so I can catch up and avoid thinking about it. <GRIN>

This months focus is on more flexible versions of the standard routines that we all need at one time or another. Checking a value against a min and max that may change rather than bounds that are hard coded. Setting a bit in a byte specified by an index register (aka bit array). Converting any number of bytes to any number of digits of packed BCD.

To start things off, here is a list of the different methods of doing a select (or table lookup) that shows which is best for a given range and type of input value. Note that the IREAD method is basically unlimited.

Select case switch

Here is a quick (and I hope thought provokeing ) list of possible ranges and types of input values and the method that will produce the most "efficient" (smallest and fastest) way of jumping to an address indexed by that value. i.e. "select case" or "switch" statement. Do you get the title now? <GRIN> This is a sort of a switch for the type of code to use for your select.

1 value starting from 0 <GRIN>
test and jump if zero flag set.
2 to 4* contiguous values starting from 0 (* or more if your code happens to be in the top half of a page)
BinJmp bit testing (see last months newsletter)
5 to 256* contiguous single byte values starting from 0 (* limited to 128 if you need to get to code outside your current page.)
Traditional jump table (add a value to the PC) But watch were your code gets put; first half page of each page only!
128 to 4096 contiguous 12 bit values starting from 0 (not that we have code space for this many subroutines...)
IREAD the address and then copy it to the page and PC
any number of mostly contiguous values
set aside a destination address to bit bucket the invalid values, pretend that the range is contigous and start over
any number of values NOT starting from 0
subtract the first possible value from the actual value and try again... duh!
1 to 256* really non-contiguous single byte values (* and how does one have 256 single byte values that are not contiguous? limited to about 64 really)
xor list (see below)
any number of multi byte values
http://www.piclist.com/cgi-bin/keyword.exe and then run the output through
http://www.sxlist.com/cgi-bin/mpasm2sasm2.exe to convert it to the SX

Which brings us to "what is an xor list"?

XOR List Select

	mov	W, rcreg
	xor	W, #'A'
	snz	; same as btfsc zero
	jmp	conversionA
	xor	W, #'A'^'B'	;undo the xor a, then xor b
	snz
	jmp	conversionB
	xor	W, #'B'^'C'	;undo the xor b, then xor c
	snz
	jmp	conversionC

This works because:  (X xor A) xor (A xor B)
is the same as: X xor (A xor A) xor B
which is the same as X xor 0 xor B
which is the same as X xor B.

If anyone is interested, I bet I could get this into a macro that you could call with any number of constant values and an index register.

	select reg
	case "A"

	case "B"

	case "C"

	endselect

Code Challenge.

Harold Hallikainen (who, by the way, provides the FCC rules on the web at his site http://www.hallikainen.org/FCC/FccRules/, and makes a darn fine line of lighting controllers (DMX etc..) at http://www.dovesystems.com/) posted this nice little range check sample. It is good because it works with min and max in ram rather than hard coded... Can you write a macro to build the shortest possible range check with constant min and max?

WindowTest macro value, min, max
;	call	as WindowTest value
; and cleared if not (wtfail).
; The key to this is the mov w,fr-w instruction. 
; Carry =1 if the result is greater than 0 (carry=1 is positive result). So,
;	carry=1 if f=>w
;	carry=0 if f<w or w>f
  local wtexit			; local labels in macro
  				; For min, we want value=>min, 
				;  so we'll put value in f and min in w
	mov	W, min		; Get minimum
	mov	W, value-w	; w=value-min. Result positive (carry set) if value=>min
	jnc	wtexit		; If no carry, we're below min. Exit with fail (carry clear)
				; For max, we want max=>value, 
				;  so we'll put max in f, value in w
	mov	W, value	; Get current value in w
	mov	W, max-w	; w = max-value. Result positive (carry set) 
				;  if max=>value. Exit with carry set
wtexit
	endm

The answer to last months code challange is, of course, at:
http://www.sxlist.com/techref/ubicom/lib/math/bit/mask_sx.htm

x byte Binary to y digit packed BCD (expandable)

This is pretty hot code! Seems to work just fine, but I haven't tested it extensivly. It's slower than some other versions, but when it comes to getting digits up for a human to look at, who cares?

; by FredMaher Madrid 10 Nov 02, Rewritten for SX by James Newton Feb 03.
; Using an extension of the >4 add 3 algorithm


	device  sx18
	reset   start:


BCDdigits = 5	;change as you like
BINdigits = 3	;change as you like


       org 16
bcd 	DS	BCDdigits
bin 	DS	BINdigits


IFNDEF count
count           DS	1
	ENDIF
IFNDEF temp
temp            DS	1
	ENDIF


;
	org 	0
Start:
;-----------------------------------------------------------------
;Hex(Binary) to BCD routine
;-----------------------------------------------------------------
Main:
	mov	temp, #BCDdigits
	mov	w, #bcd
	mov	fsr, w
BCDclear:
	clr	indf
	inc	fsr
	djnz	temp, BCDclear:
	
Testvals:
	mov	W, #0FFh
	mov	bin, W
	mov	W, #0FFh
	mov	bin+1, W
	mov	W, #0Fh
	mov	bin+2, W


	call	bin2bcd:
	
Convend:  ; remove when in main prg
	jmp	Convend:	; remove when in main prg


;-----------------------------------------------------------
; End main Bin Bcd
;------------------------------------------------------------


bin2bcd:
	mov	count, #BINdigits * 8	; count max value
	
Shifting:
	test	count
	snb	Z
	ret	; bin number is now converted 2 bcd
	dec	count
	
;----------------------------
; Now left shift all registers


	clrb	C
	mov	temp, #BINdigits
	mov	fsr, #bin
BINrlLoop:
	rl	indf
	inc	fsr
	djnz	temp, BINrlLoop:


	mov	temp, #BCDdigits
	mov	fsr, #bcd
BCDrlLoop:
	rl	indf
	inc	fsr
	djnz	temp, BCDrlLoop:

; next step check those which are >4 and add 3

	test	count
	snb	Z	; finish without testing >4
	ret

Nibtests:	;Test BCD, high and low nibbles. If greater than 4 ( or 40) add 3 (or 30)
	mov	temp, #BCDdigits
	mov	fsr, #bcd
BCDadjLoop:
	mov	W, #0Bh ;(16-5)
	add	W, indf	;DC set if carry from bit 3 to 4
	mov	W, #03h	; >4 add3
	snb	DC
	add	indf, W


	mov	W, #0B0h	; is high nibble more than 5?
	add	W, indf
	mov	W, #30h	; add 3 to high nibble
	snb	C
	add	indf, W
	inc	fsr
	djnz	temp, BCDadjLoop:
	
	jmp	Shifting:

ISR Calculator

I got the attached exe (in a zip to keep it from picking up a virus on the way) from a guy who didn't want to be identified, who says it was written by another guy who didn't want to be identified.... it passed norton on my machine and it seems to work great. Dont open it without anti-virus software... I won't take any responsibility. If anyone has the time to figure out how the exe works and write me some pseudo code, I'll try to make an online version.

There is something like this specifically designed to look for good values to match baud rate (or other) standard frequencies at
http://www.sxlist.com/techref/scenix/isrcalc.asp one of these days I'll expand on that so that it will also be able to generate a program template from the values you select.

Set or clear any bit as indexed by a register (aka bit arrays)

This amazing routine from Scott Dattalo can basically store a bit into any bit of any register. You give it a register value that counts off each bit in the register file (the top 5 bits of this index value tell us which register and the bottom 3 bits tell us which bit in that register) and a bit value to set that bit to. E.g. to clear the carry flag. Set the index (called "bit_position") to 0001 1000 (register 3 bit 0) and the "new_state" bit to 0. Bit arrays are useful for low resolution vision or pattern matching,

set_bit:

  ;Get a pointer to the byte containing the bit we want:

	mov	W, >>bit_position	;bit_position holds the bit number to set or clear
	mov	fsr, W

	rr	fsr
	mov	W, >>fsr
	and	W, #BIT_ARRAY_MASK 	;use this to exclude globals
	mov	fsr, W
	mov	W, #bit_array		;address of the start of the bit array
	add	fsr, W

  ; find 1<<(bit_position&7) [note, this could be made 2-cycles
  ;                           shorter, can you see how?]

	mov	W, #0101b
	snb	bit_position.0
	mov	W, #1010b

	mov	mask, W			;mask could be temp

	mov	W, #0011b
	snb	bit_position.1
	mov	W, #1100b

	and	mask, W

	snb	bit_position.2
	swap	mask

  ; now set or clear the bit

	mov	W, mask
	or	indf, W	; Assume we're setting.
	sb	new_state		;new_state has the bit value to store
	xor	W, indf	; assumption was wrong


Current project (IN WORK)

One of the really cool features in the IP2K processor from Ubicom is the "serdes" or serializer deserializer. This bit of hardware recognized that most forms of IO consist of some combination of a set of standard operatons. I'm trying to find a way to do that in software for the SX chips. The advantage would be that one "general purpose" virtual peripheral could then be configured to handle just about every type of IO we ever need. And... it could be setup on the fly.

mode .7 .6 .5 .4 .3 .2 .1 .0 Rate Data D:DataPresent, R:Rate C:Count
async serial rx / tx IO 1 0 0  1  P S D SRRR 1CCC P:Parity(none, even) S:Speed (High: 115,200, 57,600, 28,800, 14,400 Low:9600, 4800, 2400, 1200) In low speed mode, the count is reloaded with 12 rather than R every other time.
i2c data in / out IO 1 1 0     M D PPPP PPPP 200 (230?) Hz ISR 115.2bps. The I2C spec says SCL min low is 4.7uS and high is 4uS. That works out to 115Hz, but the spec also says SCL max is 100KHz. P bits decide which pin is the I2C clock
M:Mode (master, slave)
SPI in / out IO 1 1 0 PPPP PPPP
Quadrature decoder / Stepper IO 0 1 1 1 D PPPP PPPP Position (up/dn count of encoder or step) More than one pin on in the mask. Stepper can do any sort of pattern by recording the appropriate bit changes as a "wave" table in the FRAM buffer.
a2d / d2a IO 0 0 1 1     Single pin, sigma delta with Vin thru Rin to Cap then thru Rf to IO pin.
pluse width measurement / PWM IO 0 0 1 1 E D CCCC CCCC Duty cycle or measured pulse width C:Count Input:Set to FF when pin E:Edge(set or cleared) and dec until pin changes then copied to Data. Output: C is copied from Data and pin set to E. Then C is dec to zero and pin set to not E. Finally C is then loaded with 255-Data and dec to zero again.
freq count / generate IO 0 0 1 0 R D CCCC CCCC
bit pattern capture / generate (magic sine) IO 1 0 0 0 D 1RRR 1CCC
wave capture / out IO 0 1 0 D PPPP PPPP
in_out	equ	.7	;input or output
serial	equ	.6	;serial or parallel (do we shift in/out the data?)
pinmask	equ	.5	;serial sync or async (is there a clock pin?) 
			; Also decides if the Rate byte is a pin mask or a counter.
width	equ	.4	;is Rate counter 3 bits (reloaded from upper 3 bits) or 8 bits (loaded from/to data)
			; if Rate is not zero, and data with Rate and then input or output.
trigger	equ	.3	;Do we wait for a trigger (e.g. stop bit, clock, encoder pulse, cap charge, or just keep running?
			; 




ser_des_vp
	clr	mask
	inc	mask
	mov	fsr, pincfg+0

:each_pin
	mov	w, port
	and	w, mask
	clc
	sz
	 stc			;Pin state is in C
:counter
	dec	ind		;Reduce the counter
	jb	ind.3, cnt_done	;Check for wrap
	inc	ind		;Prep for next count xxxx0111 -> xxxx1000
				; So a preset can be or'd in. Also, .3
				; must remain set so that we know this is
				; a timed pin.
	jb	ind.serial	;If this is a serial pin
:is_serial
	setb	fsr.4		;Point to data byte for this pin
	rl	ind		;Store C in MSB and get C from LSB
	clrb	fsr.4		;back to pin config
	jmp	cnt_done

:not_serial


:cnt_done
	jb	ind.in_out	;if this is an output pin
	jc	bit_set
:bit_clear
	mov	w, ~mask	;clear the pin if the data bit is zero
	and	port, W
	jmp	in_out
:bit_set
	or	port, W		;set the pin if the data bit is one.
:in_out

:pin_done
:next_pin
	rl	mask
	inc	fsr
	
	
	

Question of the month:

If you document everything you know and write expert systems (e.g. code generators, macros, languages, etc... ) that can duplicate most of what you are good at, will you live on forever?

Feedback:

Please do comment on any errors, improvments, confusions or ideas that are found in this letter.

Thanks!

---
James Newton, Host of SXList.com
james@sxlist.com 1-619-652-0593 fax:1-208-279-8767
SX FAQ / Code / Tutorials / Documentation: 
http://www.sxlist.com Pick faster!

file: /Techref/new/letter/news0302.htm, 15KB, , updated: 2004/1/14 14:50, local time: 2024/12/22 05:47,
TOP NEW HELP FIND: 
3.145.16.251:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://massmind.org/Techref/new/letter/news0302.htm"> Massmind news letter, Feburary 2003</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

 

Welcome to massmind.org!

 

Welcome to massmind.org!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .