Page 1 of 1

setting a bit on a ram variable

Posted: Wed Nov 11, 2015 3:30 am
by Scorpion Illuminati
Lets say i have a int variable called flags. As you know an integer has 8 bits.

Code: Select all

7-6-5-4-3-2-1-0
How would I set bit X where x is 0 to 7? For example:

Code: Select all

flags       equ (audio_clock+SizeWord)

FLAG_FRET_GREEN       equ 0x1
FLAG_FRET_RED           equ 0x2
FLAG_FRET_YELLOW    equ 0x4

// now set it
?????
I want to set a bit without effecting the other ones. Any assistance in this matter would be greatly appreciated.

Sincerely,

Scorpion Illuminati

Re: setting a bit on a ram variable

Posted: Wed Nov 11, 2015 5:33 am
by TmEE co.(TM)
In assembly you use the BSET instruction.

in C I think there's no choice but to use logic functions.

Re: setting a bit on a ram variable

Posted: Wed Nov 11, 2015 5:43 am
by mikejmoffitt
In C, you can do it a few ways. Here is one

Code: Select all


// To set a bit
var = var | (1 << bit);

// To clear a bit
var = var & (~(1 << bit));

If you are more comfortable, you can make a macro:

Code: Select all


#define BITSET(x, y) x = x | ( 1 << y)
#define BITCLR(x, y) x = x & (~(1 << y))

// You can now do this:
BITSET(var, 2); // Set bit 2
BITCLR(var, 0); // Clear bit 0

If the compiler is even half decent, it should see what you're doing and optimize it to a BSET. GCC is smart enough to see that 1 << (any immediate value) can be determined at compile time, and should also see that you are ORing with a constant that has only one bit set.

Re: setting a bit on a ram variable

Posted: Wed Nov 11, 2015 10:44 am
by BigEvilCorporation
Yep, BSET is the tool for the job, note that it takes a bit number (0, 1, 2, 3, etc) instead of the bit value itself (1, 2, 4, 8, etc).

You can also abuse SNASM68K's "rs" family of keywords to make an enum of sorts:

Code: Select all

   rsset 0
FLAG_FRET_GREEN       rs.b 1
FLAG_FRET_RED           rs.b 1
FLAG_FRET_YELLOW     rs.b 1
I use the same for declaring structures, and the memory map too, which cleans up that "(audio_clock+SizeWord)" mess I wrote when I started coding.

Re: setting a bit on a ram variable

Posted: Thu Nov 12, 2015 11:09 pm
by Scorpion Illuminati
Thanks for the info. Am having a bit of trouble figuring out how to use it effectively. Here's the proposed code:

Code: Select all

      btst #pad_button_a, d0                                                   ; Check A button
      bne @NoA                                                                       ; Branch if button off
      bset #FLAG_FRET_GREEN, (fret_flags)                             ; set the green fret bit
@NoA:
      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit
The problem is no matter what the clear bit instruction executes regardless if the button is on or off. Any assistance in this matter would be greatly appreciated.

Sincerely,

Scorpion Illuminati

Re: setting a bit on a ram variable

Posted: Thu Nov 12, 2015 11:46 pm
by Mask of Destiny
You don't have a branch instruction after the bset, so after it sets the flag, the bclr instruction runs and clears it. Instead you want something like this:

Code: Select all

      btst #pad_button_a, d0                                                   ; Check A button
      bne @NoA                                                                       ; Branch if button off
      bset #FLAG_FRET_GREEN, (fret_flags)                             ; set the green fret bit
      bra @GotA
@NoA:
      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit
@GotA:

Re: setting a bit on a ram variable

Posted: Fri Nov 13, 2015 2:03 am
by Scorpion Illuminati
Mask of Destiny wrote:You don't have a branch instruction after the bset, so after it sets the flag, the bclr instruction runs and clears it. Instead you want something like this:

Code: Select all

      btst #pad_button_a, d0                                                   ; Check A button
      bne @NoA                                                                       ; Branch if button off
      bset #FLAG_FRET_GREEN, (fret_flags)                             ; set the green fret bit
      bra @GotA
@NoA:
      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit
@GotA:
Any way to shorten it to not use the bra instruction?

Sincerely,

Scorpion Illuminati

Re: setting a bit on a ram variable

Posted: Fri Nov 13, 2015 5:47 am
by Mask of Destiny
There are other ways to achieve similar goals. Which one would be best depend on what you're optimizing for (cycle count, size, RAM usage). For instance, if you want to optimize for cycle count or code size by sacrificing memory usage, you could use scc to set a byte to either $FF or 0 depending on a condition code. Another option might be to just save the pad state somewhere and test it directly rather than trying to translate it into another bitfield.

Another option might be to rethink the code a bit. Presumably you're going to check a bunch of buttons and then update all the corresponding flags. Rather than clearing and setting each bit individually you could clear the entire fret_flags variable and only do a bset for the flags that need it. While you're at it, you could move fret_flags into a register temporarily to burn a lot fewer cycles on memory access.

So something like

Code: Select all

	moveq #0, d1
	btst #pad_button_a, d0
	bne @NoA
	bset #FLAG_FRET_GREEN, d1
@NoA:
        ;handle other buttons here
        move.b d1, fret_flags

Re: setting a bit on a ram variable

Posted: Fri Nov 13, 2015 11:07 am
by Natsumi

Code: Select all

      bclr #FLAG_FRET_GREEN, (fret_flags)                              ; clear the green fret bit first
      btst #pad_button_a, d0                                           ; Check A button
      bne @NoA                                                         ; if button is off, skip setting the bit
      bset #FLAG_FRET_GREEN, (fret_flags)                              ; set the green fret bit

@NoA:
This is the easiest solution; of course there are ways to optimize cycle counts using lookuptables for example, but for 99% of the cases you'd use code like this, its completely impractical.