Monday 23 May 2016

Timers and Interrupts

In the future my posts will be roughly divided into two categories. The first one will be more technical containing the posts where I go through how to do this and program that in a detailed manner. The second one contains all the rest that doesn't make the brain (whether yours or mine) wanting to escape through the ear. The post you're reading right now belongs (unfortunately) to the first category.

Interrupts and timers are important topics what comes to programming of microcontrollers. An interrupt is a signal to the microcontroller that makes it put on hold whatever it is doing at the moment and do something else instead. After the interrupt is handled, the controller continues where it left off. Interrupts can be internal (e.g. a timer reaching a specific value) or external (e.g. a button connected to a pin is pressed).

Timers are simply counters that are synchronized with a clock signal. The clock can be the same that controls the CPU or it can be separate. For example, if I'd like to keep track on seconds, I can just wire an old digital watch to the chip instead of building a circuit of my own.

In ATtiny25/45/85, there are two innovatively named 8-bit timers/counters: Timer/Counter0 and Timer/Counter1. Both can be set to count clock pulses increasing their value from 0 to 255. When 255 is reached, the next pulse causes an overflow and the counting starts from the beginning. A prescaler can be assigned to the clock signal that lowers its frequency dividing it by a factor of 8, 64, 256, or 1024.

The timers can be set to cause interrupts. There are two types of interrupts: timer/counter overflow and compare match. The first one is caused when the timer value jumps from 255 to 0 and the second one when the timer value matches with the one in so called Output Compare Register. There are two Output Compare Registers, A and B, for both timer/counters.


For an example, let's rewrite the blinking LED code using a timer and interrupts. Let's say I want to toggle on-off state of the LED every 250 ms using the timer/counter overflow interrupt. If the clock frequency is 1 Mhz and I set the timer prescaler to 64, the timer ticks every 64/1000000 second or 0.064 milliseconds.  Thus an 8-bit counter overflows every 0.064*256 = 16.384 milliseconds.

For 250 ms I need thus 250/16.384 = 15.258... overflows, so I can't time exactly 250 ms with this approach. There are couple of ways to go around this limitation but I think simply rounding this down to 15 overflows (245.76 ms) is sufficient for my purpose. 250 ms was arbitrarily chosen anyway. I'll return to the other ways in another post.

Once again we start with begin the programming with preprocessing lines:

 #define F_CPU 1000000UL  
 #include <avr/interrupt.h>  
 #include <avr/io.h>  

The first line sets the clock frequency to 1 Mhz and the rest import the necessary declarations and functions for interrupts and pin I/O. Next we need a variable to store the number of overflows:

 volatile uint8_t ovf_count = 0;   

Note the use of the keyword volatile. It tells to the compiler that the value of ovf_count can change 'due to external factors' and thus has to be load every time even if the main program hasn't changed it. In this case the 'external factor' means interrupts, as they stop the execution of the main program while doing their own thing. (I don't use ovf_count outside the interrupt function so I could skip the use of volatile here but I wanted to brought it up, as it is certain to fuck up the code if omitted where needed.) 

Before getting to the main function, we define our Interrupt Service Routine (ISR) that is executed when the interrupt is fired. From the AVR libc reference we see that the so called vector corresponding to the timer0 overflow interrupt is TIM0_OVF_vect. Thus the ISR corresponding this interrupt is:

 ISR(TIM0_OVF_vect){  
   if (ovf_count < 15){  
     //increase the counter by 1  
     ovf_count++;   
   }  
   else {  
     //reset the counter and toggle pin PB0  
     ovf_count = 0;  
     PORTB ^= 1;  
   }  
 }  

Nothing complicated here. The if clause counts the number of overflows and when it reaches 15, it resets the counter and toggles the output of the LED pin. ^= is bitwise XOR that takes the bits of PORTB defined on the right hand side and flips them. The right hand side value 1 = 0b0001 picks the PB0 pin.

The main program looks like this:

 void main(){  
   
   //Init counter  
   TCNT0 = 0;  
     
   //set the clock, prescaler 64  
   TCCR0B |= (1 << CS01) | (1 << CS00);  
   
   //enable overflow interrupt  
   TIMSK |= 1 << TOIE0;  
   
   //Global interrupt enable  
   sei();  
   
   //Set PB0 as output  
   DDRB = 1;  
   
   //Enter the endless loop  
   while(1);  
   
 }  

So, mainly a bunch of acronyms picked up from the datasheet. TCNT0 (Timer/Counter Register) is the counter itself that is initialized to 0 in the beginning.

TCCR0B (Timer/Counter Control Register B) has two bits (0 and 1) that has to be set one to select prescaling factor of 64. I could do it like this:

 TCCR0B |= 0b00000011;  

Bitwise OR |= sets the last two bits 1 but leaves all the rest as they are. However, it is customary to use names of the bits (CS01 and CS00, from the datasheet) and use the bitshift operator << that moves 1 (or 0b00000001) as many bits to the left as CS01 and CS00 say. In this case 1 << CS01 = 0b10 and 1 << CS00 = 0b01. These are combined with bitwise OR so that  0b10 |  0b01 =  0b11. It might need a little practice to get used to this kind of notation (at least for me it did) but it makes the code easier to read.

TIMSK (Timer/Counter Interrupt Mask Register) is used to set which interrupts are active. In this case we are interested only in Timer0 overflow so we set the TOIE0 bit (Timer/Counter Overflow Interrupt Enable).

Thus Timer/Counter0 is all set. All we need now is to enable the interrupts globally with sei() (to disable use cli() ) and set the PB0 pin as output. After that the program enters to an endless loop that is paused only to handle the timer0 overflow interrupts. And tadah, The blinking LED v2 is finished!

But enough with the LEDs. Next time we'll do something that is actually useful. We are going to grow some flowers learn how to use buttons to control the microcontroller.

References:

http://www.atmel.com/images/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf

Thursday 19 May 2016

Microcontrollers part IV: The First Taste of Programming

As far as I know, there are two programming languages to program AVR: assembly and C. Assembly is a very low-level language that gets you as close to the machine level as possible. It allows to use the computing resources as efficiently as it can get but takes an ass-load more work to write and debug.

Even very simple operations like summing up three numbers from the memory can take like five lines of code to perform in assembly whereas in C one line does the job. Also C is somewhat tedious in modern standards but certainly less than assembly, making it my choice for microcontroller programming.

Finally, it's time to get cooking! Let's start with something simple: a blinking LED. What follows is a compilation from the AVR Libc Reference Manual, the ATtiny85 datasheet and my previous knowledge on the AVR programming (which is not very deep).

Let's use the pin PB0 to control the LED (see the ATtiny85 pinout here). Usually one should use a resistor to limit the amount of current passing through the LED. However, since I don't have any right now the I/O pin can output max. 40 mA of current, I can connect it directly between the PB0 and GND pins. (Note that this shortens the lifespan of both the LED and chip, though.)

Next we need the program. As usual, I open my text editor and start off by writing down definitions and includes:

 #define F_CPU 1000000UL  
 #include "avr/io.h"  
 #include "util/delay.h"  

The first line defines the clock frequency which I chose to be 1 MHz. The header file "avr/io.h" contains the definitions for I/O operations and "util/delay.h" contains the function declaration for _delay_ms() that I'll use to slow down the blinking. The rest of the program is written in the main function which is very short:

 void main(){ 
 
   DDRB = 0b0001; 
 
   while (1){  
     PORTB = 0b0001;  
     _delay_ms(250);  

     PORTB = 0b0000;  
     _delay_ms(250);  
   }  
 }  

This is the actual program that the chip starts to executed immediately after the power is connected. The first line sets the direction of the I/O pins through DDRB (Data Direction Register B). This is done by a binary number 0b0001. The prefix 0b stands for the binary number and the bits after that correspond to the pins PB3, PB2, PB1 and PB0. Since we want PB0 to be an output we set that to 1. All the other bits can be whatever, in this case 0:s or inputs.

After setting data directions, the program enters into an eternal loop that blinks the LED. The first line in the loop sets the LED on through PORTB. Here the pin-bit correspondence is the same as in the former case but the action depends how the pins are configured. If the pin set as an output, then 1 bit sets the output to HIGH and 0 to LOW. On the other hand, if the pin is configured to an input, then setting the bit controls whether the pull-up resistor is on or not. I'll talk more about this later.

After setting PORTB, the program waits for 250 milliseconds. After that it sets PORTB again but now putting the last bit to 0 i.e. PB0 to LOW state turning off the LED. The program again waits for 250 ms and then moves in the beginning of the while loop. The loop is repeated until the power source is detached from the microcontroller.

The finished program needs to be compiled and written to the chip. I saved my file as main.c and typed the following lines into the terminal:

avr-gcc -mmcu=attiny85 -Os -c main.c  
avr-gcc -mmcu=attiny85 -o main.elf main.o  
avr-objcopy -j .text -j .data -O ihex main.elf main.hex  

The first line compiles main.c, the second one links it to the libraries, and the last one produces an Intel hex file that can be uploaded to the microcontroller. Once again, if the model of the chip is different, the first two lines have to be changed accordingly.

The last step is to write the program to the chip. Plug the following into the terminal:

 sudo avrdude -p attiny85 -C ~/avrdude_gpio.conf -c pi_1 -e -U flash:w:main.hex  

If the connections and the alignment of the celestial bodies are as they should, the microcontroller should now be programmed! And here's what the result looks like:


Works like a charm! Even though I forgot to connect the operating voltage to the RESET pin.. Apparently the circuit works without it for the demo purpose but it is very unstable. Now just touching the pin with a finger causes the chip to reset which surely is unwanted behavior. Always remember to wire the RESET pin as well!

--

This concludes the Microcontrollers series that I intended as a tutorial to DIY microcontroller electronics. From the basics to setting up tools, we've now have acquired the equipment and knowledge to pursue for more complicated applications, being a small but important step closer to a working retro-style gaming system. The quest continues!
Original: https://en.wikipedia.org/wiki/File:It's_dangerous_to_go_alone!_Take_this..png

Tuesday 17 May 2016

Microcontrollers part III: Setting up the programmer

To be functional, the microprocessor needs a program. But how can we get one inside as there's no place to stick in a USB drive?

Let's take another look at the pinout of ATtiny85:
On the right side, we see that pins PB0, PB1, and PB2 have alternative labels MOSI, MISO, and SCK. These pins are used for Serial Peripheral Interface (SPI) which is a popular protocol to make embedded devices communicate with each other. When the RESET pin is pulled to ground (as opposite to the normal case), the SPI bus can be used to program the microcontroller.

To get started with programming, we first need to install and setup some essential software to the Raspberry Pi. The easiest way to do this is to paste the following line to the terminal:

 sudo apt-get install gcc-avr binutils-avr gdb-avr avr-libc avrdude  

This installs all the necessary stuff to e.g. compile and debug the programs (gcc-avr, binutils-avr, gbd-avr, avr-libc) and write them to the chip (avrdude). If you use the Pi like a normal computer with a display, mouse and keyboard, that's probably sufficient. I have only one display and I don't want to switch between my PC and Pi all the time, so I connected my Pi to the router with an Ethernet cable and access it remotely from my PC to spice up the nerd factor. However, working over the SSH connection can be tedious sometimes, so I installed the same package on my PC to develop bigger codes on it, leaving the Pi as the chip programmer.

The next step is to edit avrdude's configuration file to list the GPIO bus as a programming device. I did this following a tutorial on adafruit.com and as I'm not planning to steal any credit, I won't copy it on my post but advice you to look up the same tutorial here. Unlike the tutorial, I chose Pi's pin #8 for RESET, #9 for MISO, #10 for MOSI, and #11 for CLK as I wanted them closer to each other. It's a matter of taste what pins you choose.

Pi's GPIO pins. Source and more info: https://www.raspberrypi.org/documentation/usage/gpio-plus-and-raspi2/

All right, time to test out whether we talk with the microcontroller. To connect the chip to Pi, I used a solderless breadboard to which one can just stick all the components and wires in. The most annoying part is to connect all the pins with individual wire. One day I'll build a neat cable for this but for now I have deal with a bunch of 60 cm (2 ft.) long spaghetti. It's a mess.

Pi's GPIO connected to the chip. The red wire is the operating voltage (+3.3 V), grey is SCK (or CLK), violet MISO, orange MOSI, white RESET, and the black is ground.
Be extra careful when making these connections. You don't want to short any pins as it might break the GPIO pins or in the worst case the whole Raspberry Pi! I accidentally did short two pins once and it jammed the whole Pi. I already thought I've done goofed but fortunately turning it off and on again brought it alive again.

After connecting the chip it is ready to be tested. Assuming you followed the adafruit tutorial, the configuration file should be in the home folder and the GPIO programmer should be named 'pi_1'. To test reading the chip type the following command to the terminal replacing 'attiny85' with the model you are using:

 sudo avrdude -p attiny85 -C ~/avrdude_gpio.conf -c pi_1 -v  

avrdude then outputs a wall of text and numbers on the screen. If everything went as expected, there should be this line somewhere near the end:

 avrdude: AVR device initialized and ready to accept instructions  

Congratulations, your microcontroller is working, connected properly and ready to be programmed and you're ready to move to the next level post! However, if it isn't, you might get something like this as I did at the first try:

 avrdude: AVR device not responding  
 avrdude: initialization failed, rc=-1  
      Double check connections and try again, or use -F to override  
      this check.  

It can mean that your chip is broken, but most likely some wires are not connected as they should be. In my case none of them were; it turned out that I can't count pins up to eight properly.

Saturday 14 May 2016

Microcontrollers part II: Have a byte of ATtiny85

Microcontrollers come in a wide variety of models and packages. For my projects I'll use ones from Atmel's AVR family. After a long pondering, it turned out that AVR offers the best possible...erm, no. The true reason to pick AVR was that I've had one course in digital electronics that involved a project work using AVR chips. Thus I have a vague idea how to work with AVR controllers which makes my task a tad easier.

The model I'll start working with is ATtiny85. As the AVR family itself, the model was chosen after a comprehensive thought process i.e. I picked it randomly from the catalog while queuing at the local electronics store. I usually don't think too much beforehand; I tend to start with the first idea that comes to my mind and rethink if it fails.

ATtiny85 in DIP8 package
And here's the badass. To run this beast we need operating voltage of at least 2.7 volts but to get out the most of it we should crank it up to 5.5 V. With sufficient amount of volts, it can be run at the maximum clock frequency of 20 Mhz. It has 6 input/output pins, although usually one of them is reserved for other purpose. It has 8 KiB of flash memory to store the programs, and 512 bytes of RAM and EEPROM memory each to hold the run-time data and to store long term data, respectively. Such wow!

As bits and bytes are essential in digital electronics, I want to say a few words about them. A bit is the smallest unit of information in digital computing. It has two possible values: HIGH (ON, 1) or LOW (OFF, 0). In electronics these are practically implemented with voltage; either there is some or there is not. When we want to present numbers in binary, we put together multiple bits. For example with two bits we can present numbers from 0 to 3 with 0 = 00, 1 = 01, 2 = 10, and 3 = 11.

In 8-bit microprocessors the data is handled in the groups of 8 bits, which are also known as bytes. Each byte holds a value in the range of 0 to 255. Depending on the situation, bytes can represent other types of data as well, like characters or instructions for the processor. In ATtiny85, there is 8 KiB of memory for the program. KiB is often called kilobytes but the technically correct term would be kibibyte. One kibibyte is 1024 bytes, so 8 KiB would be 8192 bytes.

To put things into perspective, this is what it would approximately look like as an 8-bit grayscale bitmap (here I was forced to use PNG format which compresses it down). The picture contains 90 x 90 pixels. The "greyness" of each pixel is presented by one byte with the value in the range of 0 (black) to 255 (white). 512 bytes would be 16x32 sized rectangle to which Mario barely fits in. It is less than it would take to store this paragraph if every character was presented with a single byte! "Much" memory but sufficient for now.

Next we have to figure out how to connect the microcontroller to the rest of our chip. For this we need to get our hands on its datasheet. Datasheets are the source of all the necessary information regarding electronic components. Each component has a datasheet that tabulates its characteristics, like temperature behaviour or typical variation in parameter values, and most importantly for complicated components, how to use them. So in its datasheet, the pinout for ATtiny85 in DIP8 package looks like this:

ATtiny85 pinout from the datasheet
Holy fuck. Apparently this bastard is capable of doing way more stuff I knew. Honestly I have no idea what most of these acronymic abominations mean. Fortunately I don't have to. The essential thing for now is to know that VCC stands for positive operating voltage, GND for ground (i.e. negative end of the battery) and PB0 to PB4 are the input and output pins where we will eventually connect some buttons and displays and whatever our console needs.

According to the datasheet, PB5 is a special case. It behaves normally as the RESET pin, or technically its inverse. This means that if LOW signal is put to the RESET pin, it resets the chip and we get nowhere in our program. To prevent this we have to wire it to HIGH signal which is easiest to get from the operating voltage. Thus all I have to do is to connect the wires to the chip like this:


and voilĂ , it works! ...Or it would work, if it had a program in it. Now it does pretty much nothing but waste electricity. At this point we'll need to get out the Raspberry Pi but that'll be the topic of the next post.


References:

ATtiny25/45/85 datasheet

Original screenshot from the Super Mario Bros. from https://en.wikipedia.org/wiki/Super_Mario_Bros.

Thursday 12 May 2016

Microcontrollers part I: Basic structure

Last time I wrote about the Raspberry Pi, a beer can sized computer. Now it's time to go even smaller. The following couple of posts are about microcontrollers which shall be the brain and soul of my future game console.

The microcontroller, or MCU, is simply put a very small computer crammed into a single chip. Unlike personal computers, MCUs have typically a rather humble amount of computing power but they are low cost and don't require much electricity. Therefore they are perfect to solve relatively simple tasks in embedded systems. If a desktop computer is a car and the Pi is a motorcycle, then the microcontroller would be a lawnmower: not very fast but good for its intended purpose.
Basic building blocks of a microcontroller.
The core of the MCU consists of a control unit and at least one arithmetic and logic unit (ALU). The control unit is responsible that all the action happens where it should; it translates the instructions to actual operations, temporarily stores small bits of data in registers and moves the data around the chip. It is the manager that follows the programmer's instructions telling the ALU what to do. The arithmetic and logic unit is the part that does all the number crunching and logical operations. Together the control unit and the ALU are called central processing unit, or CPU, just like the processor in the desktop computer.

In addition to the CPU, a microcontroller contains memory, input and output peripherals and quite often an internal clock. Memory comes in two flavours: volatile and non-volatile memories. Here volatile memory is synonymous with random access memory (RAM) which is fast but requires power hold information. RAM is therefore used for run-time storage of data, such as the position of the player or the number of lives left.

Non-volatile memory on the other hand retains its data even without power. However, depending on the type of the memory it is either non-writeable or slow. Non-volatile memory is thus most suitable for storing the program itself or data that needs to be preserved even when the system is down, like save states.

Input and output peripherals connect the chip to the surrounding world. Input can be, for example, signals from a controller to move the player around. Output signals can control the graphics on the screen or play funky music out of the speaker.

The last but not the least is the clock, an oscillator that produces a periodic signal that rapidly switches between ON and OFF states. The clock makes the microcontroller tick controlling the pace at which the instructions are executed.

Schema of a clock signal
Whenever you see MHz (million oscillations per second) or GHz (billion oscillations per second) mentioned in the context of computers, it most likely refers to the frequency of the clock signal. Higher the frequency, the more ticks per second. This, however, doesn't necessarily mean that a microcontroller with higher clock frequency has faster computation speed as the number of clock cycles to execute instructions depends on how they are implemented in a particular processor. Many MCUs have an internal clock but their frequency can be unstable. One uses an external crystal like in electronic watches when precise timing is required.

Well, that was a good bunch of theory. In the next post I'll make it more concrete through an example chip that I'll be using in applications once I get there. Until then, stay tuned.  


References:

James J. Brophy, Basic Electronics For Scientists, 1983, McGraw-Hill International Book Company

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

Tuesday 10 May 2016

Raspberry Pi: A computer that fits into a pocket

I assume that most modern kitchens are equipped with some kind of a food processor to do all the hard work. Mine doesn't. I don't even own a microwave oven but as like 85% of my cooking involves frozen pizza, I don't need all that fancy stuff.

However, my retro kitchen doesn't survive without its own multipurpose machine. In digital electronics development there are equipment that is absolutely essential, like the power source, the programmer for the microcontroller and the oscilloscope for debugging, just to name few. Separately these would cost an assload of money which I can't afford on a short time scale. Because I'm broke. Luckily, I don't have to.

The Raspberry Pi logo
The Raspberry Pi is a small but fully functional computer which
is surprisingly powerful for its size and price. Especially intended for learning and DIY purposes, it is equipped with a bunch most commonly used ports and connectors, making it very versatile for a wide variety of uses. People have made use of it from the living room's media center to robotics and even a small scale computing cluster. It runs an operating system called Raspbian practically out-of-the-box which as Linux-based is in my opinion the most suitable platform for programming. In addition to costing less than a long night in the pub, it is ideal for my project's needs.


I got myself a Model 2 a few months ago. My original purpose was to use it as the heart and soul of a yet-to-be-built automatic flower watering system. I thought it would be nice and simple to use the Pi to control the water valve and monitor the water level but soon I realised how fucking stupid that would have been. Not that it wouldn't work but because it would have been a total waste of the Pi's capabilities. Oh yes, I would have made it to send me email every time the water reservoir runs too low but other than that there's nothing a simple microcontroller wouldn't do. In fact, an analog clock would perform just fine if one just attaches a suitable sensor or a switch to its hour hand.

Raspberry Pi 2 Model B with various features and ports labelled. Lots of cool shit in a small package, no?

Just like a full sized computer, Raspberry Pi is packed with commonly used ports, such as USB for connecting the mouse and the keyboard (and something like 98.6% of all other connectable devices), an Ethernet port for the Internet connection, both digital and analog audio and video outputs, and a slot for a Micro SD card which functions as a hard drive. In addition there are connectors for a display and a camera specifically designed for the Pi and the whole package is powered via micro USB connector.

However, for my project the most important part in the general-purpose input/output a.k.a. the GPIO pins. As the name suggests, these pins can be programmatically set either to produce or read digital signal. The generation of the digital output is the key factor in the programming of microcontrollers as it transfers the instructions from the computer to the memory of the microcontroller. I will cover microcontrollers and their programming in more detail in the next posts.

Another practical use of the signal generation is to simulate the behavior of the unfinished parts of the circuit with it. For example, we could want to test whether the system reacts to the controller input as desired but we don't have functional controllers yet. A simple way to go around this is to write a small program on the Pi that produces the same kind of signal that a controller would and test the circuit with it. Conversely, we can use the Pi's GPIO pins as input and see if the signal produced by some part of the circuit is the way it should be. Some of the GPIO pins act as voltage sources (+3.3 and +5 volts) which can power up our circuit in the building phase.

The Raspberry Pi is truly an amazing device and without it I wouldn't probably be writing this blog. Later on I'll show you how it can be used for programming but first I want to talk about microcontrollers and microprocessors and their role in the gaming systems.

More info:

Sunday 8 May 2016

It is time to oil up

Mesdames et Messieurs, welcome to my kitchen! I'm Chef Ari-Pekka and I have a passion towards retro gaming. Now it's time to heat up the oven and prepare the ingredients.

As I mentioned earlier, I will have a hands-on approach to the subject. It means that instead of in addition to going through a bunch of circuit diagrams, reviews, and technical information, I am actually going to fulfill my long lasting desire to design and build my own gaming system. That's right, I'm going to make a fucking (neo)retro console!

However, that is not going to be easy. I do have taken a couple of courses in electronics at the university level but I'm by no means an expert in this field. I'm more familiar with the programming, which will also play a large role in this project. Nevertheless, that is not going to be easy either as programming microcontrollers is quite different than what I'm used to. Lots of trials and errors, I foresee.

The quest for a working console will be a challenging and time-consuming one but I believe an entertaining and enlightening as well. I'd be eager to get right into the action but I guess it would be best to use a post or two to introduce you to my equipment before the appetizers are served. Because what would be the cook without his knives?

(idk, a knifeless cook surely)

Player 2 Press Start!

I love games. Computer games, console games, board games, card games, you name it. But among all of these incarnations of gaming there's one category that has a special place in my heart: retro consoles.

We've come a long way since the days of Atari 2600, Nintendo Entertainment System, and Sega Mega Drive (or Genesis) and that's a good thing. The Internet has made the world smaller and the life way easier.

Still, I kinda miss the cartridges, the simplicity and the lack of the Internet connection. Especially the last one, as for me playing games over the net just doesn't feel the same to me as playing them in the same living room with friends.

Besides the gaming experience itselt, I'm also fascinated by the technology behind these old systems. Consoles and computers today are so complicated that it is impossible for a single person to understand what every single part in the system is doing. With modern computers that is not even necessary.

In my work I do a lot of programming but I practically never have to worry about the hardware of the system. I just import all the shit from libraries and work on a high-level. With simpler systems that kind of comfort is not possible as the programmer needs keep track on individual memory addresses, handle all the inputs and outputs explicitly and so on. The required low-level understanding intrigues me.

The simplicity and limited computational resources adds up the challenge. It's like Japanese poems, tankas and haikus, where strict limitations in the syllable count is ought to get the creativity flowing. Creative thinking is surely what you need to get the most juice out of the system whose central processing unit is a potato by the modern standards.

In brief, this blog is a hands-on journey into the retro gaming. How? That is the topic of the next post.