Archive for the ‘Pascal’ Category

AI datorarkeologi 2026

05/04/2026

I den föregående artikeln jämförde jag en CP/M baserad dator från tidsperioden 1975-85, dock emulerad, med dagens datorer. Min konklusion var att våra nuvarande datorer i alla relevanta avseenden är från tusen till några miljoner gånger kraftfullare än gårdagens CP/M maskin som trots dess begränsningar var ett fint hjälpmedel för många småföretag.

En CP/M maskinen erbjöd t.ex. en textbehandlare för brev vilket var himmelriket jämfört med att skriva ett helt brev felfritt på en mekanisk skrivmaskin. Mot slutet av CP/M epoken fanns det redan fullständigt användbara textbehandlare t.ex. Wordstar. CP/M maskinen erbjöd också program där mitt brev automatiskt kunde omformas för olika mottagare (mail merge) vilket igen sparade mycket tid igen i förhållande till manuellt arbete där varje brev, helst felfritt, skulle skrivas ut på skrivmaskin. Det fanns primitiva databaser och program för att hantera fakturering. Maskinen var primitiv men den var användbar.

Min jämförelse av CP/M maskinen och en modern PC gjordes på min bordsdator så att jag installerade emulatorn RunCPM under Linux. Då jag lekte med emulatorn märkte jag att det skulle ha varit trevligt att inifrån CP/M kunna skriva ut text på min skrivare samt naturligtvis också kunna lagra data på klassiskt sätt genom att stansa ut en hålremsa. En stansapparat är idag svår att komma över och de är förvånande dyra, vi talar ofta om kanske en tusenlapp. Om jag kan skapa hålremsan så behöver jag naturligtvis också ett program för att läsa av en hålremsa och återskapa data. Det kunde också vara trevligt att kunna lagra data och program på magnetband på ett möjligast tidstypiskt sätt. På samma sätt som för hålremsstansen så behöver jag naturligtvis också en läsare för magnetband.

Jag beslöt att lösa problemet med hjälp av några enkla program skrivna i programmeringsspråket Python. Dessa program körs under Linux parallellt med den emulerade CP/M maskinen. Notera att en modern PC har 4-8 processorkärnor, ibland mer, vilket betyder att den fullständigt problemfritt kan emulera min CP/M maskin utan att det märkbart påverkar Linuxens, d.v.s. PC:ns kapacitet.

Hålremsa

Det första steget för att ge min CP/M emulator tillgång till en hålremsstans och motsvarande läsare är att skriva två relativt enkla python program som tar en datafil d.v.s. en serie Bytes som i princip är godtyckliga tecken som passar in i en 8-bitars Byte. Totalt finns det max 256 tecken i en åtta bitars datastruktur.

Det slog mig att jag kunde använda detta projekt till att testa hur väl AI kunde hjälp mig med programmeringen och vilken form detta kunde ta. Min diskussion med AI är alltså den ”programmering” jag gjorde. Jag använde en gratisversion av chatGPT som medhjälpare. Texten nedan visar diskussionen med AI och resultatet. Efter varje programförslag korrigerade jag AI och bad om förbättringar. Jag använde engelska under diskussionen men jag gissar att det skulle ha fungerat lika bra på svenska.

Steg 1 jag beskriver grunddesignen för AI:

(Lars) I want to encode a string of 8 bit bytes into a png image as a column of bits. Every bit consists of 10×10 pixels. A high bit is white and a low bit is black. A maximum of 128 bytes are coded into a column. When a column is full a new column is generated to the right of the previous column. Columns are separated by a double bit wide grey separator line. The number of columns in the image is not restricted. The bytes to be encoded are read from a text file given on the command line. The resulting image file is called tape.png .

(ChatGPT) This is a neat “visual tape” encoding idea. The requirements are clear enough to implement directly. Below is a complete Python script using Pillow that does exactly what you described.

Resultatet var ett körbart pythonprogram som kodade data som strimmor vertikalt ner över skärmen. I princip användbart men motsvarar inte en gammal hålremsa. Det är lätt att be om en korrektion. Tanken är att generera en bild jag kan skriva ut på skrivare och om jag så vill läsa in med hjälp av skrivarens scanner för att sedan avkoda. Stansning/avkodning görs alltså modernt via en bild av typen png d.v.s. utan fysisk stansning. Resultatet kan dock skrivas ut och mappas in i en fysisk mapp om jag vill i likhet med forntidens hålremsa som förvarades i en ask.

(Lars) Generate columns of 128 bytes in a manner of a punched paper tape. When 128 bytes has filled a column new columns are generated to the right of the previous filled column.

(ChatGPT) What you’re describing is essentially a visual punched paper tape, where each column is like a vertical slice of tape holding 128 bytes (rows), and each byte is represented by 8 holes (bits).Let me tighten and clarify the structure and give you a clean implementation that matches that mental model exactly.

För att göra hålremsan lättare att läsa för en människa separerar jag varje kodad byte med en vit rad. Vi kunde klippa ut vertikala strimmor ur den utskrivna bilden och limma ihop dem till en hålremsa som vi kunde läsa av utan större problem på optisk väg. Någon hålstansning begövs inte för en modern läsare. En svart ruta med storleken 10×10 pixlar betyder att ifrågavarande bit=0 d.v.s. låg nivå. På motsvarande sätt betyder en vit ruta att platsen ”har stansats” d.v.s. bit=1 hög nivå. Svart/vit ruta förstås så att vi i en riktig pappersremsa har en lampa på baksidan av remsan som belyser sensorer som belyser sensorer på andra sidan. Ett stansat hål ses som ljust.

(Lars) Separate bytes with white line between rows of bits.

(ChatGPT) Got it — you want the tape to be more readable by clearly separating each byte (row) with a horizontal white line.

Slutresultatet blev ett kodningsprogram som jag kunde köra från kommandoraden under Linux:

python3 encoder3.py encoder3.py

Det första kommandot python3 anger att jag vill använda python3 som tolk, det finns flera generationer av python i bruk därav python3. Jag kan enkelt modifiera programmet så att det kan köras utan explicit python3. Jag ber programmet koda sig självt och resultatet blir en bildfil tape.png . Bildfilen har följande utseende:

Bilden innehåller alltså hela texten till programmet som kodar bilden. Hålremsan skall läsas uppifrån till vänster en kolumn i taget. Det finns inga inbyggda begränsningar för hur många kolumner det får finnas i bilden. Utskrivet på en A4 sida ryms ca. 3000 tecken d.v.s. ett typisk litet program skrivet t.ex. i Pascal eller C. Jag har inte editerat en enda rad i den genererade koden, allt är skapat av chatGPT enligt mina instruktioner.

Det genererade programmet har följande utseende utan en enda editering från min sida:

import sys
from PIL import Image

# Geometry
BIT_SIZE = 10
BITS_PER_BYTE = 8
BYTES_PER_COLUMN = 128
SEPARATOR_WIDTH_BITS = 2
ROW_SEPARATOR_BITS = 1 # NEW

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (128, 128, 128)


def byte_to_bits(byte):
return [(byte >> (7 - i)) & 1 for i in range(8)]


def main():
if len(sys.argv) < 2:
print("Usage: python tape.py input.bin")
return

with open(sys.argv[1], "rb") as f:
data = f.read()

# Split into columns
columns = [
data[i:i + BYTES_PER_COLUMN]
for i in range(0, len(data), BYTES_PER_COLUMN)
]

num_columns = len(columns)

# Height in bits (bytes + separators)
height_bits = (
BYTES_PER_COLUMN +
(BYTES_PER_COLUMN - 1) * ROW_SEPARATOR_BITS
)

# Width in bits
width_bits = (
num_columns * BITS_PER_BYTE +
(num_columns - 1) * SEPARATOR_WIDTH_BITS
)

# Convert to pixels
width_px = width_bits * BIT_SIZE
height_px = height_bits * BIT_SIZE

img = Image.new("RGB", (width_px, height_px), BLACK)
pixels = img.load()

current_x_bit = 0

for col_idx, column in enumerate(columns):
y_bit = 0

for row_idx, byte in enumerate(column):
bits = byte_to_bits(byte)

# Draw byte row
for bit_idx, bit in enumerate(bits):
color = WHITE if bit else BLACK

x_bit = current_x_bit + bit_idx

for dx in range(BIT_SIZE):
for dy in range(BIT_SIZE):
x = x_bit * BIT_SIZE + dx
y = y_bit * BIT_SIZE + dy
pixels[x, y] = color

y_bit += 1

# Draw horizontal separator (except after last byte)
if row_idx < len(column) - 1:
for x_bit in range(current_x_bit, current_x_bit + BITS_PER_BYTE):
for dx in range(BIT_SIZE):
for dy in range(BIT_SIZE):
x = x_bit * BIT_SIZE + dx
y = y_bit * BIT_SIZE + dy
pixels[x, y] = WHITE

y_bit += ROW_SEPARATOR_BITS

current_x_bit += BITS_PER_BYTE

# Draw vertical separator between columns
if col_idx < num_columns - 1:
for sep in range(SEPARATOR_WIDTH_BITS):
for yb in range(height_bits):
for dx in range(BIT_SIZE):
for dy in range(BIT_SIZE):
x = (current_x_bit + sep) * BIT_SIZE + dx
y = yb * BIT_SIZE + dy
pixels[x, y] = GRAY

current_x_bit += SEPARATOR_WIDTH_BITS

img.save("tape.png")
print("Saved tape.png")


if __name__ == "__main__":
main()

Följande steg är naturligtvis att låta chatGPT göra motsatsen d.v.s. skriva ett pythonprogram som läser en hålremsa lagrad som en bildfil och återskapar den kodade informationen.

(Lars) Now generate a decoder for the last version. It takes a png-file as input and produces a text file RDTAPE.txt containing the decoded bytes.

(ChatGPT) Great — now we’ll reverse the exact format you just defined.

This decoder will:

Read tape.png

Detect bits based on pixel blocks (10×10)

Skip:

horizontal white row separators

vertical gray column separators

Reconstruct bytes

Write them to RDTAPE.txt (binary-safe)

Resultatet blev ett fungerande avkodningsprogram som korrekt återskapade det kodade programmet i bildfilen tape.png.

import sys
from PIL import Image

# Geometry (must match encoder!)
BIT_SIZE = 10
BITS_PER_BYTE = 8
BYTES_PER_COLUMN = 128
ROW_SEPARATOR_BITS = 1
SEPARATOR_WIDTH_BITS = 2

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (128, 128, 128)


def is_white(pixel):
return pixel[0] > 200 and pixel[1] > 200 and pixel[2] > 200


def is_black(pixel):
return pixel[0] < 50 and pixel[1] < 50 and pixel[2] < 50


def is_gray(pixel):
return abs(pixel[0] - 128) < 40 and abs(pixel[1] - 128) < 40 and abs(pixel[2] - 128) < 40


def read_bit_block(pixels, x_bit, y_bit):
"""Sample center of a bit block"""
x = x_bit * BIT_SIZE + BIT_SIZE // 2
y = y_bit * BIT_SIZE + BIT_SIZE // 2
pixel = pixels[x, y]

if is_white(pixel):
return 1
else:
return 0


def is_separator_column(pixels, x_bit, height_bits):
"""Detect gray separator column"""
count_gray = 0
for yb in range(height_bits):
x = x_bit * BIT_SIZE + BIT_SIZE // 2
y = yb * BIT_SIZE + BIT_SIZE // 2
if is_gray(pixels[x, y]):
count_gray += 1

return count_gray > height_bits * 0.8


def main():
if len(sys.argv) < 2:
print("Usage: python decode.py tape.png")
return

img = Image.open(sys.argv[1])
pixels = img.load()

width_px, height_px = img.size

width_bits = width_px // BIT_SIZE
height_bits = height_px // BIT_SIZE

x_bit = 0
decoded_bytes = []

while x_bit < width_bits:
# Skip gray separator columns
if is_separator_column(pixels, x_bit, height_bits):
x_bit += 1
continue

# Read one data column (8 bits wide)
column_bytes = []

y_bit = 0
row_count = 0

while y_bit < height_bits and row_count < BYTES_PER_COLUMN:
bits = []

# Read 8 bits across
for bit_idx in range(BITS_PER_BYTE):
bits.append(read_bit_block(pixels, x_bit + bit_idx, y_bit))

# Convert to byte
value = 0
for b in bits:
value = (value << 1) | b

column_bytes.append(value)

row_count += 1
y_bit += 1

# Skip white separator row
if row_count < BYTES_PER_COLUMN:
y_bit += ROW_SEPARATOR_BITS

decoded_bytes.extend(column_bytes)

x_bit += BITS_PER_BYTE

# Write output
with open("RDTAPE.txt", "wb") as f:
f.write(bytes(decoded_bytes))

print("Decoded to RDTAPE.txt")


if __name__ == "__main__":
main()

Konklusion

Vi kan ser hur arbetsprocessen då jag använder AI för programmering förändras radikalt. Jag behöver inte längre i detalj kunna programmeringsaspråkets syntax och semantik. Jag försöker endast förklara för AI, så väl jag kan, exakt vad jag vill ha på en hög nivå i form av naturligt språk. Det är självklart att jag fortfarande måste känna problemkontexten. Jag måste ha en mental bild av hur data är kodat i Byte, Bit samt veta hur forntidens hålremsa i princip såg ut. Jag behöver däremot inte i detalj veta hur problemet skall splittras up i form av datastrukturer och funktioner för att skapa ett fungerande program, detta görs av AI.

Min uppfattning är att AI är ett verktyg som motsvarar övergången från handverktyg till långt automatiserade verkstäder. Det krävs mycket kunnande för att styra AI men kunskapen som behövs ligger på en betydligt högre abstraktionsnivå.

Jag kör den nya programkod AI ger vid varje iteration och försöker förklara för AI vad jag vill korrigera. Jag uppfattar arbetsprocessen som den jag körde med i forntiden då jag sålde egna industri mätsystem till kund. Det gällde då att själv vara i samma situation som chatGPT d.v.s. försöka förstå vad kunden egentligen försökte köpa. Då jag visste vad problemet var i detalj var inte implementationen något väldigt stort problem.

Fortsättning

Min tanke är att skapa automatik där jag använder Linux på huvuddatorn till att hantera utskrift till ”hålremsestansen”. På motsvarande sätt vill jag enkelt komma åt lagrade program och filer i mitt virtuella ”bibliotek” bestående av lagrade hålremsor. I forntiden skulle jag ha varit tvungen att gå till ett skåp och söka fram rätt hålremsa och hoppas att den var korrekt märkt, lägga in hålremsan i läsaren samt starta avläsningen. I mitt system bygger jag upp det så att jag kan be hålremsläsaren hämta rätt hålremsa och läsa av den. Mitt system motsvarar inte helt det som användes i forntiden men det är relativ nära. Jag behöver inte stiga upp ur stolen för att hämta rätt hålremsa. Jag har inte heller implementerat läsning via CP/M BIOS-anrop d.v.s. min arbetsprocess kommere att skilja sig från motsvarande process i forntiden.

Min plan är att förutom en stans för hålremsor också skapa ett enkelt sätt att inifrån CP/M skriva ut textfiler till Linux skrivare. Även här tänker jag fuska i viss mån dock så att systemet ungefär fungerar som i forntiden.

Om energi och intresse räcker till kan det hända att jag också skapar system för att lagra CP/M program och data till filer på magnetband. Jag använder i såfall linuxens ljudsystem för att skapa ljudfiler som kan läsas och återskapas till program eller data.

Mera om implementation och AI-hjälp i nästa artikel.

Datorarkeologi 2026

02/04/2026

Jag har lekt med en Clockwork PicoCalc som man kan köpa som en enkel byggsats. PicoCalc är egentligen ett tangentbord och en skärm med 320×320 pixlar d.v.s. en skärm som motsvarar en typisk hemdator från 1980-talets början t.ex. en Commodore 64. Byggsatsen görs till en fungerande dator genom att lägga till något av processorkorten Rasapberry Pi Pico, Pico2 eller Pico W. Hobbyister har också kört andra processorer och lyckats köra Linux utan större problem. Användning av andra processorer än Pico kräver dock i allmänhet att man hackar hårdvaran d.v.s. löder om själva PicoCalc. Jag tycker av princip illa om att gå in och löda i fungerande hårdvara vilket är orsaken till att jag kör en normal PicoCalc och inte Linux.

Bilden visar att Turbo pascal d.v.s. turbo har startat och programmet frågar efter den fil vi vill editera och kompilera. I vårt fall TEST.PAS. Vi ser en CP/M mikroskärm med radlängden 40 tecken. En speciell font har skapats för att få möjligast mycket text att rymmas på en rad.

PicoCalc ser ut som en normalstor kalkylator från 1980-talet i vilken man kan programmera och köra Basic, Python och Lua. Under Basic och Python fungerar den förvånande bra som en programmerbar kalkylator. Det visade sig snabbt att processorn är tillräckligt snabb och det finns tillräckligt minne för att köra operativsystemet CP/M som var dominerande från mitten av 1970-talet till mitten av 1980-talet. CP/M trängdes ut av IBM:s PC kring mitten av 1980-talet. IBM PC körde ett mycket liknande operativsystemsom CP/M kallat Ms-DOS.

https://en.wikipedia.org/wiki/IBM_Personal_Computer

https://en.wikipedia.org/wiki/CP/M

ARM processorn i en RPi Pico klarar av att emulera en Intel 8080 eller en Zilog Z80 i realtid. Pico:ns lilla minne räcker till för att ge CP/M ett fullt arbetsminne trots att en stor del av Pico kapaciteten går åt till att emulera en främmande processor.

Storleken på en Raspberry Pi Pico är ungefär två normalstora frimärken i bredd. Bildens Pico har storleken 20×50 mm.

Ett mycket vanligt programmeringsspråk på 1980-talet både under CP/M och PC-DOS var Turbo Pascal som erbjöd en enligt dåtida mått mycket trevlig programmeringsomgivning för programspråket Pascal. Pascal är ett i många avseenden mycket klarare och ”renare” programspråk än t.ex. programspråket C som användes då Unix och senare Linux skapades. Med hjälp av Turbo Pascal kunde man i akademiska sammanhang enkelt t.ex. göra statistiska analyser på en liten bordsmaskin, analyser som tidigare krävde tillgång till en stordator med all den byrokrati och kostnad detta medförde. Med hjälp av Turbo Pascal kunde man också med hjälp av diverse instickskort använda en PC för förvånande avancerade automatiska mätningar. Turbo Pascal fanns tillgängligt både för CP/M baserade datorer och för Ms-DOS maskiner d.v.s. IBM-PC samt mängder av liknande kloner.

Att köra program i 64 kilo Byte minne

Dagens datorer t.ex. en PC tenderar att ha ett centralminne på 4-32 GigaByte ibland mera. Min personliga PC som kör Linux har 32 GigaByte minne som är 500 000 gånger större än än det totala minnet i forntidens CP/M dator.

Jag kompilerade på skoj ett program TEST.PAS som ger ett nytt kommando till CP/M systemet som enligt Unix tradition kallas cat d.v.s. catenate eller skriv ut/kombinera ihop. Programmet kan läsa en eller flera textfiler och skriva ut dem till skärmen eller skicka resultatet till en annan fil. Under Linux skulle jag kunna skicka filen utan förändringar till t.ex. LPR dvs skriva ut till skrivare allt det som annars skulle gå till skärmen. Jag antar att jag inte kommer riktigt så enkelt undan under CP/M. Länken nedan diskuterar hur man kommer åt en skrivare, stans för hålremsa etc. under CP/M.

https://www.mark-ogden.uk/mirrors/www.cirsovius.de/CPM/Projekte/Artikel/Grundlagen/IOByte/IOByte-de.html

Då jag kompilerar programmet under Turbo Pascal under CP/M på PicoCalc får jag ett körbart program med storleken 635 bytes vilket motsvarar en vanlig text utskriven med 80 tecken par rad som då blir ungefär åtta rader lång. Jag testade programmet under CP/M så att jag använde det kompilerade programmet till att lista ut sig själv på PicoCalc skärmen. Texten är väldigt liten och ganska svårläst men programmet fungerade OK.

En intressant fråga blir då: Om jag tar samma program och kompilerar det under Linux (eller Windows eller Mac) hur stort blir då programmet på en modern dator? Notera att jag kompilerar för användning på kommandoraden helt utan GUI (grafiskt användargränssnitt). Om jag skulle skapa ett GUI för programmet gissar jag att det skulle växa ytterligare med kanske en faktor tio.

För kompileringen under Linux använde jag fpc d.v.s. Free Pascal Compiler som är basen i bl.a. Lazarus som idag är en trevlig omgivning för att generera program med grafiskt användargränssnitt GUI. Lazarus är mycket nära besläktad med Delphi (tidigare Borland Delphi). Lazarus är trevligt eftersom program enkelt kan skrivas för Linux, Windows, Mac, Android och FreeBSD och det finns funktionalitet som i hög grad förenklar designen av ett program med GUI. Fpc är således funktionsmässigt nära släkt med Borlands Pascal d.v.s. Turbo Pascal.

Jag kompilerade om programmet TEST.PAS under fpc med:

fpc -gl TEST.PAS

Kompileringen gick igenom utan problem men jag putsade bort en del onödiga fyllnadstecken i slutet av filen, tecken som i sig inte störde kompileringen. Då jag körde programmet:

./TEST TEST.PAS

Skrevs texten till TEST.PAS ut korrekt men jag fick ett felmeddelande på den nästsista raden (se programlistningen nedan) där programmet försöker stänga filen wrf d.v.s. en fil som används om man skulle vilja att resultatet går till en annan fil och inte på skärmen. Om jag skriver till skärmen behövs inte wrf och om jag försöker stänga wrf som aldrig har öppnats uppstår det ett fel. Felet är enkelt att åtgärda genom att kontrollera om vi har alternativet redirect innan vi försöker stänga filen. Längden på det körbara programmet blev nu under 64-bitars linux med kompilatorswitchen -gl som jag använde för att komma åt vilken rad i programmet som gav felet 420968 Byte d.v.s. ungefär 663 gånger större än under CP/M.

Om jag kompilerar om programmet efter rättning utan flaggan -gl blir resultatet 188304 Byte d.v.s. ungeför 297 ggr större än under CP/M.

Vad beror storleksskillnaderna på? En självklar orsak är naturligtvis att datorns s.k. ordlängd d.v.s. hur lång en typisk instruktion är har vuxit från 8-bitar till 64-bitar. Om vi antar att vårt program fortfarande behöver ungefär samma maskinspråksinstruktioner så kan vi få en vettigare jämförelse genom att dividera Linux-varianten med åtta d.v.s. ungefär 23538 instruktioner vilket är 37 ggr större än antalet instruktioner i CP/M varianten. Jag gissar att man genom väl genomtänkta optimeringar vid kompileringen kan krympa Linuxvarianten ytterligare. En stor orsak till att programmet har blivit större är antagligen kontroll av olika fel d.v.s. debuggning som utvecklats mycket under åren. De bibliotek vi länkar mot under Linux har bättre funktionalitet men de har också vuxit betydligt och innehåller sannolikt kod vi inte behöver. Vid kompileringen kan vi ange olika nivåer av optimering som påverkar snabbhet , minnesåtgång samt stöd för olika typer av felsökning. Körning av programmet ger:

./TEST TEST.PAS
ParamCnt=1/home/lasi/Prog/Pascal/TEST
Testing for file redirection
Got last par=TEST.PAS
TEST.PAS
program cat(input,output);
(* Make a new CP/M command cat
cat xxx yyy zzz … List all files to screen
cat xxx yyy >zzz List files xxx, yyy to the file zzz
*)
var i,nfiles:integer;
red:Boolean;
rdf: Text;
wrf: Text;
line: String[255];
destF: String[10];
function CkRedirect: boolean;
(* Is the destination a file or stdout?
The last file is assumed to be the redirection file if it exists.
Write all non redirection files to a temporary file and then
dump that to stdout or rename it to the destination file.
*)
var line:String[80];
begin
writeln('Testing for file redirection');
line := ParamStr(ParamCount);
writeln('Got last par=',line);
if (line[1] = '>') then
begin
writeln('Found redirect');
CkRedirect := True;
end;
end;
begin
writeln('ParamCnt=',ParamCount,ParamStr(0));
nfiles := ParamCount;
red := False;
if CkRedirect then
begin
writeln('Redirect');
nfiles := ParamCount - 1;
red := True;
destF := ParamStr(ParamCount);
Delete(destF,1,1); (* Remove '>') ) writeln('Redirect to:', destF); end; for i:=1 to nfiles do begin ( Type one file ) writeln(ParamStr(i)); Assign(rdf,ParamStr(i)); Reset(rdf); if red=True then begin Assign(wrf,destF); Rewrite(wrf); end; while not Eof(rdf) do begin Readln(rdf,line); if red=True then begin Write(wrf,line); end else Writeln(line); end; close(rdf); Writeln(' '); end; ( Caused error on the fpc compiler *)
if CkRedirect then close(wrf);
Writeln('Done …');
end.

Testing for file redirection
Got last par=TEST.PAS
Done …

Konklusion

Den här lilla programmeringsövningen visar egentligen hur ofattbart mycket tekniken har utvecklats under en livstid. Generellt kan man antagligen säga att alla intressanta parametrar har förbättrats med en faktor tusen eller mera. Några exempel:

  • Processons klockfrekvens 1 MHz –> 4 GHz (dagen datorer är ungefär 4000 ggr snabbare sett till processorns klockfrekvens.
  • Maskinens centralminne RAM 64 kByte –> 64 GByte (1 000 000 gånger större minne i dagens persondatorer av topp klass).
  • Skivminne/Lagringsminne 100 kByte –> 4 TByte (4 000 000 ggr större idag).
  • Maskinens pris $5000 –> $100 (50 ggr dyrare än idag). Notera att jämförelsen är felaktig eftersom penningvärdet har försämrats kraftigt på 40 år. Jag gissar att en korrekt jämförelse kunde vara åtminstone 100 ggr.

Om vi glömmer dagens AI boom där AI av vanliga användare körs över nätet och således inte belastrar den egna maskinen i någon större utsträckning så används datorerna fortfarande till liknande uppgifter som i ”forntiden” d.v.s. textbehandling, skicka brev och hantera kalkylark av olika typer. Gårdagens datorer kändes responsmässigt ungefär lika som dagens datorer. Vart har en prestandaökning på mellan 1000 och 1 000 000 ggr. försvunnit? Min uppfattning är att vi har fått en ofantlig mängd ”bling” som egentligen endast gör skärmen trevligare att titta på. Vi har halvtransparenta fönster som uppdateras hela tiden medan vi flyttar dem. En gammal dator skulle ha storknat genast. I våra datorer körs mängder av program i bakgrunden hela tiden. Program som meddelar oss att vi har fått meddelanden, program som skickar information om var vi gör till Microsoft etc. Det är lätt att bränna datorkapacitet och minneskapacitet i en värld där maskinen jag använder egentligen redan länge har varit tillräckligt kraftfull för det den skapades för.

Min laptop som också kör Linux fungerar helt OK trots att den är strax över tio år gammal. En bekant fick problem d.v.s. den heliga röken som datorn antagligen kör på slapp ut och maskinen slutade fungera. Jag hjälpte personen att rädda foton och dokument från datorn och fick sedan överta skrotet. Efter egen reparation har maskinen fungerat klanderfritt i många år. Jag kör en linuxvariant där allt onödigt ”bling” är bortplockat och maskinen fungerar bra som den är.

Ett annat intressant exempel på datorns ofantliga utveckling är ”mini”-datorn PDP-11 som operativsystemet Unix utvecklades på. Maskinen skulle ha kostat en privatperson tiotals tusen dollar att köpa. Jag har idag en replica av en PDP-11/70 d.v.s. den sista PDP:n som hade en frontpanel som tillåter mig att knappa in maskinkod bit för bit. Min replika kör, liksom CP/M på PicoCalc, en emulator men i detta fall på en Raspberry Pi 4. Den emulerade minidatorn från 1970-talet kör engefär tio gånger snabbare än orginalet trots att varje maskininstruktion emuleras av ett emulatorprogram på Raspberry Pi. En raspberry pi kostar idag beroende på variant kring 100 Euro.

Världens första egentliga superdator var Cray-1. Maskinen användes för mängder av vetenskapliga beräkningar. Man har uppskattat att en Raspberry Pi 5 (100 Euro), då man använder display hårdvaran (GPU) som en vektorprocessor är snabbare än en Cray-1 superdator. En Cray-1 behövde ungefär 115 kW eleffekt. En Raspberry Pi behöver ungefär 7W. Även på effektområdet ser vi alltså en förbättring på ungefär sextontusen gånger.

https://en.wikipedia.org/wiki/Cray-1

Musik med Corona, att ‘hacka’ GarageBand (del 1)

01/04/2020

Vårt spelmanslag ”Altra Volta” har inte spelat ihop på några veckor och något borde göras för att gruppen skall kunna fortsätta att spela utan risk för smitta.

Ett sätt att fortsätta med musikhobbyn är att t.ex. börja spela in vår repertoar men så att inspelningen görs stämma för stämma och instrument för instrument över nätet. Det är inte med dagens teknik möjligt att göra inspelning i en virtuell studio där de olika deltagarna sitter hemma och spelar ihop i realtid. Problemet är fördröjningarna i nätet. Man uppfattar inom telefoni att den maximala fördröjningen är ca. 400 ms vilket hörs som ett obehagligt ”eko” om man över telefon talar med en annan person i samma rum. Om man spelar i tempot 120 slag/minut så motsvarar en fördröjning på 400 ms nästan ett taktslags fördröjning vilket inte är acceptabelt. Min gissning är att fördröjningen borde fås ned till under 100 ms (1/10 s) för att fördröjningen inte skall störa i amatörsammanhang … yrkesmusiker störs antagligen av ännu mindre inexaktheter. Kanske jag med 5g teknik kan planera den virtuella studion i framtiden?

Inspelningsprogram

Det finns mängder av inspelningsprogram på olika plattformer.

Gratisprogrammet  Audacity fungerar rätt bra under Windows, Linux och på Mac … problemet är att det verkar finnas vissa fel då man skall lägga till externa spår till ett lokalt inspelat spår, fel som gör att programmet i vissa fall vägrar köra.

På Windows finns t.ex. programmet Cubase men jag har ingen praktisk erfarenhet av detta program.

Vill man betala för ett inspelningsprogram så finns t.ex. ProTools för både Windows och Mac men inte för Linux. ProTools verkar dock relativt komplicerat utgående från erfarenheterna med att hjälpa en vän som har gått över från Windows till Mac och ProTools. Väldigt jobbigt med ett kopieringsskyddat program som dessutom inte är helt billigt.

På en Mac finns programmet GarageBand som, trots vissa buggar, verkar fungera rätt pålitligt och samtidigt innehåller en rätt stor mängd effekter som dock främst verkar vara gjorda för popmusik och inte den typ av folkmusik vi spelar. Garageband verkade dock så intressant att jag köpte mig en 21,5 tums iMac från 2009 för 50 Euro (500 SEK). Efter byte av den mekaniska hårdskivan till SSD och uppgradering av minnet till 12 GByte (billigt) så fungerar maskinen utmärkt och är trevlig att jobba med. Ljudkortet jag använder och som fungerar väl både under Linux och i Macen är Behringers Uphoria UMC404HD. Jag kan spela in elektroniska (simulerade) instrument m,ed hjälp av ett elektroniskt keyboard av typen M-Audio KeyRig 25.

För att skriva noter använder jag programmet MuseScore som finns för Windows, Mac och Linux.

Användning av GarageBand

Jag har spelat in några stycken på GarageBand flerstämmigt. Inspelningen går till så att jag skapar ett akustiskt spår (track) på vilket jag spelar in t.ex. melodin med användning av metronom (som finns i programmet). Jag kan efter detta lyssna på det inspelade bandet och spela in en stämma i taget eventuellt på olika instrument. För denna typ av extremt enkel inspelning fungerar programmet utmärkt.Jag kan också spela in piano eller en rätt stor grupp MIDI-instrument med hjälp av keyboardet.

Om jag vill lägga till t.ex. kompslingor med gitarr eller bas så visar det sig att det finns väldigt lite slingor som inte är överdrivet ”pop”-iga. Ett intressant alternativ vore att helt enkelt modifiera någon eller några existerande slingor som passar bättre till nordisk folkmusik. Det går att skapa egna slingor i GarageBand men verktygen kunde vara bättre och det är relativt besvärligt att modifiera existerande slingor. Ett alternativ vore att modifiera MIDI-spår med något lämpligt program utanför GarageBand och därefter läsa in den modifierade musiken  tillbaka i GarageBand.

GarageBand problem

GarageBand tillåter inte export av MIDI men nog att MIDI läses in utifrån. Jag kan alltså inte läsa in t.ex. en GarageBand slinga i MuseScore, transponera, ändra tempo eller taktart etc. Hur skall det problemet lösas?

Det visar sig att GarageBand sparar sina slingor i filer av typen .aif . Dessa filer är binära d.v.s. det är inte möjligt att studera dem i en texteditor däremot kan man titta på dem i en såkallad HexEditor d.v.s. ett program som visar innehållet som Hexadecimal nummerkod parallellt med att tecken som är skrivbara visas i ett eget fält. Med hjälp av en HexEditor kan man se att en .aif sling från Garageband innehåller en komplett MIDI-fil sannolikt tillsammans med ljuddata för det instrument som slingan spelar.

Lite sökande på nätet visade att en MIDI-fil alltid startar med rubriken ‘MHdr’ (MidiHeader). Filslutet utmärks med ‘CHS’ samt ytterligare de hexadecimala tecknen ’00’, ‘FF’, ‘2F’ och ’00’. På nätet hittar man instruktioner för hur man t.ex. med en hexeditor kan plocka ut MIDI ur en fil geno att söka efter ‘MHdr’ och ‘CHS’. Försöker man läsa in en fil baserat på detta i GarageBand så låser sig systemet eftersom slutkoden saknas.

En midifiles upphyggnad finns beskriven här i detalj.

Problemet med modifiering av slingar löses alltså genom att skriva ett program i Pascal. Systemet inklusive ett grafiskt gränssnitt heter ‘Lazarus’. Programmeringen görs som man under antiken d.v.s. på 1990-talet skrev t.ex. i Visual Basic. Programmets användargränssnitt ritas i ewn grafisk editor som automatiskt genererar tom kod för de skapade elementen. Programmerarens uppgift blir då att lägga till kod i de olika komponenterna så att programmet får önskad funktion. Liksom alltid då man börjar skriva i ett nytt och okänt språk så är problemet att omgivningen och alla verktyg är okända. Jag börjar med att skriva ett program med ett enda fönster och t.ex. en enda tryckknapp.

Arbetsprocessen med det nya programmety blir då ungefär följande:

Alternativ 1

  • Skriv melodislingor på MuseScore och exportera dem till GarageBand

Inget konversionsprogram behövs i detta fall.

Alternativ 2

  • Sök upp en intressant slinga i Garageband
  • Läs in slingan i MuseScore efter konvertering i GbConverter
  • Modifiera slingan i MuseScore
  • Importera den modifierade slingan som MIDI till GarageBand

För att arbetet skall göras bekvämt så körs tre program parallellt d.v.s. GarageBand, MuseScore och GbConverter. Eventuellt kan man säga att fyra program används eftersom importering av en MIDI-fil till GarageBand görs så att man från filhanteraren drar midifilen till önskat spår i GarageBand.

En liten introduktion till GarageBand från nätet:

(Fortsättning: Programmet GbConverter skrivet i omgivningen Lazarus i Pascal).


Pointman's

A lagrange point in life

THE HOCKEY SCHTICK

Lars Silén: Reflex och Spegling

NoTricksZone

Lars Silén: Reflex och Spegling

Big Picture News, Informed Analysis

Canadian journalist Donna Laframboise. Former National Post & Toronto Star columnist, past vice president of the Canadian Civil Liberties Association.

JoNova

Lars Silén: Reflex och Spegling

Climate Audit

by Steve McIntyre

Musings from the Chiefio

Techno bits and mind pleasers

Bishop Hill

Lars Silén: Reflex och Spegling

Watts Up With That?

The world's most viewed site on global warming and climate change

TED Blog

The TED Blog shares news about TED Talks and TED Conferences.

Larsil2009's Blog

Lars Silén: Reflex och Spegling