Thursday, December 14, 2023

Blackout

I realize it's been a long time since my last blog post, and so I'd like to start by apologizing for my long absence. Life, sometimes, takes us down unexpected paths and puts us face to face with challenges that require all our attention and strength.

As some of you know, I am dealing with a health condition that requires brain surgery, scheduled for the next three months. This period of waiting and preparation has been an emotional journey, full of reflections and moments of introspection.

During these months, I have experienced a range of emotions: from tiredness to sadness, from doubts to hope. These feelings have affected not only my daily life, but also my ability to focus on the Macintosh 128k replica project and keep this blog updated.

In this period of preparation for the surgery, I am learning to balance my commitment to the project with the need to take care of my health. This led me to reflect on the importance of accepting and sharing my vulnerability, not only as an act of personal courage, but also as a way to connect with others who may find themselves in similar situations.

However, I will continue to share updates when possible, because this project and this blog are important parts of my journey.

Thank you for your understanding, patience and continued support. I hope to soon share positive news and new progress on our journey together in the world of technology and innovation.

Tuesday, November 28, 2023

Inside the Macintosh: the memory.

Let's start from this post with a series of posts with technical "dissection" of the different areas of the Macintosh mainboard. It's very important to understand how the hardware works.

Of course, a software emulator works differently from the real hardware, and many times it's a question of implementing tricks, especially when the emulator must run on a limited system such as a microcontroller.

So I will take my time in studying components, I will read the datasheets, and I will include also the link to download them.

I usually consider the memory of the computer first. ROM and RAM are absolutely necessary so let's take a look at the motherboard.

The amount of RAM present in the Macintosh 128K is... 128KB!!! WOW, what a surprise. The amount of ROM in total is 64KB. The ROM is made of two 32KB modules, together they make a 16-bit 32K words memory bank.

The geometry of the RAM instead is different. There are sixteen modules of 64K bits of dynamic RAM. These modules store a matrix of one column by 64K rows of single bits. Eight of these modules are addressed together to store a single byte, one bit for each module. Like the ROM there are two blocks of eight modules, that together make a 16-bit 64K words memory bank.


It's easy to understand how this RAM works. Take a look at the pinout of this module. 

 

Basically, the access to the internal storage happens in two main steps, keeping the line "WriteEnable" low for writing one bit, or high for reading one bit. These steps are needed to set the address of the bit in the range 16-bit wide. So RAS and CAS are asserted low to latch the high and low bytes of the address. According to the state of the WE line a bit is put on data pin Q (read), or the bit on data pin D (write) is written in the memory.

This access mechanism is not needed in a software emulator of course, but I am here to understand how this Mac works. But if you are interested in going deeper with access timings, here's the DRAM MT4264 datasheet.

In my emulator, this kind  of memory can be implemented easily with arrays, I think something like:  
uint16_t ram[65536];
const uint16_t rom[32768] = {
   /* Dump of the ROM */
};

But I will be back on the implementation later.

Sunday, November 19, 2023

An experiment just for fun.

I knew that "Digital" would enchant me. Especially for the fact that it gives me the opportunity to virtually replicate different areas of the Macintosh circuit to perform tests and understand how it works.

Now I would like to do an experiment. In truth, I don't need to go so low level for the emulator I have to write, but I'm curious to see how far this circuit simulator goes.

I want to try to implement the 64k-bit MT4264 DRAM memory chips present in the 128K Macintosh. So I found the datasheet, extracted the text of the description, and asked ChatGPT to synthesize the chip in Verilog naturally following the specifications.

What happened is interesting.

Hi, I want to build a DRAM module in Verilog. The DRAM size is 64k bits organized in 64k * 1. This is the description of the component in the datasheet. Can you write the Verilog module for me?

"The MT4264 is a randomly accessed solid-state memory containing 65,536 bits organized in a x1 configuration. During READ or WRITE cycles, each bit is uniquely ad- dressed through the 16 address bits, which are entered 8 bits (A0-A7) at a time. RAS is used to latch the first 8 bits and CAS the latter 8 bits. A READ or WRITE cycle is selected with the WE input. A logic HIGH on WE dictates READ mode while a logic LOW on WE dictates WRITE mode. During a WRITE cycle, data in (D) is latched by the falling edge of WE or CAS, whichever occurs last. If WE goes LOW prior to CAS going LOW, the output pin(s) remain open (High-Z) until the next CAS cycle. If WE goes LOW after data reaches the output pin(s), data out (Q) is activated and retains the selected cell data as long as CAS remains LOW (regardless of WE or RAS). This late WE pulse results in a READ-WRITE cycle. PAGE MODE operations allow faster data operations (READ, WRITE or READ-MODIFY-WRITE) within a row address (A0-A7) defined page boundary. The PAGE MODE cycle is always initiated with a row address strobed-in by RAS followed by a column address strobed-in by CAS. CAS may be toggled-in by holding RAS LOW and strobing- in different column addresses, thus executing faster memory cycles. Returning RAS HIGH terminates the PAGE MODE operation. Returning RAS and CAS HIGH terminates a memory cycle and decreases chip current to a reduced standby level. Also, the chip is preconditioned for the next cycle during the RAS HIGH time. Memory cell data is retained in its correct state by maintaining power and executing any RAS cycle (READ, WRITE, RAS-ONLY or HIDDEN RE- FRESH) so that all 256 combinations of RAS addresses (A0- A7) are executed at least every 4ms, regardless of sequence"

Creating a Verilog module for a DRAM such as the MT4264 involves simulating the behavior of the DRAM as described in your datasheet. In this simulation, you'll model the address latching with RAS and CAS, the READ and WRITE operations controlled by the WE signal, the data input and output handling, PAGE MODE operations, and the necessary timing for refresh cycles.

Here's a basic structure for such a module. This code is a simplified representation and may need adjustments based on the specific requirements of your system, such as timing constraints and interface details.

module MT4264 (
    input wire clk,        // System clock
    input wire rst,        // System reset
    input wire [7:0] addr, // 8-bit address input
    input wire ras,        // Row Address Strobe
    input wire cas,        // Column Address Strobe
    input wire we,         // Write Enable
    inout wire data        // Data line (bidirectional)
);

    // Memory array
    reg [0:0] memory [0:65535];
    reg [15:0] full_address;
    reg data_out;
    wire data_in;

    // Bidirectional data line
    assign data = (!we && !cas) ? data_out : 1'bz;
    assign data_in = data;

    // Latching addresses
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            full_address <= 16'd0;
        end else begin
            if (!ras) full_address[15:8] <= addr; // Latch row address
            if (!cas) full_address[7:0] <= addr;  // Latch column address
        end
    end

    // Read/Write operations
    always @(posedge clk) begin
        if (!cas && !we) begin
            // Write operation
            memory[full_address] <= data_in;
        end else if (!cas && we) begin
            // Read operation
            data_out <= memory[full_address];
        end
    end

    // Refresh logic (simplified)
    // In real applications, refresh logic must cycle through all row addresses
    // within the required refresh interval (e.g., every 4ms).

endmodule

This module covers the basic address latching with RAS and CAS, and the READ/WRITE operations based on the WE signal. The "memory" array represents the DRAM cells. The actual refresh logic and PAGE MODE operations are not implemented in this example and would need to be added based on your specific requirements.

Remember that this is a simplified model and may not accurately represent all nuances of the real DRAM behavior, especially with regard to timing constraints and electrical characteristics. It's suitable for simulation purposes but might need adjustments for use in real hardware or more detailed simulations.

The data signal is not bidirectional. Can you split it into signal D as input data, and Q as output data.

Certainly, splitting the data signal into separate input and output lines makes sense for clarity and alignment with typical DRAM module designs. Here's the revised Verilog module with "D" as the input data signal and "Q" as the output data signal:

module MT4264 (
    input wire clk,        // System clock
    input wire rst,        // System reset
    input wire [7:0] addr, // 8-bit address input
    input wire ras,        // Row Address Strobe
    input wire cas,        // Column Address Strobe
    input wire we,         // Write Enable
    input wire d,          // Data input
    output reg q           // Data output
);

    // Memory array
    reg [0:0] memory [0:65535];
    reg [15:0] full_address;

    // Latching addresses
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            full_address <= 16'd0;
        end else begin
            if (!ras) full_address[15:8] <= addr; // Latch row address
            if (!cas) full_address[7:0] <= addr;  // Latch column address
        end
    end

    // Read/Write operations
    always @(posedge clk) begin
        if (!cas && !we) begin
            // Write operation
            memory[full_address] <= d;
        end else if (!cas && we) begin
            // Read operation
            q <= memory[full_address];
        end
    end

    // Initialize the output
    initial begin
        q = 1'b0;
    end

    // Refresh logic (simplified)
    // In real applications, refresh logic must cycle through all row addresses
    // within the required refresh interval (e.g., every 4ms).

endmodule

In this version, "D" is used to write data into the memory array during write operations, and "Q" is used to hold the data read from the memory array during read operations. This separation aligns better with the actual DRAM interface, where data input and output are typically on separate lines.

Again, keep in mind that this is a basic model intended for simulation purposes and does not include all aspects of a real DRAM, such as detailed timing behavior, PAGE MODE operations, and comprehensive refresh logic.

by the way, signals RAS, CAS and WE are active low.

Thank you for clarifying that RAS, CAS, and WE are active-low signals. In Verilog, this means we should treat these signals as being active or 'asserted' when they are at a logical low level ("0"). I'll modify the code to reflect this behavior:

module MT4264 (
    input wire clk,        // System clock
    input wire rst,        // System reset
    input wire [7:0] addr, // 8-bit address input
    input wire ras_n,      // Row Address Strobe (active low)
    input wire cas_n,      // Column Address Strobe (active low)
    input wire we_n,       // Write Enable (active low)
    input wire d,          // Data input
    output reg q           // Data output
);

    // Memory array
    reg [0:0] memory [0:65535];
    reg [15:0] full_address;

    // Latching addresses
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            full_address <= 16'd0;
        end else begin
            if (ras_n == 1'b0) full_address[15:8] <= addr; // Latch row address
            if (cas_n == 1'b0) full_address[7:0] <= addr;  // Latch column address
        end
    end

    // Read/Write operations
    always @(posedge clk) begin
        if (cas_n == 1'b0 && we_n == 1'b0) begin
            // Write operation
            memory[full_address] <= d;
        end else if (cas_n == 1'b0 && we_n == 1'b1) begin
            // Read operation
            q <= memory[full_address];
        end
    end

    // Initialize the output-
    initial begin
        q = 1'b0;
    end

    // Refresh logic (simplified)
    // In real applications, refresh logic must cycle through all row addresses
    // within the required refresh interval (e.g., every 4ms).

endmodule

In this revised module, "ras_n", "cas_n", and "we_n" are treated as active-low signals. The code checks for "0" (low) to determine when these signals are active. This approach better matches the behavior described in the datasheet and is common in hardware design where active-low control signals are used.

Remember, this is still a basic simulation model. For practical hardware implementation, you'll need to consider the specific timing requirements and characteristics of the DRAM, which are not fully captured in this simple model.

Another thing, this DRAM is asynchronous so the clock signal is not necessary.

You're absolutely correct. Asynchronous DRAMs, like the one described in your datasheet, do not use a system clock signal for their operation. Their actions are controlled entirely by the RAS, CAS, and WE signals, along with the address inputs. I'll revise the Verilog module to reflect this asynchronous behavior:

module MT4264 (
    input wire rst,        // System reset
    input wire [7:0] addr, // 8-bit address input
    input wire ras_n,      // Row Address Strobe (active low)
    input wire cas_n,      // Column Address Strobe (active low)
    input wire we_n,       // Write Enable (active low)
    input wire d,          // Data input
    output reg q           // Data output
);

    // Memory array
    reg [0:0] memory [0:65535];
    reg [15:0] full_address;
    reg [7:0] row_address;
    reg [7:0] col_address;

    // Latching addresses on the falling edge of RAS and CAS
    always @(negedge ras_n or negedge cas_n) begin
        if (!ras_n) row_address <= addr; // Latch row address
        if (!cas_n) col_address <= addr; // Latch column address
    end

    // Combine row and column addresses
    always @(*) begin
        full_address = {row_address, col_address};
    end

    // Read/Write operations
    always @(*) begin
        if (!cas_n) begin
            if (!we_n) begin
                // Write operation
                memory[full_address] <= d;
            end else begin
                // Read operation
                q <= memory[full_address];
            end
        end
    end

    // Initialize the output
    initial begin
        q = 1'b0;
    end

    // Refresh logic (simplified)
    // In real applications, refresh logic must cycle through all row addresses
    // within the required refresh interval (e.g., every 4ms).

endmodule

In this version, the "clk" input has been removed, and the operations are triggered by changes in the RAS and CAS signals (specifically their falling edges, which is typical for active-low control signals in asynchronous memory modules).

Since there's no clock signal, the operations are now handled by combinational logic ("always @(*)"). However, do note that this might lead to more power consumption in simulation as changes to the address or control lines would immediately reflect in the logic.

As always, this module is a simplified model and does not include specific timing behavior, detailed PAGE MODE operations, or comprehensive refresh logic, which are important in a real-world implementation.

the last thing, the original component doesn't have the reset signal.

Understood. If the original DRAM component, such as the MT4264, does not include a reset signal, we should remove it from the Verilog module to accurately reflect its functionality. Here's the revised code without the reset signal:

module MT4264 (
    input wire [7:0] addr, // 8-bit address input
    input wire ras_n,      // Row Address Strobe (active low)
    input wire cas_n,      // Column Address Strobe (active low)
    input wire we_n,       // Write Enable (active low)
    input wire d,          // Data input
    output reg q           // Data output
);

    // Memory array
    reg [0:0] memory [0:65535];
    reg [7:0] row_address;
    reg [7:0] col_address;

    // Latching addresses on the falling edge of RAS and CAS
    always @(negedge ras_n or negedge cas_n) begin
        if (!ras_n) row_address <= addr; // Latch row address
        if (!cas_n) col_address <= addr; // Latch column address
    end

    // Combine row and column addresses
    always @(*) begin
        // Combine the latched row and column addresses to form the full address
        full_address = {row_address, col_address};
    end

    // Read/Write operations
    always @(*) begin
        if (!cas_n) begin
            if (!we_n) begin
                // Write operation
                memory[full_address] <= d;
            end else begin
                // Read operation
                q <= memory[full_address];
            end
        end
    end

    // Initialize the output
    initial begin
        q = 1'b0;
    end

    // Refresh logic (simplified)
    // In real applications, refresh logic must cycle through all row addresses
    // within the required refresh interval (e.g., every 4ms).

endmodule

In this version, the module no longer includes a "rst" (reset) input. The operations are controlled entirely by the address, RAS, CAS, and WE inputs. The memory is latched based on the state of the RAS and CAS signals, and read/write operations are performed accordingly.

Keep in mind that this is a basic model for simulation and conceptual understanding. Real-world DRAM behavior, especially concerning timing and refresh cycles, is more complex and would require additional logic and considerations in an accurate simulation or hardware implementation.

Uhm, I think you missed the full_address register

You're absolutely right. I apologize for that oversight. The "full_address" register is crucial for combining the row and column addresses. Let me correct that in the Verilog code:

module MT4264 (
    input wire [7:0] addr, // 8-bit address input
    input wire ras_n,      // Row Address Strobe (active low)
    input wire cas_n,      // Column Address Strobe (active low)
    input wire we_n,       // Write Enable (active low)
    input wire d,          // Data input
    output reg q           // Data output
);

    // Memory array
    reg [0:0] memory [0:65535];
    reg [7:0] row_address;
    reg [7:0] col_address;
    reg [15:0] full_address; // Combined row and column address

    // Latching addresses on the falling edge of RAS and CAS
    always @(negedge ras_n or negedge cas_n) begin
        if (!ras_n) row_address <= addr; // Latch row address
        if (!cas_n) col_address <= addr; // Latch column address
    end

    // Combine row and column addresses
    always @(*) begin
        full_address = {row_address, col_address};
    end

    // Read/Write operations
    always @(*) begin
        if (!cas_n) begin
            if (!we_n) begin
                // Write operation
                memory[full_address] <= d;
            end else begin
                // Read operation
                q <= memory[full_address];
            end
        end
    end

    // Initialize the output
    initial begin
        q = 1'b0;
    end

    // Refresh logic (simplified)
    // In real applications, refresh logic must cycle through all row addresses
    // within the required refresh interval (e.g., every 4ms).

endmodule

In this corrected version, "full_address" is correctly declared and used to combine the row and column addresses. This register is essential for addressing the correct memory cell within the 64K-bit array. Thank you for pointing out the mistake!

Remember that the A.I. it's not infallible, it's a risk to ask and copy/paste. The best intelligence is the one between the two ears!

Anyway, I tested the component in Verilog.

Unfortunately, by creating an array of 16 MT4264 DRAMs, the application struggles a bit in the initial compilation of the component. 

So, since it is not necessary at the moment, I will create two 64K*8bit memories using the native components which simulate a typical access of a dynamic RAM. 

Saturday, November 18, 2023

Bricks for this project, really?

I don't know if it's happened to you too, but when I study electronic diagrams it makes me want to "reconstruct" the circuit to see it work. It's as if your head starts to go faster in imagining that you already have all the components at hand, ready to be inserted into their respective sockets on the PCB.

It is also frustrating to note that the transition from a scheme to a prototype is not so immediate, especially in my current condition, where handling components, wires, and soldering iron has become a  little difficult. 

The "luck" is that I don't want to build such a complex prototype because I will use a development board on which an emulator will run.

Now I'm "only" studying how the components interact, so a digital electronic circuit simulator might be enough. But what do bricks have to do with it? Well, logic gates are the building blocks of computers, and having a tool that allows you to grow assemblies of logic gates and see them in action can be essential for reverse engineering.

After several days of searching, I found him, "Digital", fantastic. The author's page reads: "Digital is an easy-to-use digital logic designer and circuit simulator designed for educational purposes." Educational says. In my opinion, it is much, much more!


In addition to being simple and intuitive to use, it is very powerful and feature-rich. The thing I love is the ability to create custom components using VHDL or Verilog, but not only that, but you can also see them in action in the simulation. 

 But what struck me most? What if I say VGA? What? But of course, there is a component that is able to function as a VGA monitor, not in real time (yet) but manages to hook HSync, VSync, and RGB signals with pixel clocks available in many resolutions.


A fire lit up inside me, I forgot for a while my never-ending headache, and like a rocket I began to design the video circuit of the Macintosh, modifying the standard 640*480 VGA signal to display the resolution of 512*342, using only 16 pixels in repetition.

Crazy!

Needless to say, I will use it a lot, and I will reveal many surprises to you! Check this out!

https://github.com/hneemann/Digital

Monday, November 13, 2023

Diving deep in the Mac.

I've been diving online for days looking for technical information on the Apple Macintosh 128k hardware. In truth, I didn't find much, at least what I was looking for.

I was studying the diagrams and photos of the motherboard that I found, and I understood that the "custom" chips have a crucial role in the functioning of the Mac. 

They are called "PAL", or "Programmable Array Logic", and are programmed from the factory with particular programs that tell the chip how to configure the output signals based on the input signals.

They are used mostly to translate memory addresses into activation signals for specific components, this means that for example if I want to read bytes from the RAM, or from the serial port, the address of the access must stay in a specific range.                     

BMU0, BMU1, TSM, TSG, LAG, ASG are the names of the 6 wonders that do the hard work of communication between components and the CPU.

Let me ask ChatGPT if he knows something about them.

Tell me something about the PAL chips (BMU0, BMU1, TSM, TSG, LAG, ASG) that are in the Macintosh 128k.

The document "Inside Macintosh" provides some information about the PAL (Programmable Array Logic) chips used in the Macintosh 128K, but it does not offer a detailed explanation of each specific chip (BMU0, BMU1, TSM, TSG, LAG, ASG). These chips are part of the custom hardware design of the Macintosh 128K and play crucial roles in its operation. Here's a brief overview based on general knowledge:

1. BMU0 and BMU1 (Bus Management Unit 0 and 1): These chips are likely involved in managing data transfers across different buses within the computer system, such as between the CPU, memory, and I/O devices.

3. TSG (Timing Signal Generator): Similar to the TSM, the TSG would be involved in generating timing signals necessary for the operation of different parts of the computer, such as the CPU and memory.

4. LAG (Logic Array Generator): This chip might be used for generating specific logic functions required for the operation of the computer, possibly in relation to the CPU or memory management.

5. ASG (Analog Signal Generator): The ASG is mentioned in the context of the disk interface. It reads the disk speed buffer in RAM and generates voltages that control the disk speed. This is crucial for reading, writing, formatting, and ejecting disks.

These chips, being part of the custom hardware design of the Macintosh 128K, were specifically tailored to meet the unique requirements of the system, contributing to its efficiency and performance. For more detailed information about these chips, additional technical resources or hardware manuals specific to the Macintosh 128K would be required.

So, from the manual "Inside Macintosh" not that much, so I did some research, and I have sound some more information:


BMU1 is a 16L8 device that performs the major address decoding functions. 

It has as inputs the higher order address lines A21, A22, and A23 from the processor, along with the overlay bit (for a description of the overlay bit, see the August issue). 

These bits are decoded to generate enable signals for the RAM, ROM, IWM (disk controller), and the SCC serial chip.


LAG is a 16R8 device that performs the majority of the video control functions. 

It has as inputs most of the video address counter outputs, which are decoded to create output signals that load the video shift register, provide the CRT sweep circuitry with horizontal and vertical syncs, increment and reset the video address counters, and switch the RAM address multiplexers between CPU, video, and sound addresses.


BMU0 is a 16R4 device that generates RAM read and write signals from the RAM enable output of BMU1 and the processor R/W line. 

It is also used as a counter to create two video address lines (VA12 and VA13) because the video counter is only 12 bits wide (VA0-VA11). In addition, it also generates DTACK, the data transfer acknowledges the handshake signal to the processor and synchronizes the output of the video shift register with the master oscillator. 

 This is a very good example of the many different types of functions that can be handled with a single programmable device.


TSM is a 16R4 device whose major function is control of the dynamic RAM. For inputs, it has the decoded RAM enable signal, along with the address and data strobes from the processor which signify whether the data transfer will be low byte, high byte, or word. From these, the RAS and CAS strobes are generated, and the row/column address multiplexer is controlled. Until there were PALs, this type of dynamic RAM control function required either about 10-20 discrete TTL packages or a 40-pin LSI dynamic RAM controller which usually didn't do what you wanted anyway.


ASG is a 16R8 device which illustrates why PALs can be so valuable. Its primary purpose is to take the 6-bit disk speed value which is fetched at the end of every horizontal retrace period and convert it to a pulse-width modulated signal. Basically, it's a 6-bit counter. This leaves a couple of inputs and outputs available, which are used to control the loading of the sound generator pulse-width modulator, which is a counter made up of TTL devices. If a discrete counter had been used for the disk PWM, another chip would have been required for the sound PWM load function. Using a PAL for a simple counter function in this instance saved a chip in the design.


TSG is a 16R6 device that illustrates the power of programmable logic. It serves a couple of mundane functions concerning interrupts and the keyboard clock, but by far its most interesting job is as a clock generator for the SCC serial chip.

The master oscillator frequency in the Macintosh is 15.667 MHz. This is divided by 2 in the TSG to get the 7.834 MHz processor clock. In order for the SCC to be able to operate at a baud rate of 230.4 KBaud, which is what AppleTalk requires, it needs an input clock frequency of 3.686 MHz.

If you pull down your calculator desk accessory, you'll find that 15.667 ÷ 3.686 = 4.25. This means that the TSG needs to divide the 15.667 MHz master oscillator by 4.25 in order to get a 3.686 MHz clock. How is this done, since 4.25 is not even an integer, let alone a binary number?

Let's call the 15.667 MHz clock the MO_clk and the 3.686 MHz clock the SCC_clk. For every 17 MO_clk periods, there are 4 SCC_clk periods (17 ÷ 4 = 4.25). The way the TSG generates the SCC_clk is to count to 4 three times and then count to 5 once (4 + 4 + 4 + 5 = 17). See Figure 11 for a graphical description. Try that using a single TTL counter chip!

Monday, November 6, 2023

Know the hardware.

What we need also is a schematic of the mainboard of the Macintosh 128k, and a photo of the PCB, top and bottom side. 

I think that if I dig into the hardware I could learn more, and the development process should be a bit easier.

Unfortunately, ChatGPT can't help me find those on the Internet, so I did it by myself. It has been difficult to find them but in the end, I have found something useful.







Sunday, November 5, 2023

Where to start from.

Now that I've set an environment for the development of tests that I can share with you, I am going back to the emulator

My first idea is to design a main section based on a Finite State Machine, that is executed every cycle of the host application. In my Replit project this application is the SDL based environment, while in the STM32 board is a specific H7 targeted project.

I would like to develop this emulator as a scalable and portable application to have it running on different target platforms. My goal here is not to build a commercial product, but to learn, experiment and enjoy the development of an Apple Macintosh 128k.

There are different approaches in building an emulator. Usually, it should be best to start from a minimalist virtual system, so CPU, RAM, ROM, and the minimum hardware used to control the system. But it may not be fun. The systems that I have written a emulator were equipped with a Video Display Processor, so I started to write my emulators from the video stage. This let me to set a visual output system to be used to show debug information.

When I asked ChatGPT to give me information about the Apple Macintosh 128k, it provided me some details on the graphics section. I to was...

Good morning, thanks for this initial information. Now let's proceed in order. I would like a more detailed description of the hardware divided into areas.

And the answer for the graphics section was...

3. Display:

  • Tipo: CRT (tubo a raggi catodici) monocromatico incorporato
  • Dimensione: 9 pollici (diagonale)
  • Risoluzione: 512 x 342 pixel, il che offriva un'immagine sorprendentemente nitida e dettagliata per l'epoca, supportando l'interfaccia grafica dettagliata del Mac.

Actually not many details, Ineed to understand how graphics is generatedfor the video signal.

How graphics are generated on Apple Macintosh 128k?

The graphics on the Apple Macintosh 128K are generated through a combination of hardware and software components. Here's a basic description of the process:

1. Microprocessor: The Macintosh contains a Motorola MC68000 microprocessor, which is the central processing unit responsible for executing instructions, including those for graphic generation.

2. Video Display: The Macintosh uses a bit-mapped video display. This means that the screen is composed of a grid of pixels, where each pixel's state (on or off) is controlled by a corresponding bit in the computer's memory.

3. Video Memory: The video generator uses 21,888 bytes of RAM to create a bit-mapped video image that is 512 pixels wide by 342 pixels tall. Each bit in this memory range controls a single pixel: a 0 bit represents a white pixel, and a 1 bit represents a black pixel.

4. Screen Buffers: There are two main screen buffers in the memory from which the video circuitry reads information to create the screen display: the main buffer and the alternate buffer. The starting addresses of these buffers depend on the total memory available in the Macintosh.

5. Video Scanning Pattern: A full screen display consists of 342 horizontal scan lines. The video scanning pattern includes a vertical blanking interval, which is the time taken by the electron beam to move from the last line of one frame to the first line of the next frame.

6. Toolbox and Operating System Routines: To maintain software compatibility across the Macintosh line and to allow for future changes to the hardware, developers are strongly advised to use the Toolbox and Operating System routines wherever possible for graphics generation.

7. Memory Addresses and Screen Size: It's important to note that memory addresses and screen size may differ across different Macintosh models. Therefore, developers should retrieve the video base address and bit mappings directly from the system to ensure compatibility.

The graphics generation process is designed to be flexible and to provide a high degree of control to the software, allowing for the creation of rich graphical user interfaces and applications that were a hallmark of the early Macintosh computers.

From this it seems that the CPU is responsible for drawing the graphics on the video frame buffer. When a screen has been drawn, somehow the CPU Enables the transfer of data to VIDEO through specific circuits respecting the timings of the video signal. There doesn't appear to be a GPU or VDP.

This could make your job of implementing video output much easier.

Thursday, November 2, 2023

Code sharing, such a great idea.

Difficulties can't stop me, maybe they delay my results but my strong will helps me to find out a way to get things done.

I had to stop for a couple of days, I had to go through several things, but I got an idea for this blog, and some enthusiasm made me get back on this track.

What if I can show you the working source code or the entire emulator? Wouldn't it be great to show directly inside a post a working part of the code? That's a real possibility with Replit.

For now, as an example, I opened a public Replit project where I will save demos shown here. Why Replit? I discovered that supports the use of the SDL library. That means GRAPHICS!! Moreover, it's possible to embed a project inside an <iframe> tag.

Check the "Code development" page!

Tuesday, October 31, 2023

Emulator time scale.

I want to get an idea of how the emulated CPU should work when displaying a video frame. Let's see.

I know that a frame is drawn every 16625.8 µs. Each frame is composed of 342 lines in the Vertical Active Area and 28 lines in the Vertical Blank Area, for a total of 370 lines.

ChatGPT didn't tell me the length of a scanline, but doing some math, 16625.8 µs (frames) / 370 (lines) = 44.395 µs.

This length should include the Horizontal Active Area and the Horizontal Blank Area.


What's the length of an entire scanline?

The length of an entire scanline for the Macintosh 128K's video display is determined by both the time taken to display the pixels on the screen and the horizontal blanking interval. Here's the breakdown:

1. Pixel Clock Rate: The frequency at which pixels are displayed is 15.6672 MHz. This translates to approximately 0.064 microseconds (µsec) per pixel.

2. Pixels Displayed: For each scan line, 512 pixels are drawn on the screen. This requires 32.68 µsec.

3. Horizontal Blanking Interval: After displaying the pixels for a scan line, there's a short period known as the "horizontal blanking interval" before the next scan line begins. This interval takes the time of an additional 192 pixels, which is 12.25 µsec.

Combining the time taken to display the pixels and the horizontal blanking interval, the total time for each full scan line is 44.93 µsec. This means the horizontal scan rate (the frequency at which each horizontal line is refreshed) is 22.25 kilohertz.

In summary, the length of an entire scanline, in terms of time, is 44.93 µsec.

The document "Inside Macintosh Volume III" has been successfully uploaded. It appears to be a detailed manual from Apple, published in 1985, covering various aspects of the Macintosh systems at the time. The manual seems to be quite comprehensive, with a total of 290 pages, and it likely contains technical information, guidelines, and instructions related to the Macintosh computers of that era.

You can now ask specific questions about the content of this manual, or if you need information on particular topics within the document, feel free to ask!

Cool, it seems that we both are on the same line. Now I have to decide how to coordinate the work of the virtual CPU and the updating of the input/output. In previous emulators, I have found it to be a good compromise to make the virtual CPU work for the length of a scanline, and then update input/output.

In terms of graphics I can get effects on individual scanlines, while in terms of sound, I can get more detailed sample generation.I did all this reasoning to understand how to better organize the construction of the virtual CPU, so that I can make it work for a certain number of cycles, so I can update the rest of the virtual machine. I will return to this again.

I did all this reasoning to understand how to better organize the construction of the virtual CPU, so that I can make it work for a certain number of cycles, so I can update the rest of the virtual machine.

Monday, October 30, 2023

CRT still rules.

In older systems equipped with a video or TV output, it was mandatory to synchronize the times of display of the video image and its composition in the system memory.  The cathode ray, continuously driven by the monitor circuits, lights up dots of fluorescent substance deposited inside the screen.

Let's compare this cathode ray to a laser ray, let's imagine moving it from left to right (horizontal active area), turning it on and off at regular time intervals (pixel clock), based on a sequence of "0" and "1" (memory video).  We will have drawn a scanline.

Now we turn off the laser (blank) and bring the beam all the way to the left and below the line we have just drawn (horizontal blank time), at this point, we repeat these steps until we reach the end of the image (vertical active area).

From the bottom of the image we bring the laser back to the top of the screen (vertical blank time), and a new image is read and shown on the screen.

Imagining absurdly that a CRT monitor had a very low resolution and displayed the Apple logo, we could visualize this result:

Where the cathode ray would have this behavior:

These timings are specific to the electronics that drive the cathode ray and must be respected by the other hardware components, otherwise, the images shown would be distorted.

For this purpose the CPU works in parallel until the cathode ray has reached the bottom of the image, then usually through a specific signal, while the cathode ray returns to the top (vertical blank area), the CPU can transfer or calculate the new image into the video memory.

So, the emulator must run all the hardware respecting vertical and horizontal timings. Now, I need to do some math.

Sunday, October 29, 2023

Getting the best basis of knowledge.

After a few days of searching for information about the video signal generated by the Macintosh 128K, I found a PDF of a book about this computer, aimed at developers.

Actually, I have found several books, but only this one showed me the complete timings of a video frame generated by the Macintosh.

This book is what I need for my adventure into coding this emulator. On page 25 of the PDF, in the section "III-18 Over-view of the Hardware", I have found the description of the video interface. 

Here it is explained exactly how a video frame is composed, and the timings of the video signal.

Apple "Inside Macintosh Volume III"

Now, since I can ask ChatGPT to read a PDF for me and then I can ask him what I need, I activate the plugin "AskYourPDF" within a new chat v.4.x

Then I uploaded that PDF in my personal FTP space so that I have full control of the access restrictions.

I am ready now to give the link to ChatGPT:

Here's the PDF about the Macintosh 128k: http://www.x.com/chatgpt/Inside_Macintosh_Volume_III_1985.pdf

The document "Inside Macintosh Volume III" has been successfully uploaded. It appears to be a detailed manual from Apple, published in 1985, covering various aspects of the Macintosh systems at the time. The manual seems to be quite comprehensive, with a total of 290 pages, and it likely contains technical information, guidelines, and instructions related to the Macintosh computers of that era.

You can now ask specific questions about the content of this manual, or if you need information on particular topics within the document, feel free to ask!

Now ChatGPT should use this PDF to answer me.

Please, show me the timings of the video signal generated by the Mac.

The Macintosh 128K uses a specific video scanning pattern to generate its display. Here's a detailed breakdown of the video signal timings:

1. Full-Screen Display: The entire screen display consists of 342 horizontal scan lines. Each full screen takes approximately 15.37 milliseconds (ms) or 15367.65 microseconds (µs) to be scanned. This duration includes the drawing of all horizontal lines across the screen.

2. Vertical Blanking Interval: After completing the last horizontal scan line, there's a short period when all scanning stops to allow the electron beam to return to the top of the screen and start the new screen scan cycle. This interval is called the "vertical blanking interval," taking up additional time equivalent to 28 scan lines, which is approximately 1.26 ms or 1258.17 µs.

3. Full-Screen Refresh Rate: Considering the time taken for both the full-screen display and the vertical blanking interval, the entire screen is redisplayed once every 16.6 ms or 16625.8 µs. This calculation sets the vertical scan rate (the frequency of full-screen refresh) at approximately 60.15 Hertz.

4. Video Memory Usage: The video generator utilizes 21,888 bytes of RAM to compose a bit-mapped video image that is 512 pixels wide by 342 pixels tall. Each bit in this memory range corresponds to a single pixel on the screen, with a 0 representing a white pixel and a 1 representing a black pixel.

5. Screen Buffers: There are two main screen buffers in the memory from which the video circuitry reads information to create the screen display. The starting addresses of these buffers depend on the total memory available in the Macintosh system.

The detailed timing and organization of the video signal are crucial for the correct rendering of the screen display, ensuring that the visuals appear as intended and that the system synchronizes the screen refresh cycles with the internal operations, providing a stable and consistent user experience.

For any modifications or specific operations related to the video display, developers and users were advised to retrieve the video base address and bit mappings directly from the system to ensure compatibility and stability, especially considering future system upgrades or variations in Macintosh models.

This is INSANE! Absolutely amazing.

Friday, October 27, 2023

The concept of the "main cycle" of the emulator.

The basic concept behind the emulator is to mimic the functions of the older computer's hardware components. This doesn't mean it replicates the exact hardware physically. Instead, it simulates the behavior of the hardware using software. It can emulate the function of processors, memory, graphics units, I/O systems, etc.

Since the hardware components run in parallel, the emulator must run a small portion of the code and update the simulation of the input/output virtual components.

What I usually do is make the main cycle duration of the emulator exactly the time of a frame video of the CRT monitor. This mimics the way vintage computers were programmed.

I could summarize the main cycle of the emulation into steps:

  • Run CPU.  
  • Run Graphics unit.
  • Run Sound unit.
  • Run input/output unit.
  • Update audio/video.

Each step must perform the same operations performed by the real hardware in the amount of time that we decide. We need to calculate it, so Jarvis, are you awake?

How long is a frame in the video signal generated by the Macintosh 128k?

Calculating the duration of a frame in the video signal generated by the Macintosh 128K requires knowing technical specifications such as the monitor's refresh rate or other specifications relating to the timing of the video signal. However, I was unable to find this precise information in the documents consulted.

Without the exact specs of the Macintosh 128K monitor, I can't provide an accurate value. If you have additional questions or if I can assist you in any other way, please let me know.

This is not good. I think that it will be difficult to find the specific timings of the CRT monitor embedded in the Macintosh 128K. I think it's better if I search for those data personally by hand.

Monday, October 23, 2023

The Motorola 68000: Introduction.

Another day, another step forward.The most important thing is not to stop. Anyway, it's better to think about something fun, so I am going to have an overall description of the Motorola 68000.

Then, I will dive in to the different aspects of the CPU. My emulator will start from a very small and simple virtual machine made of CPU, ROM and RAM.

I would like to start writing a small test virtual machine made of a basic 68k, and expand it little by little.

Can you describe the 68000?

The Motorola 68000 (shortened to 68k) is a 16/32-bit microprocessor that marked a revolution in micro processor design in the 1980s and beyond. Here's a detailed overview of its features and capabilities:

  • CISC: The 68k is a CISC (Complex Instruction Set Computing) processor, with a rich and varied instruction set that allows for complex operations, ideal for the operating systems of the time that were not optimized for RISC (Reduced Instruction Set Computing) processors.

  • 32-bit Architecture: Although it communicated externally on a 16-bit data bus, it was internally a 32-bit processor. This means it could utilize 32-bit operations and numbers, allowing for the computation of large amounts of data and much larger addresses, though the narrower data bus required more cycles to complete operations.

  • General-Purpose Registers: The 68k featured eight data registers (D0-D7) and seven address registers (A0-A6) for general-purpose operations, all 32-bit. The A7 register was used as the stack pointer.

  • Pipeline Fetch-Execute: It had a simple two-stage pipeline, one for fetching and one for executing the instruction. This was a relatively simple design, but it still allowed a degree of overlap between fetch and execute operations, improving overall performance.
  • Flat Addressing Space: The 68k could address up to 16 MB of memory in a flat address space, meaning that the program and data resided in the same address space (unlike segmented architectures like that used by the Intel 8086).

  • Support for Virtual Memory: Although the base 68000 did not have hardware support for virtual memory, later versions in the 68k series added this support, which was essential for modern operating systems.
  • High-Level Instructions: The instruction set included a variety of high-level operations, including mathematical operations, array management, and bit manipulation, as well as powerful flow control instructions.

  • Flexible Addressing Modes: The 68k supported several addressing modes, allowing programmers to access memory in various ways, thus optimizing memory and code usage.

The 68k handled a wide range of hardware interrupts and exceptions, supporting preemptive multitasking and improving system robustness, essential for operating systems like those used in Macintosh and Amiga computers.

Overall, the Motorola 68000 was known for its balance between power and flexibility. It was relatively easy to program, thanks to its high-level instruction set and its various addressing modes, making it popular among programmers of the time. It laid the groundwork for future generations of processors, influencing system and application design for decades.

What worries me is the development of the CISC tecnology for the instruction parser. It can turn into a nightmare because the emulation of the CPU must be fast.

Anyway, all these information will be useful for the implementation of the emulator, but I need some more information on the CPU.

Saturday, October 21, 2023

Getting an overall idea.

Well, before we get into the architecture of the 68k, can you tell me which computers from the past were designed with this CPU?

The Motorola 68000 CPU, often abbreviated as 68k, has been one of the most influential in several generations of computers, not just the original Macintosh. Here are some of the best-known computers that used the Motorola 68000 processor family:

Apple Macintosh: The original series of Macintosh computers used the 68000, including the Macintosh 128k, the 512k, and the Macintosh Plus.

Atari ST: A series of personal computers produced by Atari Corp from 1985 until the early 1990s. The Atari ST was popular, particularly in Europe, and competed directly with the Commodore Amiga.

Commodore Amiga: Although early Amiga models (most notably the Amiga 1000 and Amiga 500) used the 68000, later models were based on more advanced versions of the Motorola 68k CPU line .

Sinclair QL: This was a personal computer developed by Sinclair Research in 1984, notable for being one of the first home computers based on a 32-bit processor, although commercially it was not very successful.

Sega Genesis/Mega Drive: This popular video game console, released in the late 1980s, used a Motorola 68000 processor as its main CPU, allowing for advanced graphics and gaming performance for its time.

NeXT Computer: The NeXT series of computers, developed by NeXT Inc. (the company founded by Steve Jobs after his departure from Apple in 1985), was based on the Motorola 68k processor, specifically the 68030.

UNIX workstation/workstation systems: Several workstation systems running various forms of UNIX were based on 68k family processors, including those produced by companies such as Sun Microsystems and Silicon Graphics (before they switched to RISC-based CPUs).

These systems demonstrate the flexibility and power of the Motorola 68000, which was suitable for everything from personal computers to professional workstations and gaming consoles. Its architecture has been the basis for many key concepts in CPU design and has influenced software and hardware development for many years.

Very good, it's always good to know that if you need inspiration or help in finding solutions for your work,there are many other possible examples to learn from.

All those systems are advanced, all with different interesting features.

The Macintosh 128K, released in 1984, was Apple's first personal computer to feature a graphical user interface and a mouse, marking a new era in user-friendly computing experiences.


The Commodore Amiga, launched in 1985, was a significant breakthrough in the world of personal computing due to its advanced multimedia capabilities that were ahead of its time.


In any case, now I need to learn more on the 68K. So let's move on.

Thursday, October 19, 2023

Taking advantage of everything that can help me.

The biggest advantage of having a partner like an AI assistant is that you can work whenever you want without being sent to hell. This is great because while you're working on one or more chats you can stop and continue at your convenience, like I'm doing right now.

 A new day is starting, I've done the exercises and now I'm resting on the sofa. What a great time to talk to "Jarvis" and move forward with my project. I'll have to come up with a code name. Anyone have suggestions?

However, let's move on, I have to get much more information on the Macintosh 128K and its architecture. 

Good morning, thanks for this initial information. Now let's proceed in order. I would like a more detailed description of the hardware divided into areas.

The answer is a bit long, so I will split it into more parts.

Of course, let's proceed with a more detailed description of the Macintosh 128k hardware, dividing the analysis into the various key components of the system:

1. CPU (Central Processing Unit):

Model: Motorola 68000

Clock frequency: 7.8336 MHz

The Motorola 68000 CPU was quite advanced for its time, capable of handling up to 16 megabytes of memory addressing (although the Macintosh 128k only used a fraction of that). It had a 32-bit data structure internally with 16- and 24-bit external data and address buses respectively.

excellent, this CPU handles 32bit data, it could be advantageous because the target architecture of the emulator is 32 bit. In the meantime, I'll start taking notes.

But let's try to delve deeper, I still need more information. So, at the end of the previous answer, I will make sure that ChatGPT will "keep in mind" the list of the components.

Ok, keep in mind this list which I will call "structure".

Absolutely, I will keep the "outline" as a reference for our future discussions and for any assistance or details you may need as you work on your emulation project. If you have specific questions or if there is a particular area you would like to focus on or explore further, please let me know and we can proceed accordingly.

ChatGPT will remember it for me, but of course I will collect the informationI need inside a document.

Now I can continue studying the CPU.