Pic Program to update single bits from table

Trying to figure out an easy way to update a single bit within a group of 24 bits (3 bytes) using a lookup table that returns 8 bits. The first 5 bits from the table will indicate the bit to be updated (1of

24) and the 6th bit will indicate a set or reset for that particular bit.

Thought about using a counter and 3 other registers to shift the bit through the 3 registers so the single bit appears in the correct place, and then do an inclusive or to mask the bit into the existing data. but it seems complicated.

Have any other ideas?

-Bill

Reply to
Bill B
Loading thread data ...

Assuming that you are using the typical 16Fxx type PIC, you really don't have any easy way to do it. It might take a little less code if you divide the 5 bit offset field into two fields. Two bits for the byte number (0,1, or 2) and three bits for the bit position within the byte. Use the 2-bit field to set up the FSR to point to the appropriate byte. Then you can just use the three-bit field to index (by adding to the PCL) into a table that looks something like this: retlw 0b00000001 retlw 0b00000010 retlw 0b00000100 retlw 0b00001000 retlw 0b00010000 retlw 0b00100000 retlw 0b01000000 retlw 0b10000000 If necessary, negate the retrieved byte to AND off a bit, or use it as is to OR one on in the byte pointed to by the FSR.

Reply to
Anthony Fremont

It's called math:

call your first 5 bits the index, the 6th bit the value, the 8-bits a and the 24-bits stream:

then it's

(stream & ~(1 > 6) & 1) > 6) & 1;

This shifts the 6th bit to the first 1 and then ands it with 1 so that the higher bits go to 0.

index = a && 011111b;

this gets teh index, which is just the first 5 bits. i.e., I set the top 3 bits to 0 and so I'm just left with the lower 5 having any effect.

but index represents the shifting amount. i.e., if index = 8 then I shift 8 bits...

i.e.,

value place, and then do an inclusive or to mask the bit into the existing

Not sure what you are talking about here. Bit manipulation can almost always be done using boolean logic. You just have to use the standard tricks and know how the operators work.

heres a concrete example for what is above: (I'm using low bit first and only a trimmed down version)

suppose stream = 0110101 (7bits, not 24) value = 110x (lower 3 bits = index, 4th bit = value)

then

index = a & 111b = 110 = 3 value = a >> 3 = x

1
Reply to
Jon Slaughter

you have the number of bits you need to shift by in three of the bits and an address offset in the other two bits and the action to perform in the last bit.

Bye. Jasen

Reply to
Jasen Betts

"Bill B" schreef in bericht news: snipped-for-privacy@p59g2000hsd.googlegroups.com...

Complicated? Seems straight forward to me, though not the most efficient in speed as you need an average of 36 shift and jump operations. To improve speed you can consider the following:

- pick up the update byte from the table and store ir somewhere

- use bit 3 and 4 (so the fourth and fifth bit) to point the indirect register to the byte that needs to be updated

- use bit 0-3 to prepare the mask

- check bit 5 to see if you need to set or to reset

- if set is required, use an OR operation, if reset is required complement mask and use an AND.

petrus bitbyter

Reply to
petrus bitbyter

tsk tsk, that wasn't very nice

I think the OP is talking about doing it with PIC assembly language.

Reply to
Anthony Fremont

It's true though... nice or not. Point I was trying to make is that you don't need anything else.

um, yes, you have to translate it.. All cpu's have boolean logic to do such things. (i.e. ALU)

Reply to
Jon Slaughter

Yes, it's easy with high level languages, but I need a little more speed and memory conservation, so assembly language is the preferred method.

Thanks,

-Bill

Reply to
Bill B

Yes, that's a good idea, I was using IORWF against say "00010000" to set bit 4, but I hadn't thought of using the negative "11101111" with the ANDWF to reset the bit. I'll give that a try.

Thanks,

-Bill

Reply to
Bill B

[snip]

The following might save an instruction or two --

  1. Get byte in accumulator
  2. OR accumulator with 1-bit mask M.
  3. Go to 4 if bit is being set.
  4. XOR accumulator with M
  5. ...
--
jiw
Reply to
James Waldby

That'll only set the mask. You also have to update a byte.

Suppose:

'updbyte' to be a copy picked from the update table FSR pointing to the byte to be updated 'mask' to be the prepared mask, containing one 1

movf mask,w ; (Only if mask is not in w already) btfsz updbyte, 5 ; check for set or reset goto setupd ; set required go for it xorlw 0xff ; reset required so complement mask andwf IND,r ; reset bit goto continue ; reset done, so continue setupd iorwf IND,r ; set bit continue nop

As there are only few instructions, I see no way to save one or two.

petrus bitbyter

Reply to
petrus bitbyter

movf mask,w ; (Only if mask is not in w already) iorwf IND,r ; set bit btfss updbyte, 5 ; check for set or reset xorwf IND,r ; reset bit continue nop

--
jiw
Reply to
James Waldby

Clever.

Reply to
Anthony Fremont

This is dangerous, if an interrupt is generated after the iorwf.

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply to
Frank Buss

How so?

Reply to
Anthony Fremont

If an interrupt occurs before the reset then the state might not be properly defined if the interrupt depends on the data. Turning off interrupts for the modification will help but writing the bit in one go is best.

Reply to
Jon Slaughter

Depends if you have room to trade space for speed.

Another way is to take the bitno in W and shift it left once then have a computed jump table with 24 following 2 byte entries of the form:

BSF Reg0,0 RETURN BSF Reg0,1 RETURN ... BSF Reg0,7 RETURN BSF Reg1,0 etc. etc.

RETURN could be GOTO BSDONE

Obviously with long jump tables you have to take care not to have it spanning a segment boundary or unexpected results will ensue. This is about the simplest way, indivisible operation for bit change and possibly the fastest.

Regards, Martin Brown

Reply to
Martin Brown

Well duh, but that would be a logic error and that goes beyond the scope of this discussion; we could make up scenarios like that all day. I was thinking (well hoping) Frank had something special for us pertaining to the PIC architecture.

With all due respect, that's more a matter of opinion than one of fact as it depends upon the specific application. If the ISR is dependant upon the data that is currently being modified, then disabling INTs for a few instructions [atomizing the update] is probably the best thing to do to, unless your ISR can't handle the entry jitter. In that case, you need to rethink the design. Otherwise, I don't see how an INT occuring at that location can cause any harm if the ISR is properly saving and restoring the program context before returning. Please elaborate Frank.

Reply to
Anthony Fremont

Yes, this might be a solution. And you are right, it depends on the application. But I prefer to write code that can't break, e.g. you use this nice small code, because you don't use interrupts. Then some years later someone adds interrupts and forgets to check the rest of the program and it could cause a bug.

--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Reply to
Frank Buss

You really save two instructions but I don't like the price. You set a bit for some microseconds. Depending on the application it may not do any harm. But suppose the bit switches a motor for instance when the byte is copied to an output port by an interrupt routine? If things can go wrong they will eventually go wrong and at that time you will have to pay an high interest for the bytes saved now. I've seen this kind of things go wrong you know and I learned to avoid chanches like that whenever I can. Nevertheless I once more agree: You saved two instructions.

petrus bitbyter

Reply to
petrus bitbyter

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.