Kalan's Blog

Software Engineer / Taiwanese / Life in Fukuoka

Current Theme light

Background

2020 was a chaotic year, but it also gave me an opportunity to rethink the essence of computers. During this year, I ventured into many areas that were not my expertise, all centered around one theme: understanding the fundamentals.

I studied electronics in vocational school (technically, it was a vocational high school). In the era focused on higher education, although we had practical classes, it often felt like we were just following a syllabus, and most of our time was spent studying and solving problems. The only fortunate thing was that the workload wasn't as heavy as in regular high schools; otherwise, I might not have been able to enter a technical university.

One regret I had during vocational school was that I didn't have much interest in hands-on projects. A significant portion of my time was spent on soldering, breadboarding, ensuring wires didn't overlap or cross each other – tasks that were challenging for someone like me, who wasn't skilled in craftsmanship.

Interestingly, during my electronics studies, I didn't have a strong interest in electronics itself, and I never anticipated that I would make a living by writing code. However, because of this, I recently started developing an interest in these lower-level aspects.

Coming back to the main question, the answer depends on how well you understand computers. Diodes and transistors, registers, CPU operations, operating systems – the knowledge in each of these areas is vast and could take a lifetime to explore fully. It's truly profound.

For me, this year has been about truly understanding what a computer is. Although I am not a professional, I have found great pleasure in gaining a deeper understanding. I have also found colleagues at work who share the same interest in the lower-level aspects.

Overlap with Electronics Studies

When studying electronics in vocational school, I never expected that the knowledge I gained would be so useful later on. Concepts like bridge rectifiers, diodes, filters, and voltage regulators are frequently used in charger circuits. I must have solved hundreds of problems related to these topics during exams, and even had to experiment with a bridge rectifier circuit during practical classes.

When performing addition in a CPU, you need to implement an adder, which can be further divided into half adders and full adders. We learned about these step by step in class, creating truth tables and implementing them on breadboards using logic gates (although you could also use integrated circuits).

CPUs require clock signals for operation, often generated by quartz oscillators or external clock generators. It turns out that the NE555 circuit, which we struggled to understand back then, can generate clock signals for a CPU to function! (Of course, nowadays it's mostly built-in.)

The flip-flop circuits, which seemed mysterious at first, are actually the foundation of implementing registers. As I gained a deeper understanding of these fundamentals, I realized that I had already covered these topics during vocational school, but I hadn't connected the dots back then.

Knowledge related to these lower-level aspects has a sense of mystery. On one hand, the entry barrier is relatively high, as not everyone buys chips and breadboards every day, and you need to have some understanding of each knowledge point. On the other hand, there is very little information available online, and you may have to search for keywords for a long time to find the answer buried in the xth comment under some forum thread. Many times, when faced with a problem, you have to find a way to solve it on your own.

Returning to the Basics

In light of this, in 2020, one of my goals was to get as close to the fundamentals as possible, whether it was hardware, understanding how operating systems work, or understanding how programming languages operate. Anything that could help me understand the underlying aspects was fair game.

So, at the beginning of this year, I bought an Arduino. Some people might think that Arduino is just a pre-packaged solution, right? That's true, but I thought it would be a good starting point. Instead of using pre-written libraries for a certain sensor, I would first dive into the datasheet and figure out how to use it. If that didn't work, I could then refer to the library implementation.

In July of this year, I implemented an air quality monitoring application using Arduino and ESP32. It involved using MQTT, DHT11, and MH-Z14A sensors, with UART for data communication. Instead of relying solely on libraries, I made sure to thoroughly read the MH-Z14A datasheet and implement it myself. Although I used libraries for Wi-Fi and MQTT, I still learned a lot from the project.

But that wasn't enough. I didn't want to be limited by the Arduino framework. So, I went on Amazon and found the legendary MOS 6502.

The MOS 6502 is considered a classic because it is affordable and relatively powerful. It was used in devices like the Famicom and Apple II as an 8-bit CPU. Furthermore, compared to modern CPUs, its instruction set and design are relatively simple, making it easier to understand CPU operations.

I was excited to place an order and eagerly awaited its arrival. However, I later realized that the MOS 6502 doesn't have built-in EEPROM, so you have to write the program to an EEPROM and then feed it to the MOS 6502. Unfortunately, I don't have a good channel to buy the EEPROM I wanted in Japan at the moment, so I had to put that plan on hold.

As an alternative, I turned to AVR. Fortunately, there is an electronics parts store near where I currently live, which sells various microcontrollers from the ATmega series (including ATmega328, the same MCU used in Arduino UNO).

Using ATmega328 has its advantages. Firstly, its size fits perfectly on a breadboard. Secondly, its instruction set is relatively simple. Additionally, it has some unique features, such as:

  • 32 registers, which is more than other architectures (x86: 8, ARM: 16)
  • Most instructions require only one clock cycle
  • Most AVR chips have built-in flash and EEPROM, eliminating the need for an external EEPROM and making reading more efficient

Understanding Assembly Language and Hardware Logic

In the world of hardware, everything becomes simple yet inconvenient. For example, if you want to set a certain pin to output a high voltage using pure assembly language (AVR), you might write something like this:

ldi r16, 0x01
out DDRB, r16
out PORTB, r16

First, you load 0x01 into register r16, then you set the DDRB register (data direction) to 0x01, and finally, you set the PORTB register to 0x01. This is similar to what digitalWrite does.

Surprisingly, assembly language is not as difficult as one might imagine. However, writing assembly language at an industry level is likely much more challenging.

Deeper Understanding of Interrupts

Although I haven't fully grasped how interrupts work in terms of hardware circuits, I have gained a deeper understanding of interrupts themselves.

In general, CPUs define an interrupt vector to describe what should happen when an interrupt occurs. The decision to enable or disable interrupts is usually determined by the Global Interrupt Enable bit in the SREG register. Understanding this requires sufficient knowledge of register operations and bit shifting. In AVR, there are usually several corresponding functions (avr/interrupt.h).

This aspect is fascinating but also prone to errors. It's relatively manageable for toy projects, but I wonder how people manage and debug interrupt mechanisms in production.

Understanding Operating Systems

Around March-April this year, I intermittently studied an operating systems course on Coursera. I learned about various concepts, from the program counter (PC), instruction register (IR), kernel mode, user mode, atomic operations, threads, and even semaphores. Although I don't fully understand how to implement them yet, I have a relatively better understanding. Recently, I came across a book called "30 Days to Make Your Own OS," which looks quite basic and likely omits many details, but I find it interesting. Maybe I'll give it a try when I have some free time. I still prefer testing directly on real hardware rather than using simulators!

operating system-30

Programming Languages

At the beginning of this year, I unexpectedly came across a book written by Yukihiro Matsumoto, titled "Language Implementation by Yukihiro Matsumoto." In the book, he implemented a programming language from scratch, starting with yacc/lex, and explained the principles and implementation step by step. I was amazed by the level of completeness he achieved. It wasn't just about basic arithmetic operations; it included strings, time processing, numbers, randomness, arrays, atomics, and more – all the fundamentals that a programming language should have. Although I would like to do something similar, I find it challenging to understand the yacc/lex documentation. I'll take on that challenge when I have a deeper understanding of the C language.

Another project I worked on was attempting to create a simple version of Svelte (without reactive features) from scratch while participating in an IT competition. I wrote a basic parser. It was a small taste of working with programming languages.

There is still so much to learn in the future! Let's all strive to overcome the chaos of this year together!

Prev

linaria - CSS-in-JS solution that doesn't require runtime

Next

Hotwire and Turbolinks

If you found this article helpful, please consider buy me a drink ☕️ It'll make my ordinary day shine✨

Buy me a coffee

作者

Kalan 頭像照片,在淡水拍攝,淺藍背景

愷開 | Kalan

Hi, I'm Kai. I'm Taiwanese and moved to Japan in 2019 for work. Currently settled in Fukuoka. In addition to being familiar with frontend development, I also have experience in IoT, app development, backend, and electronics. Recently, I started playing electric guitar! Feel free to contact me via email for consultations or collaborations or music! I hope to connect with more people through this blog.