Put your multimeter's black lead on pin 3 or 8. Both are common pin as they are internally connected. Now put your meter's red lead on any other pin such as 1 or 5. If any of the display's segments glow then the display is common cathode.
Alphabet. In addition to the ten digits, seven-segment displays can be used to show most letters of the Latin, Cyrillic and Greek alphabets including punctuation. One such special case is the display of the letters A–F when denoting the hexadecimal values (digits) 10–15.
All linebreaks may be removed.
@s=unpack"C*",~"P\xdbLI\xc3a`[\@AB\xe0t\xc8df";
$_=<>;for$s(6,3,0){print map$s[hex$&]&1<<$_+$s?$_%2?"_":"|":" ",
0..2while/./g;print$/}
@s
stores the bits for each segment. The entries are in order from 0 to F (thanks to hex()
) and the bits map to segments in this order:
6 7 x
3 4 5
0 1 2
with 0
being the LSB. (Bit 6 is unused). The values are stored packed in the string bit-inverted so there are a lot more printable characters; the ~
operator flips the bits and unpack gives me numbers (perl's bitwise operators are much clumsier when it comes to strings).
With the data in hand I read the input and proceed to loop over it three times; the only difference between the three loops is the bitmask required. For each character of input three characters of output are printed. The character to be printed is
$s[ hex $& ] & (1 << ($_ + $s) )
? ($_ % 2 ? "_" : "|" )
: " "
where @s
is the lookup table, $s
is the shift in effect depending on the row, and $_
is whether we're printing the 1st, 2nd, or 3rd character in the row. If the right bit in the lookup table entry is false it prints a space; otherwise it prints a "|" on the sides or a "_" in the middle.
char*q,a=3;p(l){putchar(*q?"|#]u&rzc~vn:X=ZJ"[*q-(*q&64?55:48
)&15]+1>>l&1?"|_||_|_"[l]:32:10);}main(r,v)char**v;{for(;a--
;p())for(q=v[1];*q;++q)for(r=3;r--;)p(a-2?5-r-a*3:r-1?7:6);}
stdin
)char*q,b[9],gets(char*),a=3;p(l){putchar(*q?"|#]u&rzc~vn:X=ZJ"[*
q-(*q&64?55:48)&15]+1>>l&1?"|_||_|_"[l]:32:10);}main(r){for(gets
(b);a--;p())for(q=b;*q;++q)for(r=3;r--;)p(a-2?5-r-a*3:r-1?7:6);}
Explanation:
char*q,b[9],gets(char*),a=3;
p(l){
putchar(*q?
/*
* Each element of the magic string is decremented so 0x7F is
* '~' (0x7E). Each bit before the decrement represents
* a segment (thus "8" is 0x7F (0x7E), i.e. all 7 bits on).
* Bit 7 is always cleared so p(7) always prints a space.
*/
"|#]u&rzc~vn:X=ZJ"
[*q-(*q&64?55:48)&15]+1 /* d[ascii2hex(*q)] + 1 */
>>l&1 /* Is bit 'l' set? */
?"|_||_|_"[l] /* Yes; choose _ or | by position. */
:32 /* No; enter a space. */
:10); /* End of line. */
}
main(r){
for(gets(b);a--;p()) /* Grab input and loop through each of 3 lines (a = 2, 1, 0). */
for(q=b;*q;++q) /* Iterate across input. */
for(r=3;r--;) /* For each of three characters across... */
p(a-2?5-r-a*3:r-1?7:6); /* Print the segment, mapping position to the bit. */
}
COM Executable: 102 bytes
Assemble the following using A86 (this is the original, larger version):
dd 0801E8Ah,0BD80C380h,03B50154h,0D789D58Ah,0B20082BEh,077F33B03h,0C048A29h,0149F0420h
dd 020AD431h,088C402C4h,01468BC1h,0F8C1E0D3h,046220Fh,0AA036E8Dh,0DD75CAFEh,04609ED83h
dd 0C583D1EBh,0D0AB809h,075CDFEABh,0AA24B0C3h,021CD09B4h,05F0000C3h,020B7EBh,8EFB7C00h
dd 07C3EF75Fh,0BF7CF9E4h,0B6DE5FA2h
dw 0F47Ch
db 0DFh
Edit:
The DosBox issue is probably the way the program assumes register values at start-up. Anyhow, here's the modified source that assembles to 102 bytes and should work with DosBox:
mov bp,d1
mov ch,3
mov dx,ds ; if you want to use dos box, put "mov dx,08000h" here instead, it might fix the problem
mov di,dx
l4: mov si,082h
l3: mov bl,3
cmp byte ptr [si],0dh
je l5
mov cl,[si]
cmp cl,40h
jle l2
add cl,9
l2: and cl,0fh
l1: mov ax,word ptr [bp+1]
shl ax,cl
sar ax,15
and al,byte ptr [bp]
add bp,3
stosb
dec bl
jnz l1
sub bp,9
inc si
jmp l3
l5: add bp,9
mov ax,0d0ah
stosw
dec ch
jnz l4
mov al,'$'
stosb
mov ah,9
int 21h
d1: ret
dw 0
db '_'
dw 01011011111101011xb
db ' '
dw 0
db '|'
dw 01000111011111011xb
db '_'
dw 00011111011110111xb
db '|'
dw 01111100111100100xb
db '|'
dw 01010001010111111xb
db '_'
dw 01011011011011110xb
db '|'
dw 01101111111110100xb
Thanks to ephemient for a couple of tweaks!
Inspired by Jonas Gulle over in the Code Golf: The wave. Usually I'd be writing a 32-bit Linux ELF, but a 16-bit DOS COM is much smaller (shorter instructions, zero overhead).
46 instructions and 24 non-executed words. (They do stand out quite obviously at the end there, don't they?) Nothing tricky like reusing code as data; it probably wouldn't save more than 10 bytes anyhow.
C:\>od -xAn ss.com c930 82be ac00 0d3c 3e74 403c 027e 0904 0f24 0198 bbc8 0162 c301 0eb4 078a 0424 0474 7cb0 02eb 20b0 10cd 078a 0224 0474 5fb0 02eb 20b0 10cd 078a 0124 0474 7cb0 02eb 20b0 10cd bdeb f980 7420 b014 cd0d b010 cd0a 6610 c381 0010 0000 c180 eb10 c3a1 0002 0202 0200 0202 0202 0002 0002 0202 0105 0303 0607 0106 0707 0607 0304 0606 0107 0306 0301 0107 0307 0705 0706 0406 C:\>ss deadbeef _ _ _ _ _ _||_ |_| _||_ |_ |_ |_ |_||_ | ||_||_||_ |_ |
This just goes letter-by-letter printing the first line, then the second line, etc. using 3 bytes to store the 9 bits of data for each character. Obviously there's room left for enhancement… (This is my first time using NASM syntax; I'm more accustomed to gas but I couldn't convince it to output a raw binary.)
org 0x100
; initialize registers
xor cl,cl
; reset ds:[si] to start of arguments
start:
mov si,0x82
; load one character of arguments
read:
lodsb
cmp al,0xd
je next
; transform [0-9A-Fa-f] to [\x00-\x0f]
cmp al,0x40
jle skipa
add al,0x9
skipa:
and al,0xf
; load font definition
cbw
add ax,cx
mov bx,letters
add bx,ax
mov ah,0xe
; print first char
mov al,[bx]
and al,0x4
jz s1
mov al,0x7c
jmp short w1
s1:
mov al,0x20
w1:
int 0x10
; print second char
mov al,[bx]
and al,0x2
jz s2
mov al,0x5f
jmp short w2
s2:
mov al,0x20
w2:
int 0x10
; print third char
mov al,[bx]
and al,0x1
jz s3
mov al,0x7c
jmp short w3
s3:
mov al,0x20
w3:
int 0x10
; next character
jmp short read
; print newline
next:
cmp cl,0x20
je end
mov al,0xd
int 0x10
mov al,0xa
int 0x10
add ebx,0x10
add cl,0x10
jmp short start
end:
ret
letters:
db 2,0,2,2,0,2,2,2,2,2,2,0,2,0,2,2
db 5,1,3,3,7,6,6,1,7,7,7,6,4,3,6,6
db 7,1,6,3,1,3,7,1,7,3,5,7,6,7,6,4
Man... can't beat the perl. Here's some py3k at 163 chars.
i=input()
[print(''.join(' | _ _|| | ||_ |_|'[(7&(d>>l))*3:][:3]for d
in[255&0xb4b61fa637bdbbbf89b7b3399b9e09af>>int(x,16)*8 for x in i]))for
l in[6,3,0]]
Explanation. First here's what it looked like completely unoptimized:
# segment positions, easily understandable as octal. first digit is top row
# last digit is bottom row. high bit is first column, low bit last.
a=[0o257, 0o011, 0o236, 0o233,
0o071, 0o263, 0o267, 0o211,
0o277, 0o273, 0o275, 0o067,
0o246, 0o037, 0o266, 0o264]
# and the corresponding segments:
# 421 421 421 421 421 421 421 421
b=[' ', ' |', ' _ ', ' _|', '| ', '| |', '|_ ', '|_|']
# function to look for the proper segment for a decoded digit:
def lookup(digit, line):
return b[ 7& (digit>>(6-line*3))]
#function to encode an ascii hex string into coded form suitible for
#above function
def code(i):
return [a[int(x,16)] for x in i]
def fmt(i):
return '\n'.join(''.join(lookup(d,l) for d in code(i)) for l in [0,1,2])
i = input()
print(fmt(i))
Then i go about finding ways to pack the data. First I can transform a
into a big, long integer, last element first, 8 bits at a time. That produces, in octal: 0o2645541764615736673577046675463463347404657
. written in hex, that's 0xb4b61fa637bdbbbf89b7b3399b9e09af
, 90 chars shorter than the list of octals. To use it you have to rewrite code, of course. That looks like
def code_a_8(i):
return [255&a_8>>int(x,16)*8 for x in i]
b
can be concatenated, ''.join(b)
is 26 chars, including the quotes. the lookup function must also change to support this.
def lookup_b_cat(d, l):
return b_cat[(7&(d>>6-l*3))*3:][:3]
Next I just eliminate all unneeded syntax by folding functions and constants into the expression, and that's pretty much it.
It's possible to tighten up the printing a bit, too. Instead of joining the lines, just print them immediately. this results in a modified fmt()
:
def fmt_print(i):
[print(''.join(lookup(d,l) for d in code(i))) for l in [0,1,2]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With