OprogramowanieImplikacje w budowy sprzętowej w programie generującym zawartość pamięci EPROM muszą ujmować wszystkie aspekty rozwiązania sprzętowego. Do pamięci EPROM dochodzi (ilustracja 1):
btr4_ilu01.PNG
Czyli dla kombinacji adresowej:
A15 … A0
0100000000000000 – w pamięci ma być zapisana taka kombinacja zer i jedynek, która na wyświetlaczu utworzy oczekiwaną cyfrę, w tym przypadku jest to
010 – szyna danych 8-bitowa,
000 – stan automatu 0 odpowiadający wyświetleniu cyfry skrajnie lewej,
00 – wyświetlenie w reprezentacji binarnej,
00000000 – przetwarzana liczba ma wartość 0 i na wyświetlaczu ma być zobrazowany znak '0', czyli włączony segment A, B, C, D, E, F.
Zadaniem PASCAL'owego programu jest umieszczenie w odpowiednich komórkach pamięci (reprezentowanej przez szynę adresową EPROM) takich danych, by składały się na właściwe cyfry na wyświetlaczu. Wyjścia pamięci EPROM mają następujące znaczenie:
btr4_ilu02.PNG
- Bit D0 steruje segmentem A
- Bit D1 steruje segmentem B
- Bit D2 steruje segmentem C
- Bit D3 steruje segmentem D
- Bit D4 steruje segmentem E
- Bit D5 steruje segmentem F
- Bit D6 steruje segmentem G
- Bit D7 steruje segmentem K
Dokładniejsze przyjrzenie się dla toru sterowania segmentami pokazuje, że dany segment świeci w sytuacji, gdy na wyjściu pamięci EPROM jest stan logicznej jedynki. No więc implikuje to następujący fragment programu (znak $ w turbopascalu oznacza zapis szesnastkowy):
Kod: Zaznacz cały
SegmentA = $01 ;
SegmentB = $02 ;
SegmentC = $04 ;
SegmentD = $08 ;
SegmentE = $10 ;
SegmentF = $20 ;
SegmentG = $40 ;
SegmentK = $80 ;
To z kolei implikuje, że dane zapisane w EPROM reprezentujące poszczególne cyfry mają mieć następujące wartości:
Kod: Zaznacz cały
SpaceDisplayEquivalent = $00 ;
MinusDisplayEquivalent = SegmentG ;
Digit0DisplayEquivalent = SegmentA + SegmentB + SegmentC + SegmentD + SegmentE + SegmentF ;
Digit1DisplayEquivalent = SegmentB + SegmentC ;
Digit2DisplayEquivalent = SegmentA + SegmentB + SegmentD + SegmentE + SegmentG ;
Digit3DisplayEquivalent = SegmentA + SegmentB + SegmentC + SegmentD + SegmentG ;
Digit4DisplayEquivalent = SegmentB + SegmentC + SegmentF + SegmentG ;
Digit5DisplayEquivalent = SegmentA + SegmentC + SegmentD + SegmentF + SegmentG ;
Digit6DisplayEquivalent = SegmentA + SegmentC + SegmentD + SegmentE + SegmentF + SegmentG ;
Digit7DisplayEquivalent = SegmentA + SegmentB + SegmentC ;
Digit8DisplayEquivalent = SegmentA + SegmentB + SegmentC + SegmentD + SegmentE + SegmentF + SegmentG ;
Digit9DisplayEquivalent = SegmentA + SegmentB + SegmentC + SegmentD + SegmentF + SegmentG ;
DigitADisplayEquivalent = SegmentA + SegmentB + SegmentC + SegmentE + SegmentF + SegmentG ;
DigitBDisplayEquivalent = SegmentC + SegmentD + SegmentE + SegmentF + SegmentG ;
DigitCDisplayEquivalent = SegmentA + SegmentD + SegmentE + SegmentF ;
DigitDDisplayEquivalent = SegmentB + SegmentC + SegmentD + SegmentE + SegmentG ;
DigitEDisplayEquivalent = SegmentA + SegmentD + SegmentE + SegmentF + SegmentG ;
DigitFDisplayEquivalent = SegmentA + SegmentE + SegmentF + SegmentG ;
ErrorDisplayEquivalent = SegmentD ;
Do wyświetlania są używane następujące znaki: spacja → żaden segment nie włączony → 0; '-' → włączony segment G; poszczególne cyfry dziesiętne i szesnastkowe. Jak zachodzi konieczność „zmiany fontu”, to należy zmodyfikować powyższe stałe.
Z analizy fragmentu dotyczącego formatu wyświetlania (ilustracja 3) i treści zawartej na nalepce na frontpanelu (ilustracja 4) wynika, że:
btr4_ilu03.PNG
btr4_ilu04.PNG
Kod: Zaznacz cały
BinFormat = $000 ;
HexFormat = $100 ;
DecFormat = $200 ;
U2Format = $300 ;
Kolejne implikacje sprzętowe mające znaczenie w programie generującym zawartość EPROM, to określenie szerokości szyny danych (ilustracja 5) w korelacji z nalepką (ilustracja 4), to:
btr4_ilu05.PNG
Kod: Zaznacz cały
BusWidth_3bit = $E000 ;
BusWidth_4bit = $6000 ;
BusWidth_5bit = $A000 ;
BusWidth_6bit = $2000 ;
BusWidth_7bit = $C000 ;
BusWidth_8bit = $4000 ;
Kolejne hardware'owe istotne informacje, to identyfikacja poszczególnych wyświetlanych cyfr. Z ilustracji 6 i ilustracji 7 wynika powiązanie cyfr z jej numerem.
btr4_ilu06.PNG
btr4_ilu07.PNG
Skrajnie lewa cyfra na wyświetlaczu jest identyfikowana przez '000' dla układu HC138.
Rozpatrując kolejny fragment (ilustracja 8), zostaje ustalona kolejność wybierania cyfr.
btr4_ilu08.PNG
Jak widać, nie jest to naturalne przyporządkowanie. W sumie nie ma to żadnego istotnego znaczenia. Takie rozwiązanie wynikało w optymalizacji ścieżek na PCB, bo w sensie obsługi wyświetlania nie ma żadnego istotnego znaczenia. By były wybierane na fizycznym wyświetlaczu kolejne cyfry, to układ HC138 musi dostać określone wartości kodu sterującego wejściami A, B i C (pin 1, 2 i 3). Cyfry na display'u są wybierane w następującej kolejności: D0 → D4 → D2 → D6 → D1 → D5 → D3 → D7. Wpływa to na wartości stałych:
Kod: Zaznacz cały
Digit0Offset = $0000 ;
Digit1Offset = $1000 ;
Digit2Offset = $0800 ;
Digit3Offset = $1800 ;
Digit4Offset = $0400 ;
Digit5Offset = $1400 ;
Digit6Offset = $0C00 ;
Digit7Offset = $1C00 ;
Teraz rozpatrzmy generowanie danych do pamięci EPROM:
Kod: Zaznacz cały
procedure CreateEPROMData ;
var
BusData : byte ;
DisplayData : string [ 8 ] ;
begin (* CreateEPROMData *)
CurrentBusWidth := BusWidth_8bit ;
for BusData := 0 to 255 do
begin
DisplayData := _8BinaryConversion ( BusData ) ;
AddToEPROM ( DisplayData , BusData , BinFormat ) ;
DisplayData := _8HexConversion ( BusData ) ;
AddToEPROM ( DisplayData , BusData , HexFormat ) ;
DisplayData := _8DecConversion ( BusData ) ;
AddToEPROM ( DisplayData , BusData , DecFormat ) ;
DisplayData := _8U2Conversion ( BusData ) ;
AddToEPROM ( DisplayData , BusData , U2Format ) ;
end (* for *) ;
(…)
end (* CreateEPROMData *) ;
Jest założona pętla na wszystkie kombinacje szyny danych. Realizowana jest konwersja liczba z postaci binarnej na postać znakową (do DisplayData, do napisu o 8 znakach) w zapisie dwójkowym, szesnastkowym, dziesiętnym i dziesiętnym ze znakiem (U2). W każdym przypadku pakowana jest to pamięci EPROM postać po konwersji na znaki. W przypadku konwersji dwójkowej:
Kod: Zaznacz cały
function BinaryDigit ( Data : byte ) : char ;
begin (* BinaryDigit *)
if Data <> 0 then
BinaryDigit := '1'
else
BinaryDigit := '0' ;
end (* BinaryDigit *) ;
function _8BinaryConversion ( BusData : byte ) : string ;
var
CnvString : string [ 8 ] ;
begin (* _8BinaryConversion *)
CnvString := '' ;
CnvString := CnvString + BinaryDigit ( BusData and $80 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $40 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $20 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $10 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $08 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $04 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $02 ) ;
CnvString := CnvString + BinaryDigit ( BusData and $01 ) ;
_8BinaryConversion := CnvString ;
end (* _8BinaryConversion *) ;
„Produkowany” jest łańcuch znaków w taki sposób, że najbardziej znacząca (do wyświetlenia) cyfra jest na mniejszym indeksie w tablicy.
Kod: Zaznacz cały
procedure AddToEPROM ( Data : string ;
Addr : word ;
FormatOffset : word ) ;
var
EPROMAddress : longint ;
begin (* AddToEPROM *)
EPROMAddress := Addr + FormatOffset + CurrentBusWidth ;
PutEPROMByte ( EPROMAddress + Digit0Offset , EncodeTo7Seg ( Data [ 1 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit1Offset , EncodeTo7Seg ( Data [ 2 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit2Offset , EncodeTo7Seg ( Data [ 3 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit3Offset , EncodeTo7Seg ( Data [ 4 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit4Offset , EncodeTo7Seg ( Data [ 5 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit5Offset , EncodeTo7Seg ( Data [ 6 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit6Offset , EncodeTo7Seg ( Data [ 7 ] ) ) ;
PutEPROMByte ( EPROMAddress + Digit7Offset , EncodeTo7Seg ( Data [ 8 ] ) ) ;
end (* AddToEPROM *) ;
I jest:
Addr – reprezentuje przetwarzaną liczbę → stanowi 8 najmłodszych bitów szyny adresowej EPROM,
FormatOffset stanowi przesunięcie w przestrzeni adresowej dla liczb wyświetlanych jako dwójkowe, hex, dec czy U2, dodane informacje określające szerokość szyny danych
CurrentBusWidth. Suma arytmetyczna, ale stałe mają tak dobrane wartości, że złoży się to sumę logiczną (złożenie poszczególnych szczegółów na wynikową szynę adresową do EPROM). I zadany napis
Data jest rozłożony po znaku do pamięci EPROM z uwzględnieniem przesunięć wynikających z działania układu HC138. Napis
Data zawiera znaki ASCII, do EPROM potrzebne są kody sterujące wyświetlaczem 7-segmentowym. Następuje konwersja, rozwiązanie najprostsze z możliwych:
Kod: Zaznacz cały
function EncodeTo7Seg ( Data : char ) : byte ;
begin (* EncodeTo7Seg *)
case Data of
' ' : EncodeTo7Seg := SpaceDisplayEquivalent ;
'-' : EncodeTo7Seg := MinusDisplayEquivalent ;
'0' : EncodeTo7Seg := Digit0DisplayEquivalent ;
'1' : EncodeTo7Seg := Digit1DisplayEquivalent ;
'2' : EncodeTo7Seg := Digit2DisplayEquivalent ;
'3' : EncodeTo7Seg := Digit3DisplayEquivalent ;
'4' : EncodeTo7Seg := Digit4DisplayEquivalent ;
'5' : EncodeTo7Seg := Digit5DisplayEquivalent ;
'6' : EncodeTo7Seg := Digit6DisplayEquivalent ;
'7' : EncodeTo7Seg := Digit7DisplayEquivalent ;
'8' : EncodeTo7Seg := Digit8DisplayEquivalent ;
'9' : EncodeTo7Seg := Digit9DisplayEquivalent ;
'A' : EncodeTo7Seg := DigitADisplayEquivalent ;
'B' : EncodeTo7Seg := DigitBDisplayEquivalent ;
'C' : EncodeTo7Seg := DigitCDisplayEquivalent ;
'D' : EncodeTo7Seg := DigitDDisplayEquivalent ;
'E' : EncodeTo7Seg := DigitEDisplayEquivalent ;
'F' : EncodeTo7Seg := DigitFDisplayEquivalent ;
else
EncodeTo7Seg := ErrorDisplayEquivalent ;
end (* case *) ;
end (* EncodeTo7Seg *) ;
I tak dla wszystkich kombinacji. Pewnego wyjaśnienia może wymagać format U2.
Najstarszy bit szyny danych (bit 8 dla szyny 8-bitowej; bit 7 dla szyny 7-bitowej, … bit 3 dla szyny 3-bitowej) jest bitem znaku: 0 → liczba jest dodatnia; 1 → liczba jest ujemna. By PC-et poprawnie przetworzył liczbę, to należy ją trochę „podrasować”. Pamiętając, że PC będzie przetwarzał liczbę 8-bitową, to konieczne jest pewne „podrasowanie”. Dla liczb dodatnich liczby krótsze niż 8-bitowe są uzupełniane zerem. Dla liczb ujemnych należy uzupełnić jedynką. Przykładowo w przypadku konwersji 5-bitowej
if ( BusData and $10 ) <> 0 then wycina najbardziej znaczący bit szyny danych. Jeżeli jest on 0, to wszystkie uzupełnienia do 8 bitów wymagają zera. Jeżeli jest 1, należy uzupełnić jedynkami. Identycznie istotny bit należy powielić na pozostałe (
integer w turbopascal ma 16-bitów).
Kod: Zaznacz cały
function _5U2Conversion ( BusData : byte ) : string ;
var
CnvString : string [ 8 ] ;
Number : array [ 0 .. 7 ] of char ;
Loop : word ;
U2Byte : integer ;
Minus : boolean ;
begin (* _5U2Conversion *)
if ( BusData and $10 ) <> 0 then
BusData := BusData or $E0
else
BusData := BusData and $1F ;
U2Byte := BusData ;
if ( BusData and $80 ) <> 0 then
U2Byte := U2Byte or $FF00 ;
Minus := false ;
if U2Byte < 0 then
begin
Minus := true ;
U2Byte := - U2Byte ;
end (* if *) ;
for Loop := 0 to 7 do
Number [ Loop ] := ' ' ;
Loop := 0 ;
repeat
Number [ Loop ] := HexChar ( U2Byte mod 10 ) ;
U2Byte := U2Byte div 10 ;
Loop := Loop + 1 ;
until U2Byte = 0 ;
if Minus then
begin
if Number [ 1 ] = ' ' then
begin
Number [ 1 ] := '-'
end (* if ... *)
else
begin
if Number [ 2 ] = ' ' then
begin
Number [ 2 ] := '-'
end (* if ... *)
else
begin
if Number [ 3 ] = ' ' then
begin
Number [ 3 ] := '-'
end (* if ... *)
else
begin
if Number [ 4 ] = ' ' then
begin
Number [ 4 ] := '-'
end (* if ... *)
else
begin
Number [ 7 ] := '-'
end (* if ... else *) ;
end (* if ... else *) ;
end (* if ... else *) ;
end (* if ... else *) ;
end (* if *) ;
CnvString := Number [ 7 ] ;
CnvString := CnvString + Number [ 6 ] ;
CnvString := CnvString + Number [ 5 ] ;
CnvString := CnvString + Number [ 4 ] ;
CnvString := CnvString + Number [ 3 ] ;
CnvString := CnvString + Number [ 2 ] ;
CnvString := CnvString + Number [ 1 ] ;
CnvString := CnvString + Number [ 0 ] ;
_5U2Conversion := CnvString ;
end (* _5U2Conversion *) ;
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.