Alwin Blok wrote:
I was playing wih the framebuffer device, using pack, I was able to get
the bits where I wanted, but It’s not handy when you want gradients and
other fancy stuff
When I use
File.open(‘/dev/fb0’,‘w’) do |fb|
(800*600).times do
fb.putc 0b0111110000000000
end
end
I get half my screen filled, Which is obvious since putc is short for
putchar (i assume), hence 8bits
(the screen is 16 bits color)
For that specific case, 2 x putc
File.open(‘/dev/fb0’,‘w’) do |fb|
(800*600).times do
fb.putc 0b011111000
fb.putc 0
end
end
… but, I know, you want something more flexible.
It intrigues me that you’d want to write, say, 10 bits when you
haven’t specified left, right or no padding.
Here are all the screen size options on my display adapter.
Test width / height exactly divisible by 8
ss = lambda {|w, h| p [w % 8 == 0, w/8, h % 8 == 0, h/8]}
ss[ 640, 480]
ss[ 800, 600]
ss[1024, 768]
ss[1152, 864]
ss[1280, 1024]
ss[1600, 1200]
#-> [true, 80, true, 60]
#-> [true, 100, true, 75]
#-> [true, 128, true, 96]
#-> [true, 144, true, 108]
#-> [true, 160, true, 128]
#-> [true, 200, true, 150]
Anyway, see if any of this helps …
Constraint:
···
#------------
If the bit pattern is to be given as an integer,
the pattern length also needs to given because
leading zeros have no significance.
puts
puts 0b0110.to_s(2)
puts 0b00110.to_s(2)
puts 0b00000000000000110.to_s(2)
puts
Strings have a slight advantage in this respect.
puts ‘0110’.length
puts ‘00110’.length
puts ‘00000000000000110’.length
OTOH, with known length, leading zeros
need not be given.
fmt = “%010b\n”
(e.g. these examples are equivalent):
puts format(fmt, 0b110)
puts format(fmt, 0b0110)
puts format(fmt, 0b00000000000000110)
puts format(fmt, 6)
#-> 110
#-> 110
#-> 110
#->
#-> 4
#-> 5
#-> 17
#-> 0000000110
#-> 0000000110
#-> 0000000110
#-> 0000000110
Here’s a buffered write to play with:
(messed up by comments & display stuff)
#-----------------------------------------------------------------
$watch = true
n = 0b1001_11101101_00010000
nbits = 20 # n represents 20 bits
Normally start with:
##> buff = bufn = 0
buff = 0b10 # example remainder from “previous use”
bufn = 3 # buff represents 3 bits == 010
Prepend bits (less than a full byte) to new bits
n |= (buff << nbits)
Temporarily adjust the number of bits to write this time round
nb = nbits + bufn
if $watch
printf(“START (%2d) x[%08x] b[%0#{nb}b]\n\n”, nb, n, n)
end
while nb >= 8
nb -=8
mask = 0xff << nb ## find the first full byte
n8 = (n & mask) ## temporarily ignore the rest
if $watch
printf(“mask x[%08x] b[%0#{nb+8}b]\n”, mask, mask)
printf(“tmp x[%08x] b[%0#{nb+8}b]\n”, n8, n8)
end
n ^= n8 ## remove these 8 bits from the bits to be written
n8 >>= nb ## move these 8 bits down to bits 7…0
if $watch
printf(“putc x[%08x] b[%08b]\n\n”, n8, n8)
printf(“NEXTn (%2d) x[%08x] b[%0#{nb}b]\n”, nb, n, n)
puts ‘-’*10
end
end
buff = n ## save partial last byte for next time round
bufn = nb ## AND the exact number of bits with significance
if $watch
printf(“-> buff %0#{bufn}b\n”, buff)
end
#-----------------------------------------------------------------
And here’s how it might look in the real world:
class Screen
def initialize(w, h, nbits = 16)
@width = w
@height = h
@nbits = nbits
@screen = File.open(‘tbinary.dat’, ‘wb’)
@screen.sync = true
@buff = 0
@bufn = 0 # Number of unwritten bits in buffer
end
def close
##
@buff <<= 8-@bufn # align left in byte
@screen.putc(@buff) # write to screen
@screen.close
end
def write(patt, nbits = @nbits)
patt |= (@buff << nbits)
nb = nbits + @bufn
while nb >= 8
nb -=8
mask = 0xff << nb ## find the first full byte
n8 = (patt & mask) ## temporarily ignore the rest
patt ^= n8 ## remove these 8 bits from the bits to be written
n8 >>= nb ## move these 8 bits down to bits 7......0
@screen.putc(n8) # write to screen
end
@buff = patt ## save partial last byte for next time round
@bufn = nb ## AND the exact number of bits with significance
end
end
fb = Screen.new(800, 600, 10)
5.times {fb.write(0b11111010, 16)}
fb.write 0b1101101101 # length 10 from Screen.new
fb.write 0b1010111010
fb.write(0b0011001100, 40)
fb.close
See what happened …
File.open(‘tbinary.dat’, ‘rb’) do |fb|
bd = fb.read
puts bd.unpack(‘H*’)
end
#-> 00fa00fa00fa00fa00fadb6ba00000000cc0
#-----------------------------------------------------------------
So my real question is:
What command do I use to put an arbitrary amount of bits?
putc
I can think of some ways, but I hate it when it feels like a workaround.
I know what you mean.
It’s not a workaround, it’s a tricky problem. Once you have a
method which does what you want, you can forget about the complexity
and advance to the next stage like adding Screen#fill(pattern).
Thanks
-Alwin
OK,
daz