Previous Thread
Next Thread
Print Thread
Page 1 of 15 1 2 3 14 15
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Good morning,

I am trying to write a driver from scratch and I have many doubts:
  • I do not know how to compile only the source I am working on. I followed the instructions but cannot compile especifically the part I want, something seems to be missing.
  • I do not know how to add LED devices into my driver. The computer I am trying to emulate has a diagnostics port whose values are read using a LED probe add-on. Due of the complexity of the computer, it is crucial for this diagnostics port to be readable during the development.
  • Under Windows, how could I generate the checksum hashes for the ROMs I want to include in the project?

I do know these are very noob questions, but I am already making an effort to understand C++ and I find MAME documentation is too complex for a newcomer. If you are asking yourselves why I am going through all the trouble with this, I let you know all this hassle is for bringing the first ever emulator for this forgotten machine - so forgotten it's not even in any dump or TO-DO list.

Thank you for your time and patience!

Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
If you don't understand C++, a MAME driver is not the ideal way to learn it, but I'll try to answer your questions.

When you add a completely new source file, the first time you compile with it you must include REGENIE=1 when doing the 'make' so that the build system will re-scan for new files. Also, don't forget to add the new driver to src/mame/mame.lst or MAME will say the driver doesn't exist when it does.

Are these individual LEDs, or a 7-segment display, or some other kind of LED display?

For hashes, a lot of people simply add fictional hashes like "12345678" the first time. When you try and run the driver, MAME will print the hashes it actually found and you can copy and paste those out from your command window.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I do understand C but C++ is not something in which I have had an excuse to deal with. I used to program web applications...

I'll take note on the REGENIE option. This will come useful indeed.

About the LEDs, any of both could be used. The diagnostics port per se expects the probe to be connected, but no probe for this machine has been found to this day. What I have is a homemade device which simply add eight LEDs. The only difference is having to interpret the outcoming signals or having them presented nicely without effort.

[video:youtube]
[/video]

I'll take also note for the hashes.

Thank you!

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
Originally Posted by jlopezm
About the LEDs, any of both could be used. The diagnostics port per se expects the probe to be connected, but no probe for this machine has been found to this day. What I have is a homemade device which simply add eight LEDs. The only difference is having to interpret the outcoming signals or having them presented nicely without effort.

If you want to treat it as a pair of 7-segment displays for convenience, the easiest thing to do would be to have two output digits:
Code
output_finder<2> m_diag_digits;

Ensure that they're initialized in your driver_device's constructor:
Code
m_diag_digits(*this, "digit%u", 0U)

To send an 8-bit value to them:
Code
m_diag_digits[0] = val & 0x0f;
m_diag_digits[1] = (val >> 4) & 0x0f;

To see how to display them using MAME's artwork system, refer to src/mame/layout/maxaflex.lay, and take note of the named "digit" element, and the two individual digits - "digit1" and "digit0" - that refer to it.

Give your .lay file an appropriate name and ensure it's in src/mame/layout/, and include the generated layout file as so:
Code
#include "datamaster.lh"

In the machine-configuration function, point the machine config at it:
Code
config.set_default_layout(layout_datamaster);

Build with REGENIE=1 once again, to ensure that the necessary layout-header is generated from the .lay that you created.

If you want to display each individual bit, there should be enough info above, while also referring to the maxaflex layout file, for you to intuit how to do that.

Last, but not least, it might speed up your development process by doing a single-driver build, and also using "lld" to link instead of the usual "ld". You do that like so:
Code
make SUBTARGET=myname SOURCES=src/mame/ibm/datamaster.cpp ARCHOPTS="-fuse-ld=lld" REGENIE=1

...and take the REGENIE=1 off once you've built. Re-add it if you add any new files.

Make sure that any new drivers are added to src/mame/mame.lst in the appropriate spot, and any new CPU cores or individual devices are added to the appropriate Lua scripts in scripts/src/.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Thank you very much for this information. I am, however, lost when dealing with the layout. I have updated my mame devices list and created the first commit into my private repository. You can find the new source in the following link.

The plan is to have a skeleton that runs the diagnostics steps correctly from the beginning of the work and we keep adding the required parts in the order marked by the tests. I think this way the emulator would self-verify itself.

I am sure I missed something, don't know what because I am still very green at it. Please, could anybody take a look at it?

Thank you very much and sorry for the hassle

Joined: Aug 2009
Posts: 1,285
Likes: 222
Very Senior Member
Very Senior Member
Joined: Aug 2009
Posts: 1,285
Likes: 222
1. Should go under `src/mame/ibm/system23.cpp`
2. `MACHINE_SKELETON` is a flag that doesn't exist in bleeding edge.
3. Needs a machine_config that describes what components your motherboard has.
4. `ROM_REGION(0x1800, "ros_unpaged", 0)` will throw a validation failure, what you map below is 0x4000 in length.

1 member likes this: jlopezm
Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
To be more explicit about point 3, do a Find In Files in src/mame/*.cpp for (machine_config &config), literally every machine has one, it's what specifies the actual hardware that existed for a machine.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Thank you very much for the insight.

1. Isn't the code already at this directory?
2. Removed the flag.
3. I don't understand this point.
4. Copy-paste issues. Corrected to 0x4000. I am examining both ibm6850.cpp and alphatpx.cpp as references.

Again, thank you for your assistance

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I will take a look for it. Thank you very much!

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Originally Posted by Kale
1. Should go under `src/mame/ibm/system23.cpp`
Hm... the source is at this directory, but it's true that it is not finding it for some reason. I have the impression that is what you intended to point out, right?

Again, thank you

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Code
$ make SUBTARGET=system23 SOURCES=ibm/system23.cpp ARCHOPTS="-fuse-ld=lld" -j20
GCC 11.2.0 detected
Linking system23.exe...
ld.lld: error: undefined symbol: driver_system23
>>> referenced by ../../../../mingw-gcc/obj/x64/Release/generated/mame/system23/drivlist.o:(driver_list::s_drivers_sorted)
collect2.exe: error: ld returned 1 exit status
make[2]: *** [system23.make:274: ../../../../../system23.exe] Error 1
make[1]: *** [Makefile:112: system23] Error 2
make: *** [makefile:1127: windows_x64] Error 2
It's strange. I have added the driver to mame.lst as required but it can't find it. Please, does anybody have any clues about it? Otherwise the source seems to be compiling correctly.

Sorry again for the hassle

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
Originally Posted by jlopezm
Code
$ make SUBTARGET=system23 SOURCES=ibm/system23.cpp ARCHOPTS="-fuse-ld=lld" -j20
GCC 11.2.0 detected
Linking system23.exe...
ld.lld: error: undefined symbol: driver_system23
>>> referenced by ../../../../mingw-gcc/obj/x64/Release/generated/mame/system23/drivlist.o:(driver_list::s_drivers_sorted)
collect2.exe: error: ld returned 1 exit status
make[2]: *** [system23.make:274: ../../../../../system23.exe] Error 1
make[1]: *** [Makefile:112: system23] Error 2
make: *** [makefile:1127: windows_x64] Error 2
It's strange. I have added the driver to mame.lst as required but it can't find it. Please, does anybody have any clues about it? Otherwise the source seems to be compiling correctly.

Sorry again for the hassle

When building, you need to provide the full path to the driver file: src/mame/ibm/system23.cpp

Regarding the machine_config function, refer to this file, it's one of the more straightforward and small drivers that actually displays something: https://github.com/mamedev/mame/blob/master/src/mame/skeleton/600cat.cpp

See the function at line 124? You need a function like that in your own driver, which configures the CPU and any other devices used by the system. Let's go over the one in 600cat.cpp together -

This is the function prototype. It always takes a reference to a machine_config, called config. It's no different from a function in C, it's just namespaced to the class that it belongs to: _600cat_state.
Code
void _600cat_state::_600cat(machine_config &config)
{

This configures the class member "m_maincpu", which you can see declared on line 51. It's a Hitachi HD6303R CPU, clocked at 4MHz.
Code
	HD6303R(config, m_maincpu, 4'000'000);

This tells our main CPU about the function used to configure its program-space address map.
Code
	m_maincpu->set_addrmap(AS_PROGRAM, &_600cat_state::mem_map);

These plumb various callbacks specific to the Motorola HD6303 to the appropriate functions in the driver class.
Code
	m_maincpu->out_p1_cb().set(FUNC(_600cat_state::p1_w));
	m_maincpu->out_p2_cb().set(FUNC(_600cat_state::p2_w));
	m_maincpu->out_p3_cb().set(FUNC(_600cat_state::p3_w));
	m_maincpu->out_p4_cb().set(FUNC(_600cat_state::p4_w));
	m_maincpu->out_sc2_cb().set(FUNC(_600cat_state::sc2_w));
	m_maincpu->out_ser_tx_cb().set(FUNC(_600cat_state::ser_tx_w));

This configures the class member "m_screen", which you can see declared on line 53. We configure it as an LCD-type screen, since this was a handheld device with a simple LCD display.
Code
	SCREEN(config, m_screen, SCREEN_TYPE_LCD);

...with a (guessed) 50Hz refresh rate, a (guessed) 2500-microsecond vertical blanking interval, and a resolution of 120x36.
Code
	m_screen->set_refresh_hz(50);
	m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
	m_screen->set_size(120, 36);

This sets the screen to not have vertical or horizontal blanking periods, due to being an LCD. This means that my call to "set_vblank_time" above is actually an error on my part and could potentially be removed.
Code
	m_screen->set_visarea_full();

Every screen needs to have its contents painted, right? Usually, this would refer to a function in the driver class itself. But since our screen is driven by the LCD controller (see below), we point it at the appropriately-named member function provided by the LCD controller device.
Code
	m_screen->set_screen_update(m_lcdc, FUNC(hd44780_device::screen_update));

This points the screen at our palette device, in order to have a more realistic-looking LCD palette.
Code
	m_screen->set_palette(m_palette);

This configures the class member "m_palette", which you can see declared on line 54. palette_device is a device which, as the name implies, is used to provide a palette, for the (many) systems that didn't use direct RGB. The palette is initialized by a function in our driver class called "lcd_palette", and the palette is 3 entries long.
Code
	PALETTE(config, m_palette, FUNC(_600cat_state::lcd_palette), 3);

This configures the class member "m_lcdc", which you can see declared on line 52. It is a Hitachi HD44780 LCD controller chip. The implementation is in src/devices/video/hd44780.h (and .cpp). Since we don't know the actual clock used, we go with a relatively safe default of 270kHz.
Code
	HD44780(config, m_lcdc, 270'000); // TODO: clock not measured, datasheet typical clock used

The LCD is 4 lines tall and 20 characters wide.
Code
	m_lcdc->set_lcd_size(4, 20);

The HD44780 implementation uses a function delegate so that drivers using it can have exact control over how the character pixels are drawn, oriented, and so on. So we point it at our driver's function, lcd_pixel_update, which is declared at line 40 and defined starting at line 58.
Code
	m_lcdc->set_pixel_update_cb(FUNC(_600cat_state::lcd_pixel_update));

This system also has a Dallas DS1643 real-time clock, so at this point in the machine configuration function, we configure the class member "m_rtc", which was declared on line 55 in our driver class declaration.
Code
	DS1643(config, m_rtc);
}

2 members like this: MrBogi, jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I rechecked with 600cat.cpp and understood what was I doing wrong. I committed some stupid errors, such as naming the namespace and declaring the driver inside it. I get it compiled into an application with the main menu and the only option is this driver. It is a big step for the first day.
I have updated the checksums, but it just doesn't recognize them. I guess I have to tinker with it a little more.

Thank you!

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Yesterday I managed to get the driver "working". It now gets stuck during the tests programmed in ROM. With the information I had beforehand and the result of running the program with the -debug flag I found that port A of the 8255 that manages the keyboard is used to test the CPU and the bus. It stucks just two instructions before writing to the LED display for the first time.

I took as an example the IBM Displaywriter (ibm6580.cpp), which also carries this component. At the time being I have tried by creating a private variable that holds the value of the register, then read and write to them using getters/setters and finally setting such methods as callbacks of the 8255. However, it seems that reading from the port always returns 0xff, as if nothing was assigned of that port (or tristated?). Any experience with the usage of this component?

Thank you in advance

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
Originally Posted by jlopezm
I took as an example the IBM Displaywriter (ibm6580.cpp), which also carries this component. At the time being I have tried by creating a private variable that holds the value of the register, then read and write to them using getters/setters and finally setting such methods as callbacks of the 8255. However, it seems that reading from the port always returns 0xff, as if nothing was assigned of that port (or tristated?). Any experience with the usage of this component?

It's impossible to guess just based on a verbal description, show how you've hooked up the port callbacks. Either put the current revision on gist.github.com and post a link, or just commit what you have to your existing branch.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Originally Posted by Just Desserts
It's impossible to guess just based on a verbal description, show how you've hooked up the port callbacks. Either put the current revision on gist.github.com and post a link, or just commit what you have to your existing branch.
My bad. Sorry, I forgot. I will try to be more careful in the future.

system23.cpp at github

Joined: Apr 2012
Posts: 347
Likes: 66
Senior Member
Senior Member
Joined: Apr 2012
Posts: 347
Likes: 66
You only mapped your PPI to a single address, so:
Code
map(0x4c, 0x4c).rw(m_ppi_kbd, FUNC(i8255_device::read), FUNC(i8255_device::write));
should be:
Code
map(0x4c, 0x4e).rw(m_ppi_kbd, FUNC(i8255_device::read), FUNC(i8255_device::write));


BBC Model B, ATPL Sidewise, Acorn Speech, 2xWatford Floppy Drives, AMX Mouse, Viglen case, etc.
3 members like this: Just Desserts, exidyboy, jlopezm
Joined: Aug 2009
Posts: 1,285
Likes: 222
Very Senior Member
Very Senior Member
Joined: Aug 2009
Posts: 1,285
Likes: 222
PPI is 4 addresses so:
Code
map(0x4c, 0x4f).rw(m_ppi_kbd, FUNC(i8255_device::read), FUNC(i8255_device::write));

(ppi offset $3 is for mode select and tristate of port C)

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
At the end this was the solution that solved my problem. So the emulated Datamaster now passes the first test and assigns the LED display for the first time. It now gets stuck in the second test, but I will investigate the issue.
I have seen the 7-segment LED display is directly driven by the values I send to them. Is there some sort of table/array to transform an hexadecimal number into 7-segment display code?

Thank you very much!

Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
You will need to provide the pattern yourself. Here's an example:

Code
void submar_state::submar_led_w(offs_t offset, uint8_t data)
{
	// 7447 (BCD to LED segment)
	static constexpr uint8_t _7447_map[16] =
			{ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x58,0x4c,0x62,0x69,0x78,0x00 };

	// 2 digits per write. port 4: time, port 5: score
	m_digits[((offset << 1) & 2) | 0] = _7447_map[data >> 4];
	m_digits[((offset << 1) & 2) | 1] = _7447_map[data & 0x0f];
}

(from mwsub.cpp)

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Originally Posted by Duke
You will need to provide the pattern yourself. Here's an example:

(from mwsub.cpp)

That's what ended doing. Now it displays all hex digits.


By the way, now I am struggling with RIM and SIM instructions and its corresponding SID and SOD data lines. I suspect they are tied in the hardware, but in my partial schematics I did not note their state. However, judging for the code in the diagnostics area they should.

I have added the following:

int system23_state::sid_r()
{
return sid_sod_connection;
}

void system_23_state::sod_w(int state)
{
sid_sod_connection = state;
}


and of course I have set the callbacks.

maincpu.in_sid_func().set(FUNC(system23_state::sid_r));
maincpu.out_sod_func().set(FUNC(system23_state::sod_w));


Now, for some reason, genie.exe fails to find my driver again.

Last edited by jlopezm; 12/30/24 09:21 AM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
By assigning a hard-coded value when reading SID, I managed to get to test four. Test three doesn't seem to exist. I guess it's time to add RAM into the machine, however it will be complicated and will require some help as it is the first time I do it.

There are four amounts of RAM obtained by five different configurations.
  • 32KB - A single 32KB board
  • 64KB - Two 32KB boards
  • 64KB - A single 64KB board
  • 96KB - A 64KB board and a 32KB one
  • 128KB - Two 64KB boards


I know the amount of RAM can be configurable. How could I do it this way?

Thank you very much!

Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
You can look up drivers using the ram_device, however I would get the basic driver going first and after it's working add optional features like configurable ram expansions.

Joined: Jan 2012
Posts: 1,191
Likes: 17
R
Very Senior Member
Very Senior Member
R Offline
Joined: Jan 2012
Posts: 1,191
Likes: 17
Great progress J.! Congratulations!

Robert


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
Seconding what Duke said: I usually start with a fixed amount of RAM and make it configurable later once it's at least minimally working.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
The problem is how memory is structured. The system has 16KB of RAM (possibly VRAM) at 0x8000-0xbfff and then a bank of paged ram at 0xc000-0xfff. The computer expects a minimum of 32KB to start operation. The amount is detected by software with the tests.

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
Originally Posted by jlopezm
The problem is how memory is structured. The system has 16KB of RAM (possibly VRAM) at 0x8000-0xbfff and then a bank of paged ram at 0xc000-0xfff. The computer expects a minimum of 32KB to start operation. The amount is detected by software with the tests.

That makes it much less of a problem, actually.

Map a fixed 16 kilobytes from 0x8000 to 0xbfff, then add a required_memory_bank member to your driver class, map it to 0xc000-0xffff, and in your driver class's machine_start function-override, configure the appropriate number of entries - for now, one - according to the documentation here: https://docs.mamedev.org/techspecs/memory.html#banks-memory-bank.

1 member likes this: R. Belmont
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I will test it later today. However I think I am doing something wrong with the fixed 16kb segment too, as it seems not to be passing its part of the test.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I managed to find why test 04 was failing. In the first place, I had misconfigurated the memory. Last but not least, after all the memory tests are performed, lecture is done of port at 2eh. This input port wasn't controlled and still haven't found what it is on the board (other than port C of a 8255). The value was compared and, as it was ffh it was found to be incorrect. I applied a patch in order to make it advance to test 05 while such port is being studied.

The diagnostics routines force me to a certain order. Next one is video output and will require a 8275+8257 to achieve it, plus all the shift logic for the character representation. I imagine this may be one of the most complex parts, if I saw correctly in the other emulators. Video generation uses to be one of the most custom features each system has.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Hello again,

I am trying to set up the 8257 DMA for video generation, but I am having some issues when configuring it. The code is in my repo, as always; could you take a look into it, please?
When it is configured and with no errors the 8275 will be added into the mix. I will require some help then to configure the screen and the video generation that writes into it.

Thank you in advance!

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have also taken as a reference some terminal from microbee as it also has the 8257+8275 duet in them. I am having the following errors but no clue on how to solve them and I am stuck.

Code
ld.lld: error: undefined symbol: i8275_device::i8275_device(machine_config const&, char const*, device_t*, unsigned int)
>>> referenced by libmame_system23.a(system23.o):((anonymous namespace)::system23_state::system23(machine_config&))

ld.lld: error: undefined symbol: I8257
>>> referenced by libmame_system23.a(system23.o):(.refptr.I8257)

ld.lld: error: undefined symbol: vtable for device_finder<i8275_device, true>
>>> referenced by libmame_system23.a(system23.o):(.refptr._ZTV13device_finderI12i8275_deviceLb1EE)

ld.lld: error: undefined symbol: vtable for device_finder<i8257_device, true>
>>> referenced by libmame_system23.a(system23.o):(.refptr._ZTV13device_finderI12i8257_deviceLb1EE)

ld.lld: error: undefined symbol: i8275_device::write(unsigned int, unsigned char)
>>> referenced by libmame_system23.a(system23.o):(.refptr._ZN12i8275_device5writeEjh)

ld.lld: error: undefined symbol: i8275_device::read(unsigned int)
>>> referenced by libmame_system23.a(system23.o):(.refptr._ZN12i8275_device4readEj)

ld.lld: error: undefined symbol: i8257_device::write(unsigned int, unsigned char)
>>> referenced by libmame_system23.a(system23.o):(.refptr._ZN12i8257_device5writeEjh)

ld.lld: error: undefined symbol: i8257_device::read(unsigned int)
>>> referenced by libmame_system23.a(system23.o):(.refptr._ZN12i8257_device4readEj)

Please, could you take a look into it and tell me what I'm doing wrong (or maybe what I am not doing)? My code is at my repo at github.

Thank you in advance!

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
Remember to REGENIE=1 if you are doing a single-driver compile and have added a device to your driver that previously was not there.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I am having problems with constructing the 8275. Looking at the microbee terminal, it does not declare its 8275 as required, but instantiates it directly in the constructor. Should I do the same thing?

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
It depends on whether you're going to need to directly call member functions of the device in any of your read/write-handler functions or function callbacks.

What a "finder" is - required_device<T> or optional_device<T> - really is is a form of smart pointer that looks up a device in the running machine's tree of instantiated devices, and enforces type safety.

For example, if in the machine-configuration function a wd33c93_device is instantiated with the tag "scsi", and the driver class has a required_device<cpu_device> member which is provided the tag of "scsi" - remember those strings in the constructor initializers for the required devices? - then MAME will punt a validation error.

If you're not going to need to directly call member functions on the device, then it can be instantiated purely in the machine-configuration function as microb.cpp does. An instance of the device will still be created and added to the device tree with the specified tag - in microb's case, "crtc".

If it were desired, a required_device<i8275_device> m_crtc could be added to the declaration of the microb_state class, with a constructor initializer of m_crtc(*this, "crtc"), at which point this:
Code
	i8275_device &crtc(I8275(config, "crtc", 1'620'000));
	crtc.set_screen("screen");
	crtc.set_character_width(8);
	crtc.set_display_callback(FUNC(microb_state::draw_character));
	crtc.irq_wr_callback().set_inputline(m_maincpu, I8085_RST65_LINE);
	crtc.drq_wr_callback().set(m_dmac, FUNC(i8257_device::dreq2_w));

Would become this:
Code
	I8275(config, m_crtc, 1'620'000);
	m_crtc->set_screen("screen");
	m_crtc->set_character_width(8);
	m_crtc->set_display_callback(FUNC(microb_state::draw_character));
	m_crtc->irq_wr_callback().set_inputline(m_maincpu, I8085_RST65_LINE);
	m_crtc->drq_wr_callback().set(m_dmac, FUNC(i8257_device::dreq2_w));

Unless you already know in advance that you're not going to be calling any member functions, I consider it good practice to have a finder for each device. String-based lookups at runtime can be slow, and with your overall level of experience with the codebase, you most likely are not going to be in a position of knowing in advance which functions are called once on machine construction, and which are going to be called often.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have solved the issues with the constructor. I decided to use finders and managed to write it up in a way that it doesn't report an error for that. Still, even after REGENIE=1 I am getting the errors stated previously. Apparently it is reporting that cannot fing methods for accessing its registers? It confuses me a little.

In any case, thank you for your help

Joined: Aug 2009
Posts: 1,285
Likes: 222
Very Senior Member
Very Senior Member
Joined: Aug 2009
Posts: 1,285
Likes: 222
A common workaround is to save without any mods the reported linker errors, in your case `src/devices/video/i8275.cpp` / `i8275.h` and `src/devices/machine/i8257.cpp` / `i8257.h` to force compiling those, the alternative is make clean and recompile from scratch.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Thank you. I now have the work of setting the display and this kind of stuff... I will notify the progress.

1 member likes this: R. Belmont
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Good. I have managed to get a black screen - no character is drawn yet to screen. I have looked at the source of the microbee terminal but it confuses me more than anything. I have also lost sight of the seven-segment displays. I think it is time to rearrange the layout file.

Meanwhile, could anybody with experience in the video generation explain me how to deal with it, please? Especially when it's with a 8275 or a derivative, that would be really helpful.

Thank you very much for your patience!

EDIT:

No matter what I do with the layout file, I am not getting the seven segment displays back.
The layout file is at github.

Last edited by jlopezm; 01/03/25 04:22 PM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
I think that when you add the screen it "changes the coordinate system" to accommodate everything that is now displayed. Your width for the 7 segments are less than a pixel wide, adjust the width to something like 7 and height 10.

Last edited by Golden Child; 01/03/25 06:39 PM.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Thank you. I rechecked and corrected this issue. Now I have recovered the seven segment displays. Now it's time to check why it halts again. Screen is activated at test 05 but not written until test 07 so I will require them until then.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
you might try hardcoding the pixel values like the microb just to see if that's the problem

1 member likes this: jlopezm
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
you may be missing a line to set this:
(looking at the microb)

crtc.drq_wr_callback().set(m_dmac, FUNC(i8257_device::dreq2_w));

and also the irq line

Last edited by Golden Child; 01/03/25 11:53 PM.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Thank you very much! I am currently investigating the board in order to find those signals.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
After some time examining the board I reached a via in near the CPU, but the trace was lost. Then I saw J1 between that via and another one. When tracing that second via I reached the 8085's RST5.5 pin. So the 8275 asserts RST5.5 when the jumper is bridged. Maybe I should do this during development...

By the way, what is the correct way to add a jumper?

Thank you in advance!

EDIT:

I have found that the DMA request line is the result of ANDing both the 8275 DMA Request and the DMA's channel 2 acknowledge signal. What would be the best way to handle this behaviour in the code?

Again, thank you very much.

EDIT 2:

Could it be that MAME does not support breakpoints with multi-BIOS systems? I have added an alternate BIOS and at the same time I have lost the capability to add breakpoints.

EDIT 3:

Regarding jumpers, I understand that the way most are are created is as soft jumpers, and this raises two questions. The first one, how would I create some equivalent of a hard switch in which a signal is interrumped? The second one, regarding soft switches, how could I define one that is read through a 8255 PPI?

Thank you in advance

Last edited by jlopezm; 01/04/25 05:35 PM.
Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
Originally Posted by jlopezm
I have found that the DMA request line is the result of ANDing both the 8275 DMA Request and the DMA's channel 2 acknowledge signal. What would be the best way to handle this behaviour in the code?

ANDing? Not ORing? I'm going to assume those signals are active low, possibly with a pull-up resistor then.

The underutilized way to handle that in MAME is with an INPUT_MERGER_ALL_HIGH() device. That lets you wire multiple outputs from other devices into the one device and its output will be the logical AND of all of the inputs. There aren't a lot of examples of it, but I use it for the I2C data line in src/mame/apple/powermacg3.cpp around line 177.

Quote
Could it be that MAME does not support breakpoints with multi-BIOS systems? I have added an alternate BIOS and at the same time I have lost the capability to add breakpoints.

MAME absolutely supports breakpoints in multi-BIOS systems. What happens when you add a breakpoint?

Quote
Regarding jumpers, I understand that the way most are are created is as soft jumpers, and this raises two questions. The first one, how would I create some equivalent of a hard switch in which a signal is interrumped? The second one, regarding soft switches, how could I define one that is read through a 8255 PPI?

Thank you in advance

Can you clarify exactly what this jumper is? Is it user-configurable, or fixed at the factory?

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
m_dmac->out_hrq_cb().set(FUNC(dmac_hrq_w));

you might need a system23_state::dmac_hrq_w qualifier to get it to compile, I thought I'd compile it myself to follow along

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Yes, it's ANDed and the signals are active-low. Actually it's NOT NANDed... I will take a look into that method of yours, thank you.

By the way, I solved the issue with breakpoints. Somehow it was related with the name of the ROM region...

I have problems when accessing this site. Sometimes I am not able to access it for about a day. Is there something going on?

Again, thank you very much!

EDIT:

The jumpers selecting the language are DIP switches, while the one enabling interrupt 5.5 is an unsoldered bridge marked as J1. I don't know its state in older versions of this computer.

Wenever I try to use INPUT_PORTS_START it won't compile even if I call those ports.

Again, thank you!

Last edited by jlopezm; 01/06/25 10:35 AM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I already have this line. However this does not do anything. You see, the 8275 is issued the enable interrupt command, and the interrupt flag from the CRTC is checked by the CPU using polling. It attempts it I think that 4 or 5 times, but the interrupt request flag is never asserted. I'm starting to think that this is an issue with the emulated component. If that's so, unfortunately the development of my driver will be halted until the issue is solved.

Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
Enable logging for the 8275 (uncomment #define VERBOSE 1), then check the log if the screen is configured correctly.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Soft reset
[:crtc] I8275 Command a0
[:crtc] I8275 Enable Interrupt


This is what I get in my log console. I imagine it should work straightforward, at least in real hardware it does... The thing is the computer just wants to detect if the CRTC is defective. In the emulated part it does not respond as it expects, so it decides it is defective and hangs.

Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
"Enable interrupt" would be an unusual first command. Usually systems reset the CRTC and then program the screen parameters. Until valid screen parameters haven't been programmed there won't be an interrupt.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
That should be what could be considered logical. However, it may not be that way. My dumps are from a machine I own, it passes all the tests and works. Maybe an undocumented behaviour of the 8275?

EDIT:
Could it be a custom 8275 and come presetted?

Last edited by jlopezm; 01/06/25 01:05 PM.
Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
Or maybe your system thinks it's doing a warm boot instead of cold boot and skips initialization.

If you own the system then you could attach a logic probe to the 8275 and see what exactly gets written to it to verify your emulated program flow.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
No, there is no option to warm boot this computer. It always does its checks and initializations.

I have taken a look at the code and it really looks like an initialization of the device is done, so it doesn't seem to be a custom part fortunately. However such initialization takes place after the interrupt enable command is issued and the test is performed. So it never takes place in the emulator. This should confirm some kind of undocumented behaviour of the 8275...

If I were to test this, how should I do it? I have no more 8275 other than the one installed in the Datamaster. Maybe writing an eprom to test only that part and output the result of the status port of the 8275 into the diagnostics port?

Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
Looking at the datasheet, it says: "HRTC and VRTC timing are random on power-up.". So it's possible that you will get an interrupt even without configuring any parameters. This isn't currently handled by the 8275 device and would need to be added (if true).

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
So do I do bring an issue to mame developers? I should do it from Github, right?

It seems that I will remain stuck on test 5 for a while. While I am in this deadlock, I could try to improve the code and add the dip switches.

EDIT:
Done

Last edited by jlopezm; 01/06/25 02:21 PM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
well you can put an empty input ports in

static INPUT_PORTS_START( system23)
INPUT_PORTS_END

// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME
COMP( 1981, system23, 0, 0, system23, system23, system23_state, empty_init, "IBM", "IBM System/23 Datamaster", MACHINE_NO_SOUND | MACHINE_NOT_WORKING)


and add it to your COMP line

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
All this time I was missing adding it to the COMP line... embarrassing. Thank you very much!

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I think on making a pull request so they include this driver as-is so it gives them a way to test the 8275 behaviour that needs to be implemented. What's your opinion?

EDIT:

Already done, but I guess this process will take a lot of time. If I were to alter the device driver myself, where should I initialize the registers with dummy data so the component gets into a free-running state? It is important both to settle this and at the same time enable it to produce interrupts. The involved file is the following:

https://github.com/RetroAND/mame/blob/master/src/devices/video/i8275.cpp

Last edited by jlopezm; 01/06/25 07:04 PM. Reason: Added link to resource
Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
Just don't initialize it with dummy data, initialize it with something that makes a little sense. Get the values from any working driver with the same component. They're as probable as anything else, and it avoid improbable extreme cases where the system actually wouldn't have booted.

1 member likes this: jlopezm
Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
Why not use something official?

"Intel Application Note: CRT Terminal Design Using The Intel 8275 and 8279"
https://mark-ogden.uk/files/intel/p...he%20Intel%208275%20and%208279-Nov77.pdf

Page 45: Screen param bytes 1 to 4. Those should define a valid display.

Alternatively use the values your system would program anyway.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
@Olivier @Duke Thank you very much.

I will use the Intel application note to initialize it. Now, should I do it on the constructor or at the machine_start method?

Thank you in advance!

Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
neither? In the device_start of the 8275

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I meant the device_start, sorry.

So it should be as follows:

//preinitialize the device with valid data (in real hardware parameters initialize to random)
m_param[REG_SCN1] = 0x4f;
m_param[REG_SCN2] = 0x58;
m_param[REG_SCN3] = 0x89;
m_param[REG_SCN4] = 0xd9;


But I feel there is something missing...

In any case, thank you very much!

EDIT:

I had to call recompute_parameters and I got the cursor into the screen!

Thank you all the involved!

EDIT 2:

Okay. Now it halts on the same test under different circumstances. Now it is searching for a light pen? (checking the status register & 0x10). I think I have to research a bit more the board.

Thank you again!

Last edited by jlopezm; 01/07/25 11:44 AM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
I did some mangling of the 8275 and it was able to do some further initialization:

some printfs to help:

LOG("I8275 Command %02x\n", data);
printf("i8275 command=%x context=%s\n",data, machine().describe_context().c_str());

LOG("I8275 Parameter %02x\n", data);
printf("i8275 param=%x data=%x context=%s\n",m_param_idx, data, machine().describe_context().c_str());



i8275 command=a0 context=':maincpu' (05AB)

a0 = enable interrupts

i8275 command=0 context=':maincpu' (05CE)
i8275 param=0 data=4f context=':maincpu' (05D2)
i8275 param=1 data=57 context=':maincpu' (05D6)
i8275 param=2 data=cd context=':maincpu' (05DA)
i8275 param=3 data=59 context=':maincpu' (05DF)
i8275 command=80 context=':maincpu' (3986)
i8275 param=4 data=0 context=':maincpu' (3989)
i8275 param=5 data=0 context=':maincpu' (398C)
i8275 command=23 context=':maincpu' (05E8)
i8275 command=0 context=':maincpu' (05CE)
i8275 param=0 data=4f context=':maincpu' (05D2)
i8275 param=1 data=57 context=':maincpu' (05D6)
i8275 param=2 data=cd context=':maincpu' (05DA)
i8275 param=3 data=59 context=':maincpu' (05DF)
i8275 command=80 context=':maincpu' (3986)
i8275 param=4 data=0 context=':maincpu' (3989)
i8275 param=5 data=0 context=':maincpu' (398C)
i8275 command=23 context=':maincpu' (05E8)
i8275 command=0 context=':maincpu' (05CE)

0 = reset

i8275 param=0 data=4f context=':maincpu' (05D2)
i8275 param=1 data=57 context=':maincpu' (05D6)
i8275 param=2 data=cd context=':maincpu' (05DA)
i8275 param=3 data=59 context=':maincpu' (05DF)
i8275 command=80 context=':maincpu' (3986)
i8275 param=4 data=0 context=':maincpu' (3989)
i8275 param=5 data=0 context=':maincpu' (398C)
i8275 command=23 context=':maincpu' (05E8)

23 = display start

i8275 command=0 context=':maincpu' (05CE)
i8275 param=0 data=4f context=':maincpu' (05D2)
i8275 param=1 data=57 context=':maincpu' (05D6)
i8275 param=2 data=cd context=':maincpu' (05DA)
i8275 param=3 data=59 context=':maincpu' (05DF)
i8275 command=80 context=':maincpu' (3986)

80 = set cursor position

i8275 param=4 data=0 context=':maincpu' (3989)
i8275 param=5 data=0 context=':maincpu' (398C)
i8275 command=23 context=':maincpu' (05E8)

(oh... didn't see all the replies on the next page)


as far as I can see, the 8275 won't set that LP status bit unless lpen_w gets called

Last edited by Golden Child; 01/07/25 01:04 PM.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Sorry for the delay. For some reason the server keeps me out for some time nearly every day.

I have traced the light pen circuit. I cannot post pictures here, but I have posted it at VCFed. I still have to determine the frequency at which the latch is updated, though.

Being a noob at MAME, how would this circuitry be emulated?

Thank you in advance!

EDIT:

I placed the following code at I8275_DRAW_CHARACTER_MEMBER( system23_state::display_pixels ) at system23.cpp but it never gets asserted.

if (BIT(attrcode, GPA0) && BIT(attrcode, GPA1))
{
m_crtc->lpen_w(ASSERT_LINE); //hack to test the light pen at test 05
LOG("Sytem/23: Light pen asserted\n");
}
else
{
m_crtc->lpen_w(CLEAR_LINE);
}


Then I found that apparently the 8275 driver does not support LA0 and LA1. They are defined at i8275.h but there are no mention of them at the driver itself. I guess I have to study where how they operate and then include them.

Last edited by jlopezm; 01/08/25 12:52 PM. Reason: Added code
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
It seems to want very specific values from the light pen:

case CMD_READ_LIGHT_PEN:
LOG("I8275 Read Light Pen\n");
m_param[REG_LPEN_COL] = 0x49;
m_param[REG_LPEN_ROW] = 0x17;
m_param_idx = REG_LPEN_COL;
m_param_end = REG_LPEN_ROW;
break;

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
The problem is that the emulator does not trigger the strobe. I placed the trigger at the method that draws a character because that's a place where all the parameters I need are present. But maybe it's not the correct place to do so... Basically, it asserts the line always that either the actual light pen or the test circuit register a low value, and the test circuit produces a low value always that GPA0 and GPA1 are both high. In order to simplify, I left the light pen out of the equation.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
well, if you put a bunch some printfs in, the attributes look like this, but it doesn't seem to show any GPA0 or GPA1 that I can tell

printf("x=%x y=%x attrcode=%x\n",x,y,attrcode);

x=200 y=140 attrcode=0
x=208 y=140 attrcode=0
x=210 y=140 attrcode=0
x=218 y=140 attrcode=0
x=220 y=140 attrcode=0
x=228 y=140 attrcode=0
x=230 y=140 attrcode=0
x=238 y=140 attrcode=0
x=240 y=140 attrcode=0
x=248 y=140 attrcode=0
x=250 y=140 attrcode=0
x=258 y=140 attrcode=0
x=260 y=140 attrcode=0
x=268 y=140 attrcode=0
x=270 y=140 attrcode=0
x=278 y=140 attrcode=0
x=0 y=141 attrcode=2
x=8 y=141 attrcode=2
x=10 y=141 attrcode=2
x=18 y=141 attrcode=2
x=20 y=141 attrcode=2
x=28 y=141 attrcode=2
x=30 y=141 attrcode=2
x=38 y=141 attrcode=2
x=40 y=141 attrcode=2
x=48 y=141 attrcode=2
x=50 y=141 attrcode=2
x=58 y=141 attrcode=2
x=60 y=141 attrcode=2
x=68 y=141 attrcode=2
x=70 y=141 attrcode=2
x=78 y=141 attrcode=2
x=80 y=141 attrcode=2
x=88 y=141 attrcode=2
x=90 y=141 attrcode=2

1 member likes this: jlopezm
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
ok, making a couple of modifications to 8275

Code
std::pair<uint8_t, uint8_t> i8275_device::char_from_buffer(int n, int sx, int rc, int lc, int &end_of_row, int blank_row)
{
	uint8_t data = BIT(end_of_row, n) ? 0 : m_buffer[!m_buffer_dma][sx];
	uint8_t attr = m_field_attr;
	int lineattr = 0;


	if ((data & 0xc0) == 0x80)
	{
		// field attribute code
		m_field_attr = data & (FAC_H | FAC_B | FAC_GG | FAC_R | FAC_U);
	
		if (m_field_attr & FAC_GG) printf("GG n=%x\n",n);              // so we are getting GG bits here, if so print something


		if (!visible_field_attribute())
		{
			attr = m_field_attr;
			data = m_fifo[!m_buffer_dma][m_fifo_idx_out];

			m_fifo_idx_out++;
			m_fifo_idx_out &= 0xf;

			if (BIT(blank_row, n))
				attr |= FAC_B;
			else if (!(m_char_blink < 32))
				attr &= ~FAC_B;
			if (lc != underline())
				attr &= ~FAC_U;
		}
		else
		{
			// simply blank the attribute character itself
			attr = FAC_B;
			attr |= (data & FAC_GG);                                             //     pass through the FAC_GG bits
		}
	}



and add a printf to DRAW_CHARACTER_MEMBER

Code

		if (BIT(attrcode, GPA0) || BIT(attrcode, GPA1)) printf("GPA0 GPA1 x=%x  y=%x attrcode=%x\n",x,y,attrcode);

		if (BIT(attrcode, GPA0) && BIT(attrcode, GPA1))
		{
			m_crtc->lpen_w(ASSERT_LINE);				//hack to test the light pen at test 05
			LOG("Sytem/23: Light pen asserted\n");
		}
		else
		{
			m_crtc->lpen_w(CLEAR_LINE);




and a prinf in scanline_tick

Code
		for (int sx = 0; sx < characters_per_row(); sx++)
		{
			int n = 0;
			uint32_t charcode = 0;
			uint32_t attrcode = 0;

			for (i8275_device *crtc = this; crtc != nullptr; crtc = crtc->m_next_crtc, n++)
			{
				auto [data, attr] = crtc->char_from_buffer(n, sx, rc, lc, end_of_row, blank_row);

				if (attr & FAC_GG) printf("CHARFROMBUFFER GG n=%x sx=%x  rc=%x  lc=%x\n",n,sx,rc,lc);

				charcode |= uint32_t(data) << (n * 8);
				attrcode |= uint32_t(attr) << (n * 8);
			}

GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=0
GPA0 GPA1 x=1e0 y=142 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=0
GPA0 GPA1 x=1e8 y=142 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=1
GPA0 GPA1 x=1e0 y=143 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=1
GPA0 GPA1 x=1e8 y=143 attrcode=e
i8275 command=60 context=':maincpu' (0611)
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=2
GPA0 GPA1 x=1e0 y=144 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=2
GPA0 GPA1 x=1e8 y=144 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=3
GPA0 GPA1 x=1e0 y=145 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=3
GPA0 GPA1 x=1e8 y=145 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=4
GPA0 GPA1 x=1e0 y=146 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=4
GPA0 GPA1 x=1e8 y=146 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=5
GPA0 GPA1 x=1e0 y=147 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=5
GPA0 GPA1 x=1e8 y=147 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=6
GPA0 GPA1 x=1e0 y=148 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=6
GPA0 GPA1 x=1e8 y=148 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=7
GPA0 GPA1 x=1e0 y=149 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=7
GPA0 GPA1 x=1e8 y=149 attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=8
GPA0 GPA1 x=1e0 y=14a attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=8
GPA0 GPA1 x=1e8 y=14a attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=9
GPA0 GPA1 x=1e0 y=14b attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=9
GPA0 GPA1 x=1e8 y=14b attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=a
GPA0 GPA1 x=1e0 y=14c attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=a
GPA0 GPA1 x=1e8 y=14c attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=b
GPA0 GPA1 x=1e0 y=14d attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=b
GPA0 GPA1 x=1e8 y=14d attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=c
GPA0 GPA1 x=1e0 y=14e attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=c
GPA0 GPA1 x=1e8 y=14e attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3c rc=17 lc=d
GPA0 GPA1 x=1e0 y=14f attrcode=e
GG n=0
CHARFROMBUFFER GG n=0 sx=3d rc=17 lc=d
GPA0 GPA1 x=1e8 y=14f attrcode=e

Last edited by Golden Child; 01/08/25 06:36 PM.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
By modifying your printf at char_from_buffer to printf("GG = %x\n",m_field_attr & FAC_GG) I obtain 0x0c. So both GPA0 and GPA1 should be high, right? With an attribute code equal to 0x0e it should be working, unless those bits get lost somewhere in the middle.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
yes, I believe so. The attr = FAC_B line clears out the FAC_GG bits.

// simply blank the attribute character itself
attr = FAC_B;
attr |= (data & FAC_GG);



You might try adding a "fudge factor" to get the horizontal character position to come out as it expects to find 0x49,

print(0x1e0/8+13)
73.0



Also, I get a warning about the palette on the screen, you might just comment out the set_palette ine.

Driver system23 (file system23.cpp): 0 errors, 1 warnings
Warnings:
Video Screen device 'screen': Screen does not need palette defined


SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green());
m_screen->set_raw(18'432'000, 800, 0, 640, 324, 0, 300);
m_screen->set_screen_update(m_crtc, FUNC(i8275_device::screen_update));
// m_screen->set_palette(m_palette);

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I cleaned the code, got rid of the palette.
I also reached the part of the test where it asks for the appropriate values. However it returns zero for some reason.
Still, that's been a good progress for today.

Thank you very much!

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Okay. I checked again for both values and I obtained wrong column but right row. The current value for the column is very different from the expected... I will take a look into the board again in order to find what is the refresh rate of that trigger.

EDIT:
Making some quick calculations, it should trigger when x=248h. The place where it triggers currently is x=220h. Any idea from where the zero could come from?

Thank you in advance!

EDIT 2:

I took a look into screen.hpos(), but I don't see anything anomalous.

EDIT 3:

I modified the 8275 to cease to import vertical and horizontal values from class screen and rely on its own counters. With that, I reached the correct row again, but also a much nearer 45h in the column value. I have a difference of 4 between this and the expected value.

Last edited by jlopezm; 01/09/25 12:08 PM. Reason: correction of statement
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
For some reason, the DMA controller is beginning its fetching from 8209 and not 8200. It's like the first fetch is grabbing the first dma of 8 bytes and then treating that as the start point.

You can see this if you bring up the m_channel.m_address and m_channel.m_count of the 8257 in the debugger, or using a memory window to put values into the 8200 range.

So that's 9 characters of difference where it's off, and the datasheet says the light pen reading will be off by at least 3 character positions. That's pretty close to where that value should be.

Currently targeting system23 (IBM System/23 Datamaster)
>wpi 0,9,w
Watchpoint 1 set
>g
Stopped at watchpoint 1 writing 84 to 08 (PC=05BD)
Stopped at watchpoint 1 writing 7F to 05 (PC=05C1)
Stopped at watchpoint 1 writing 87 to 05 (PC=05C5)
Stopped at watchpoint 1 writing 00 to 04 (PC=05C8)
Stopped at watchpoint 1 writing 82 to 04 (PC=05CB)
>g


so it's putting the 8257 into autoload, then putting 77F into the count and then 8200 into the address.


print(0x780/80)
24.0
24 rows of 80 characters

1 member likes this: jlopezm
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
I think that the bits for the display are MSB first because currently the characters are backwards

from the microb:

u32 *pix = &bitmap.pix(y, x);
for (int i = 0; i < 8; i++)
{
*pix++ = BIT(dots, 7) ? fg : rgb_t::black();
dots <<= 1;
}

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
So I added 3 to the column count in the 8275 to simulate this offset and I have added a delay of a character at the System/23 source to simulate the latch. As a result I obtain 0x49, which is the expected result and as such, I passed to test 06.

How are you doing to display characters?

In any case, thank you very much!

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
just using the debugger to jam values into the 8200 range and seeing what happens:

in the debugger, just hit CTRL+M to bring up a memory window (or use the menus Debug/New memory window) and type in 8200 for the address and then start putting some values in.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Now I should track the board again, I have to find what is prt 0x4D doing. There is no description of this test other than it is CRTC-related.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
IBM_System_23_Model_5324_MAP.pdf


*********************************************************************
*
*
FAILURE IN CRT INTERFACE LINES <HORIZONTAL,VERTICAL, OR VIDEO).
*
06 <LATCHES) *
07 ON CRT>


DISCONNECT CRT CABLE AT THE*
* CPU END. RUN TEST AGAIN. IF TEST ENDS WITHOUT
* ERROR CAN AUDIBLE ALARM AFTER APPROXIMATELY 30-45*
*SECONDS INDICATES CORRECT ENDING), AFTER
*
* REMOVING THE CRT CABLE, REPLACE: 1. CRT DRIVER/ *
RECEIVER CARD CSEE SM 1430). 2> CRT ASSEMBLY <SEE*
*SM 1430). 3) CRT CABLE ASSEMBLIES <SEE SM 1430). *
*
* IF TEST FAILS AT ERROR '06' IN THE CE LATCHES,
*
*
* WITH THE CRT CABLE REMOVED, REPLACE THE CPU
*
*PLANAR BOARD (SEE SM 1230). IF PROBLEM NOT
*

1 member likes this: jlopezm
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
One thing you might do is to move the digits off of the top of the screen, (yes you can have negative coordinates)

Code
		<element name="digit0" ref="digit">
			<bounds x="14" y="-30" width="14" height="20" />
		</element>
		<element name="digit1" ref="digit">
			<bounds x="0" y="-30" width="14" height="20" />
		</element>



One way to "fix" the display is to reset the DMA counters manually to 8200 and 77F. Once the counters stabilize, pause the execution in the debugger and change them manually to get the display to start at 8200.

You could also set it from the lua console:

emu.item(manager.machine.devices[":dma"].items["0/m_channel.m_address"]):write(2,0x8200)
emu.item(manager.machine.devices[":dma"].items["0/m_channel.m_count"]):write(2,0x77F)



[Linked Image from i.imgur.com]



To experiment:

to pass this test, you can set all the test dips and then unset them (3x) and it will pass the test. I think that this test is just to see if the various line values are changing.



Code
		I8255(config, m_ppi_kbd);
		m_ppi_kbd->in_pa_callback().set(FUNC(system23_state::cpu_test_register_r));
		m_ppi_kbd->out_pa_callback().set(FUNC(system23_state::cpu_test_register_w));
		m_ppi_kbd->in_pb_callback().set([this] () -> u8 
		{
			return ioport("TEST06")->read();
		});


		PORT_START("TEST06")
			PORT_DIPNAME( 0x04, 0x00, "04")
			PORT_DIPSETTING(    0x00, DEF_STR( Off ))
			PORT_DIPSETTING(    0x04, DEF_STR( On ))
			PORT_DIPNAME( 0x08, 0x00, "08")
			PORT_DIPSETTING(    0x00, DEF_STR( Off ))
			PORT_DIPSETTING(    0x08, DEF_STR( On ))
			PORT_DIPNAME( 0x10, 0x00, "10")
			PORT_DIPSETTING(    0x00, DEF_STR( Off ))
			PORT_DIPSETTING(    0x10, DEF_STR( On ))



once you get past this, you get to test 08

[Linked Image from i.imgur.com]

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
You really got very ahead from myself! That's nice to see the Diagnostics screen for the first time! Thank you for the sight.

I found HRTC to be tied to port 4dh at 10h.

This thing with DMA means that we will need to fix the 8257 too?

Again, thank you for your support. With the degree of involvement you are having, you deserve to be in the credits for this.

EDIT:

Do you know if there is a way to get the synchronisms in a data form instead of a callback?

EDIT 2:

I found VRTC tied to a 74LS174, and its output tied to port 4d at 08h.

Last edited by jlopezm; 01/10/25 08:33 AM.
Joined: Aug 2009
Posts: 1,285
Likes: 222
Very Senior Member
Very Senior Member
Joined: Aug 2009
Posts: 1,285
Likes: 222
You sure it's I8257 and not really I8275 doing the bad sorcery? A +9 would cause havoc to basically anything that uses either chips, and probably noticed in big players such as dkong.cpp or pc8801.cpp

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Personally, I don't know. I haven't taken a look at the DMA yet as I am tracking traces to find the connections for test 06.

The address generation is completely the 8257 responsibility. However, the video chip used in the PC-88 is very similar to the 8275 in various aspects (I wouldn't dare to say it's a derivative of some sort, but it has similarities). As the PC-88 uses a similar tandem and has no strange effects, maybe it could be the 8275.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
Currently targeting system23 (IBM System/23 Datamast
>wpi 0,9,w
Watchpoint 1 set
>g
Stopped at watchpoint 1 writing 84 to 08 (PC=05BD)
Stopped at watchpoint 1 writing 7F to 05 (PC=05C1)
Stopped at watchpoint 1 writing 87 to 05 (PC=05C5)
Stopped at watchpoint 1 writing 00 to 04 (PC=05C8)
Stopped at watchpoint 1 writing 82 to 04 (PC=05CB)

as soon as it loads the 82, you can single step and each step it will count up, it will immediately count from 8200 to 8206 in dma channel 2, Then it pauses and you can reset the counters manually and then it will work fine.


You might try something like:

Code

	
			u8 m_vrtc = 0;
			u8 m_hrtc = 0;
			u8 m_pixel = 0;

in draw character

	m_pixel = BIT(gfx,1);



	m_ppi_kbd->in_pb_callback().set([this] () -> u8 
		{
			return m_hrtc << 4 | m_vrtc << 3 | m_pixel << 2;
			//ioport("TEST06")->read();
		});

		I8275(config, m_crtc, (18'432'000 / 8));
		m_crtc->set_character_width(8);
		m_crtc->set_screen(m_screen);
		m_crtc->set_display_callback(FUNC(system23_state::display_pixels));
		m_crtc->drq_wr_callback().set(m_dmac, FUNC(i8257_device::dreq2_w));
		//m_crtc->irq_wr_callback().set_inputline(m_maincpu, I8085_RST55_LINE); // Only when jumper J1 is bridged
		m_crtc->vrtc_wr_callback().set([this] (u8 data) { m_vrtc = data; });
		m_crtc->hrtc_wr_callback().set([this] (u8 data) { m_hrtc = data; });



bp 6

to catch when it errors,

then you can use history to see where it went awry

and set the pc back to "fix" it


071A: in $2d
071C: ani $40
071E: jz $0006
0006: di

pc=721

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
By adding more jumpers to the 2dh input port I surpassed this part, and got a nice diagnostics screen even with a trap statement.

EDIT:

I already fixed error 08. It expected the paging registers from 20h to 23h. I am sure 23h is for ROM, I am not sure about the others. I do know two are for RAM (one for CPU lectures, another for CPU reads) and another one for DMA. I will determine which of them is each one in further tests.

Now come the tests 0ah-1fh, which are meant for paged ROS ROMs. For now I have passed without the need for banks. So it will become far more difficult from now on. I don't entirely understand the docs. Do I have to create a view? If I understand correctly, I must override the read and write methods for each device that access the memory, right?

On top of that, I have the issue that while most variants of the Datamaster have 16 ROS ROMs, the oldest variants have only 14 of them. Would this be more difficult to configure?

Thank you in advance!

EDIT 2:

I'm trying with the banks, however it crashes during the tests because the input of the page exceeds the number of available pages. On top of that, I now recall that there are multiple optional ROMs that could be placed in that memory area... Is there a way to manually define the number of pages a bank has?

Thank you in advance!

Last edited by jlopezm; 01/10/25 04:13 PM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
SY34-0171-0_IBM_5322_Computer_Service_Manual_Dec80.pdf

p74

looks like 4 different registers mentioned

ROS page
DMA page
r/w read page
r/w write page

says ros pages 2,3 and r/w page 7 not used

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Actually ROS page 3 is used in most models (early units lack ROMs 10h and 11h), and page 7 is used too (18h and 19h). I debugged through tests 09h-19h to find where they do belong in the memory map. I also found that the very first byte of each ROM wxcept the boot one must equal the highmost byte of the first address they are allocated to.

I do know the paging registers, but I do not know how are they ordered in the I/O map yet (but I have them located at 20h-23h). I only know at this point that I/O port 23h is the ROM paging register, as confirmed by the tests 0a-19.

I have updated the repo with some definitions of ROMs in the paged area of the ROS. Unfortunately I don't know how to tell the bank system that I need an empty page...

EDIT:

I realized how to configure the banks. All defined ROMs in the paged area are becoming accessible to the emulated computer. I will add the remaining ones for set "R".

Last edited by jlopezm; 01/10/25 05:47 PM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
well you can always do it "manually", where you have a routine that computes the address

declare a buffer for the memory

Code
u8 m_rw_storage[16*16384] ={0};
u8 m_rw_write_bank = 0;
u8 m_rw_read_bank = 0;
uint8_t read_rw_page(offs_t offset);
void write_rw_page(offs_t offset, u8 data);	


	map(0xc000, 0xffff).rw(FUNC(system23_state::read_rw_page),FUNC(system23_state::write_rw_page));

	uint8_t system23_state::read_rw_page(offs_t offset)
	{
		return m_rw_storage[(m_rw_read_bank & 0xf) * 16384 + offset];
	}

	void system23_state::write_rw_page(offs_t offset, u8 data)
	{
		m_rw_storage[(m_rw_write_bank & 0xf) * 16384 + offset] = data;
	}


Last edited by Golden Child; 01/10/25 07:21 PM. Reason: oops forgot the offset
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
If I were to make a configurable bank memory with different RAM sizes, how should I do it?

Thank you in advance!

Last edited by jlopezm; 01/10/25 06:39 PM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
you can make an input port that is config and use ioport("NAME")->read() or if you can use a required_ioport

(cribbing from apple2.cpp)


m_sysconfig(*this, "a2_config"),

required_ioport m_sysconfig;



PORT_START("a2_config")
PORT_CONFNAME(0x04, 0x04, "Shift key mod") // default to installed
PORT_CONFSETTING(0x00, "Not present")
PORT_CONFSETTING(0x04, "Installed")

if (m_sysconfig->read() & 0x04)
{



and have entries for 32K, 64K. 96K and 128K

maybe have a variable to hold the size limit (if you work out the entries, the bit pattern read could be the size (in pages))

if (m_rw_read_bank <= m_rw_size) return value else return 0;

It's unclear exactly what it does when it addresses memory that isn't there, do you get a trap? parity error?

Last edited by Golden Child; 01/10/25 07:35 PM.
1 member likes this: jlopezm
Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
For RAM size differences, there needs to be a good reason not to just use the RAM device and the standard -ramsize switch.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
these fragments from apple2.cpp show the ram device being used

Code
 grep -rni 'm_ram\|RAM' src/mame/apple/apple2.*

53:#include "machine/ram.h"
84:		m_ram(*this, RAM_TAG),
104:	required_device<ram_device> m_ram;
127:	u8 ram_r(offs_t offset);
128:	void ram_w(offs_t offset, u8 data);
183:	u8 *m_ram_ptr;
184:	int m_ram_size;
277:	m_ram_ptr = m_ram->pointer();
278:	m_ram_size = m_ram->size();
298:	for (int adr = 0; adr < m_ram_size; adr += 2)
300:		m_ram_ptr[adr] = 0;
301:		m_ram_ptr[adr+1] = 0xff;
799:	return m_ram_ptr[address % m_ram_size];
806:u8 apple2_state::ram_r(offs_t offset)
808:	if (offset < m_ram_size)
810:		return m_ram_ptr[offset];
816:void apple2_state::ram_w(offs_t offset, u8 data)
818:	if (offset < m_ram_size)
820:		m_ram_ptr[offset] = data;
826:	map(0x0000, 0xbfff).rw(FUNC(apple2_state::ram_r), FUNC(apple2_state::ram_w));
1273:	RAM(config, RAM_TAG).set_default_size("48K").set_extra_options("4K,8K,12K,16K,20K,24K,32K,36K,48K").set_default_value(0x00);
1280:	/* internal ram */
1281:	RAM(config, RAM_TAG).set_default_size("48K").set_extra_options("16K,32K,48K").set_default_value(0x00);

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Hello,

I tried the code you showed me but I have no way it compiles, so for the time being I commented it. I have modified it for my needs but it shouldn't be that bad...

uint8_t system23_state::ram_r(offs_t offset)
{
LOG(offset);
if(offset < 0xc000)
{
return m_ram_ptr[offset];
}
else
{
uint32_t page = (16 * 1024 * m_ram_r_page) + 1;
if (offset < (page + offset))
{
return m_ram_ptr[page + offset];
}
}

return 0xff;
}

void system23_state::ram_w(offs_t offset, uint8_t data)
{
LOG(offset);
if(offset < 0xc000)
{
m_ram_ptr[offset] = data;
}
else
{
uint32_t page = (16 * 1024 * m_ram_w_page) + 1;
if ((page + offset) < m_ram_size)
{
m_ram_ptr[page + offset] = data;
}
}
}


Do you have any idea why this won't work? Please, any hint, for small it can be, will be welcome.

EDIT:
Still, I haven't been able to configure the memory even after I used the proposed line at the constructor. Also, the source file has started to grow so much I am starting to consider to divide it into an h and a cpp file. What do you think about it?

Thank you in advance!

Last edited by jlopezm; 01/14/25 10:28 AM.
Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
Ok, there are multiple levels to unpack there.

Ignoring the ram device for a second, what you have in your code is a system where you have a fixed ram range from 0 to bfff and a banked range from c000 to ffff. If you do have that, you want to have that in the memory map, e.g. a ram() in 0..bfff and a bankr/w() in c000..ffff. You need to configure() the rambank in device_start then select the correct page when m_ram_*_page is updated. If you don't (which I suspect, you'd have no space for boot rom), then adapt as needed. In particular if the c000..ffff can say be ram *or* rom *or* i/o, you need a combination of bank and view, let us know.

The ram device function is to store the passed in ramsize parameter *and* give you a memory range of that size. So you have to have one, then in device_start do a m_maincpu->space(AS_PROGRAM)->install_ram(0,...., m_ram->pointer()). '...' varies depending on whether m_ram->size() can be less than 0xc000. And you also need to call configure on the bank with m_ram->pointer() and the appropriate parameters.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Please, wouldn't you know if there is any machine with a similar memory map I could take as an example? I am not very sure about the third parameter at configure_entries.

I do currently have a ram device at 0x08000-0xbfff and I am trying to configure a bankrw at 0xc000-0xffff.

EDIT: There is a complication with banks as this computer uses two different registers for the CPU to access RAM, one for reading and another for writing.
EDIT 2: To add more confusion, DMA accesses memory with its own paging register, too.

Last edited by jlopezm; 01/14/25 11:47 AM.
Joined: Feb 2004
Posts: 2,635
Likes: 340
Very Senior Member
Very Senior Member
Joined: Feb 2004
Posts: 2,635
Likes: 340
Some of the TRS CoCo computers do funky stuff with banking. Whatever it was cam900 converted to a view the other week (nmk/quizdna.cpp I think) can swap banked ROM over the top of RAM.

Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
Separate read and write banks aren't a problem, and neither is a separate DMA bank (what was later called an IOMMU).

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Please, how would you reccommend me to implement it then? bankrw only allows one register for paging. Does this mean I need to make it manually?

Thank you in advance!

Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
You don't use one bankrw, you use one bankr and one bankw.

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
So one bankr and one bankw at the same position on the memory map? It sounds like a clever solution to my problem.

EDIT:

Tried this solution and after fiddling a while with the I/O ports for those registers I got the first page of RAM to be detected, but not the other six. Therefore it seems to be left constrained at 32KB for the time being.

Last edited by jlopezm; 01/15/25 08:27 AM.
Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
you did the configure_entries on both banks and the correct page selection where needed?

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Bank initialization
m_ram_bank_r->configure_entries(0, 16, m_ram->pointer() + 0x4000, 0x4000);
m_ram_bank_w->configure_entries(0, 16, m_ram->pointer() + 0x4000, 0x4000);


RAM Device initialization
RAM(config, m_ram).set_default_size("128k");

Memory map initialization
map(0xc000, 0xffff).bankr(m_ram_bank_r);
map(0xc000, 0xffff).bankw(m_ram_bank_w);


Read page being set
void system23_state::ram_read_page_w(uint8_t data)
{
m_ram_r_page = data;
m_ram_bank_r->set_entry(data & 0xf);
}


Write page being set
void system23_state::ram_write_page_w(uint8_t data)
{
m_ram_w_page = data;
m_ram_bank_w->set_entry(data & 0xf);
}


If you need any other code segment, please tell me.


EDIT:

I have an unrelated doubt. If I have a 8253 as a baud rate generator for a 8251, how should I express this in code? And if it directly drives a beeper, like in the PC?

Thank you in advance!

Last edited by jlopezm; 01/15/25 09:07 AM.
Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
I'm surprised by the +0x4000. More often than not I've seen the page 0 refer to the fixed page. You should log the ram_read_page_w/ram_write_page_w calls just to be 100% certain of what the bios looks at. Also the 16 should be m_ram->size() / 0x4000 - 1 (the -1 only if the +0x4000 is kept).

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
The size should remain as it is, as the datamaster also checks for page 0xf. I placed the + 0x4000 as the first 16KB of RAM are fixed and the rest are paginated.

Please, take a look into this documentation: bitspassats - Datamaster.

I'll also take a look into the logs as advised.

Thank you very much!

Joined: May 2004
Posts: 1,016
Likes: 131
D
Very Senior Member
Very Senior Member
D Offline
Joined: May 2004
Posts: 1,016
Likes: 131
The +0x4000 will get you memory trashing on the selection of page 16 because your RAM isn't that large. I assume you want to get rid of the +0x4000 and just set the page to 1 in your machine_reset().

EDIT: 16 * 0x4000 = 256k, so something isn't adding up here.

Last edited by Duke; 01/15/25 10:37 AM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
The system is capable of addressing up to 256KB of RAM at 0xc000-0xffff, but officially there was never a Datamaster with more than 128KB of RAM.

Memory boards contain the infamous TMS4132, which is structured in 2 separate banks of 16Kb. Nine memories per segment (8+p) so 16KB available to the CPU per bank. A 32KB board contains two memory banks and a 64KB four.

As with ROM, the computer checks them on start up and detects its presence and integrity. Then it displays this on the screen codes.

However, even if no Datamaster ever had such big amount of RAM and has no code for it on the diagnostics screen, it explicitly searches for page 0xf, probably as part of a test.

EDIT:
According to the logs, all three registers are being set, so maybe implementing the DMA banking may have something to do with the issue...

Last edited by jlopezm; 01/15/25 01:09 PM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have solved the issue with RAM memory. While at first I thought it to be an issue with my configuration, I later recalled that the memory card sockets had indeed two lines each, one that determines if they are present and another one that determines if they are 64KB. I have successfully traced them on my board and reached the PPI on the same port as the A1-A4 jumpers, which were also wrongly assigned. I can choose the amount of memory by DIP switch configuration now, from 32KB to 128KB. If there is a better way to do so, please could you teach me about it?

Now it would be time to deal with the 8253 PIT. Please, how could make a speaker sound if directly connected to the output of one of the counters, like in the 5150 PC? With some luck I may be able to hear some beep! I also have to trace the outputs in order to find how does it detects that the device is installed.

EDIT:
I managed to get the sound running! I had some trouble with the speaker_sound_device, but after it was resolved it went very smooth. However, I still don't know how the Datamaster expects to test the 8253, so test 34 still fails. I am thinking on starting with test 35, which is the keyboard. The Datamaster's keyboard is an intelligent peripheral and it uses a 8048 as a microcontroller. What would be the best approach to handle it?

Thank you all the involved!

Last edited by jlopezm; 01/16/25 11:37 AM.
1 member likes this: robcfg
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Hello, it has been some time since the last time I wrote here. I solved all the tests and the computer made a clean IPL for the first time two days ago!

[video:youtube]
[/video]

Now, I have some fronts to deal with, but maybe one of the more urgent ones is regarding the keyboard, whose implementation isn't finished due to lack of data. @GoldenChild found the scancodes at 0x300 in the keyboard microcontroller ROM. Is there an easy way to get the matrix back from those processed scancodes if we have a layout with them mapped on?

Thank you in advance!

1 member likes this: R. Belmont
Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
Generally we just start running the microcontroller. You'll see it toggle bits in order on its GPIO pins and from there you can hook up some keys to each row/column and see what they generate.

Alternatively if there's a schematic available, that of course will show the matrix. Or since you know where the scancode table is, you can disassemble the relevant section of the microcontroller ROM and see how the rows/columns map to the scancode table.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
You can actually reconstruct the matrix from the scancode table, according to the ibm manuals there are 88 possible keys, and there's 83 that are used, 00 goes in the table where there's a gap.

If you look at hi-res pictures of the 5322 or 5324 keyboards, you can see the matrix connecting to the pads. Also you can figure out how it's connected from the pictures of the board traces.

I think I've got a pretty good idea of how it works, there's 11 matrix lines and an 8273565 sense amplifier (that has a multiplexer which selects which of 8 lines to sample) (11 matrix lines * 8 sense lines)




(from my posting on reddit:)

Also, I found some disassemblies of various IBM keyboard controllers, some of which also use the same capacitive sense amplifier, the 9314 (aka the 8273565)

https://github.com/Halicery/8042

Also, there's some nice pix at

https://deskthority.net/wiki/IBM_5322_System/23_Datamaster_computer

I think the 5324 keyboard was very similar (if not identical internally)

https://www.flickr.com/photos/129328866@N04/albums/72157649745488066/

Last edited by Golden Child; 02/02/25 04:19 PM.
1 member likes this: jlopezm
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
taking a hi res pic and superimposing the pinout of the 8048

[Linked Image from i.imgur.com]

so you can see pin 12 on the connector is connected to Reset

looks like T1 and P23 are connected to the capacitive sense

T0 connects to the delay strobe

P20-P22 select the sense multiplexer

P10-P17 control the matrix lines

P24-P26 control matrix lines

P27 is data strobe



you can also get some clues from a pc keyboard schematic:

http://www.kbdbabel.org/schematic/kbdbabel_doc_ibmpc_kbd.pdf

I think that DB7 is connected to the G line of the capacitive sense (must be a chip enable line)

Last edited by Golden Child; 02/02/25 06:58 PM.
1 member likes this: jlopezm
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
[Linked Image from i.imgur.com]

with the scancode table order drawn on top, 11 matrix lines (going from right side to left), following the sequence from the bottom to the top are the sense lines (8)

(there's one scancode in the table that isn't shown (5a) so I don't know what's up with that one)

Last edited by Golden Child; 02/02/25 04:58 PM.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Thank you for the information.
I was aware of the computer interface pins because I had to solve the test 35h and for this reason communication between both microprocessors had to be done. Examining diagrams for the 5150 and the 5160, I can say the microcontroller was used in a completely different way. The parallel data bus from the microcontroller is used as interface with the computer in the Datamaster while in the PC it drives the matrix, apparently.

The Datamaster is capable to recognize when the keyboard lid is open. So maybe the 5ah scancode may be from a hidden button.

I have some errands to do this morning, but when I get home again I will check again. What I still don't understand is the usage of the sense amplifier... it seems to have four data line as input, however the output of the matrix is eight bits wide, right?

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
it has a multiplexer built in, so it uses 3 bits to select one of the sense inputs, the 3 bits can choose 1 of 8 possibilities (from 0 to 7). They had to do this because there just aren't enough i/o pins on the 8048 to drive 11 bits of matrix and 8 bits of inputs along with 7 bits of output.

The microcontroller is just wired up slightly differently than the IBM XT, they're using the bus to drive serial data to the computer in the XT instead of parallel data here in the Datamaster, but otherwise very similar.


with regards to the hidden button, there's what looks like a capacitive pad near the microcontroller, (in the upper right of the board), maybe that is where that's coming from

https://www.reddit.com/r/Mechanical...23_datamaster_keyboard_precursor_to_the/

Last edited by Golden Child; 02/03/25 12:15 PM.
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
btw the superimposed pictures above came from

[Linked Image from i.imgur.com]

and

https://www.flickr.com/photos/129328866@N04/15857780170/in/album-72157649745488066

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
A little experiment to generate the PORT from the scancode table with lua

Code
a = io.open("KBD_8048.bin","r")
b = a:read("*all")

for i=0x300,0x300+11*8-1 do io.write(string.format("%02x ",b:byte(i+1))) if (i+1)%8==0 then print() end end

function hex(a) return string.format("%02x",a) end

function domatline(line) print('PORT_START("MD'..string.format("%02d",line)..'")') for i=0,7 do c=b:byte(line*8+i+0x300+1) cstr=hex(c) 
if c~=0 then print("PORT_BIT( 0x"..hex(2^i)..", IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // ".."scancode "..cstr) 
else print("PORT_BIT( 0x"..hex(2^i)..", IP_ACTIVE_LOW, IPT_UNUSED ) // ".."scancode "..cstr) end end print() end

for matline = 0,10 do domatline(matline) end


calling the matrix drive lines MDxx as in src/devices/bus/pc_kbd/pcxt83.cpp

Code

PORT_START("MD00")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 4a
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 4d
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 43
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 46
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 4e
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 49
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 4c
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 5a

PORT_START("MD01")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 40
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 42
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 41
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 45
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 44
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 47
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 48
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 4b

PORT_START("MD02")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 68
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 0b
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 56
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 59
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 2d
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 2c
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_) PORT_CHAR('') PORT_CHAR('')   // scancode 3d
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // scancode 00
...
etc


Last edited by Golden Child; 02/03/25 12:57 PM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
My current problem is that being capacitive, the sets and resets the column scan values, so they are a strobe instead of a more constant value. By the time the key value is read, the counter is always 0. I will update my repo soon.

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
just as an aside, here's a page where a guy was making his own capacitive pads for an IBM keyboard

https://deskthority.net/viewtopic.php?t=3047&start=60

also talks about the reference capacitors of the 8273565, etc


from the keyboard babel schematic of the xt keyboard:

[Linked Image from i.imgur.com]

Last edited by Golden Child; 02/04/25 12:25 PM.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
As far as I went, the counter is reset before I can actually use it. I have tried to "latch" it, but I can't get it to another value other than 0. Same happens with the three selection bits, they change but by when T1 is read they are reset to their default at 7...

Joined: May 2009
Posts: 2,231
Likes: 402
J
Very Senior Member
Very Senior Member
J Offline
Joined: May 2009
Posts: 2,231
Likes: 402
Originally Posted by jlopezm
As far as I went, the counter is reset before I can actually use it. I have tried to "latch" it, but I can't get it to another value other than 0. Same happens with the three selection bits, they change but by when T1 is read they are reset to their default at 7...

Then latch it from the other direction. Look into PORT_CHANGED_MEMBER.

Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
Assuming a similarity to the PC/XT (commented disassembly at https://github.com/Halicery/8042/blob/main/8048_XT_INTERN.TEXT) the microcontroller tells the external circuitry when to latch the bits. On the PC/XT there are 2 latches, Q (latches the selection bits) and RESET (latches the value read from the keyboard matrix).

This is typical late 70s/early 80s IBM overengineering. Most keyboard microcontrollers do what you'd expect: set the selection bits and read live.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have been able to stabilise the values of the counter and the select signals until T1 is read. I can see them changing through the logs.

The next step is to assign the real key to the emulated one. I have been trying to assign "Reset Error" (6e) to F5 as it is the position it has in the original keyboard ("Reset error" became F5 in the transition from the Datamaster to the IBM PC) but I haven't got any reaction to the key being pressed. What would be the best way to test this?

Thank you in advance!

Joined: Aug 2009
Posts: 1,285
Likes: 222
Very Senior Member
Very Senior Member
Joined: Aug 2009
Posts: 1,285
Likes: 222
Are those inputs read as active low or active high? Wrong input pressed polarity can cause a stuck case where the host CPU believes everything is pressed and do nothing (or at best cause havoc).

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
No, I don't think this is the issue. If there was a key pressed test 35h would fail and display the offending key's scan code.

It's like the key input at T1 was not recognised.

Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
It's somewhat common for microcontrollers to not properly detect stuck keys if that's the initial state. But add some printf()s or whatever and see if the T1 read callback is returning what you expect it to.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have successfully read keys, but the scancodes don't seem to match... I imagine I have to revise the matrix again.

EDIT:
By the way, I would like to assign the unassigned ROM space to a known value (for example 0xff). What would be the best way to so? With uninitialized memory I get some sporadic ROM errors between tests 1A and 29...

Last edited by jlopezm; 02/05/25 08:30 PM.
Joined: Apr 2012
Posts: 347
Likes: 66
Senior Member
Senior Member
Joined: Apr 2012
Posts: 347
Likes: 66
Originally Posted by jlopezm
EDIT:
By the way, I would like to assign the unassigned ROM space to a known value (for example 0xff). What would be the best way to so? With uninitialized memory I get some sporadic ROM errors between tests 1A and 29...
Replace
Code
ROM_REGION(0x24000, "maincpu", 0)
with
Code
ROM_REGION(0x24000, "maincpu", ROMREGION_ERASEFF)


BBC Model B, ATPL Sidewise, Acorn Speech, 2xWatford Floppy Drives, AMX Mouse, Viglen case, etc.
1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
This time I think I do require some revision by someone else. I have to revise the keyboard matrix again, but there's something that is troubling me: the scancodes generated do not match the characters I get to the screen. There's a catch, that is the verification scan codes are working fine, but when it comes to the regular ones, I even get some keys with multiple key codes...

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
For those of you who have cloned jlopezm's github and are following along, to get past the startup tests you need to unset all the DIP switches except for the ones that deal with memory.

It's great to see some keystrokes working.

I haven't got time today but I'll try to figure out why the matrix isn't what we expect. (Hopefully it will stop snowing here...)

Joined: Jun 2001
Posts: 538
Likes: 43
O
Senior Member
Senior Member
O Offline
Joined: Jun 2001
Posts: 538
Likes: 43
It's figured out already :-)

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Good morning!

I have some more issues with the keyboard. All the space for the keys has been used, but even so, a lot of keys are missing. I have seen a lot of invalid scan codes and even combinations trigggered by a single key stroke. Maybe my keyboard is different from the one pictured here in this thread, it could be that my unit has an entirely different matrix... as the computer always receives the scancodes it really does not care about the matrix. There's also the possibility that there could be more columns, but so far I have been unable to find them. It may also be that my logic for the keyboard could be entirely wrong.

I have made tests on that machine that could give goosebumps to other owners of the system. But our red line lies within the keyboard. Fortunately, with the help and contributions of @Golden Child and another Datamaster owner I have had all the information required to reach the stage I'm at with the keyboard.

There are other things to do in this emulation that only me or any other Datamaster owner can do:
  • Paging the character ROM.
  • Setting the DMA page.
  • Build the Datamaster bus (there are undocumented signals).
  • Build the Datamaster keyboard bus (for internationalization -> our small community has people around the world: USA, Canada, Spain, Andorra, France, Belgium, Italy, Deutschland, Romania, and maybe others still not contacted); it also has undocumented stuff...
  • Dump the FDC microcontroller and study the card.
  • Document the drivers.
  • Add remaining jumpers
  • Dump and document ROMs
  • Add the printer port


There are issues that could be resolved by someone more experienced than me in MAME:
  • Fix the uninstalled ROMs errors (sometimes in the space of uninstalled ROMs the program finds the signature for a present ROM and checks it, but as there is only garbage it does not pass the test). This happens at 10, 11, 1A-29.
  • Fix a crash at test 19. Cause is unknown.
  • Replace parts of my poorly produced code with something more worthy of MAME standards. While having been programming for some years, I am still a novice in C/C++ and MAME.


And finally we have the keyboard, whose communication has been found but the expertise of someone with knowledge of MCS-48 may be the only way to make it viable.

I have also some doubts regarding the definitions of dip switches. So far I have made them as in the hardware, but would it be better to do it with only the valid options (for example in the language switches)?

With the virtual machine in the current state, I will center myself on tasks of the first group. Basically because only owners of a unit can do them. At the same time, I would like to consolidate the learnt knowledge by building a hardware clone of the computer. I would be very grateful if someone could help me with stability/quality issues and if someone with experience with such microcontroller could join, please. I am not asking people to write it for me, as you have seen I have done it by myself (with lots of help, of course). From March on I will have less time to dedicate to the emulator, and from September on, I will not have regular access to the System/23 computer except during special occasions. My goal would be to deliver a working machine before I lose access to the hardware, but I cannot do it alone. Due to the nature of the hardware, reverse-engineering is a more costly process than usual.

Please, could I count with some collaborators? I hope I am not asking too much, and if I do I ask your forgiveness. In any case, wether if you accept or refuse, thank you very much. If I had been alone this wouldn't have progressed as much as it has done.

Regards

Joined: Feb 2008
Posts: 178
Likes: 15
G
Senior Member
Senior Member
G Offline
Joined: Feb 2008
Posts: 178
Likes: 15
You can submit the current work-in-progress and get it into MAME (or send it to someone who can make it acceptable for inclusion) then it will be more accessible to others who may step up and try to fix things. Of course if you have not finished then finish your work first. But do get it into MAME at some point even if not fully working otherwise your work will have been for nothing.


Dumping ROMs for MAME since 1999!
https://gurudumps.otenko.com
2 members like this: jlopezm, robcfg
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
Doing some experiments,

I wonder if that the bit reversal in read_keyboard may be unnecessary. In the documents, it says that the bits are reversed coming out of the keyboard controller bus, but when the I8255 reads them on port A maybe it is hooked up in reverse too, so the net effect is that the bits aren't reversed when they're actually read.

If we take out that reversal bitswap, the matrix looks more like what we would expect to see from the table in rom at 0x300.

Maybe. (or maybe I need more sleep haha)

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
For the time being I am testing it without the reversal and the matrix seems correct, at least for the unshifted characters. When shift is pressed, I get the wrong character on screen again; however that's something I have to investigate later on. For the Pull Request, there would be the reversal in the keyboard and also in the computer to compensate and also to be respecting the pinout in the service manual of the computer. Thank you!

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
Here's a fragment of code that helped me experiment with the key matrix. You press 0-9,a to select the matrix drive line, and keypad0 to 7 to select the sense line. Pressing the sense line presses the key for that combination of matrix drive line and sense line.


Code
	#define PRESSED(x) (machine().input().code_pressed(machine().input().code_from_token(x)))

		u8 keydown = 0;

		const char * matrix_table[11] = 
		{
			"KEYCODE_0",
			"KEYCODE_1",
			"KEYCODE_2",
			"KEYCODE_3",
			"KEYCODE_4",
			"KEYCODE_5",
			"KEYCODE_6",
			"KEYCODE_7",
			"KEYCODE_8",
			"KEYCODE_9",
			"KEYCODE_A"
		};

		for (int i=0;i<11;i++)
			if (PRESSED(matrix_table[i])) 
				m_c = i;  // set the column

		const char * sense_table[8] = 
		{
			"KEYCODE_0PAD",
			"KEYCODE_1PAD",
			"KEYCODE_2PAD",
			"KEYCODE_3PAD",
			"KEYCODE_4PAD",
			"KEYCODE_5PAD",
			"KEYCODE_6PAD",
			"KEYCODE_7PAD"
		};

		for (int i=0;i<8;i++)
			if (PRESSED(sense_table[i]))
			{
				m_r = i;  // set the row
				keydown = 1;
			}

		u8 retval = (keydown ? ((m_c == translate_columns() && m_r == m_select) ? 0 : 1) : 1);

		m_counter = 0;
		m_select = 7;
		return retval;



another approach is to use an ioport:


Code
		u8 keydown = 0;

		for (int i=0;i<11;i++)
			if (BIT(ioport("TESTMATRIX")->read(),i)) 
				m_c = i;  // column

		for (int i=0;i<8;i++)
			if (BIT(ioport("TESTSENSE")->read(),i))
			{
				m_r = i;  // row
				keydown = 1;
			}

		u8 retval = (keydown ? ((m_c == translate_columns() && m_r == m_select) ? 0 : 1) : 1); // active high

		m_counter = 0;
		m_select = 7;
		return retval;
		


	PORT_START("TESTMATRIX")
		PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0)
		PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1)
		PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2)
		PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3)
		PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4)
		PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5)
		PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) 
		PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7)
		PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8)
		PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9)
		PORT_BIT( 0x400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A)

	PORT_START("TESTSENSE")
		PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0_PAD)
		PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1_PAD)
		PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2_PAD)
		PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3_PAD)
		PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4_PAD)
		PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5_PAD)
		PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6_PAD)
		PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7_PAD)


if you get an error 94 (when you press a field key) you can clear that off with A and KEYPAD 3 which is the ERROR RESET key and it goes back to INPUT.

Last edited by Golden Child; 02/11/25 10:59 AM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Sounds pretty good! I will try it later.
Thank you very much!

Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
Another experiment I was trying was to make an ioport from a spreadsheet using google sheets and google Apps Script:


[Linked Image from i.imgur.com]

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have good news. I have completed assigning keys to the keyboard.
BASIC works!
I am updating the repo so anybody interested can see the code and play with BASIC.
Thank you!

2 members like this: robcfg, Golden Child
Joined: Feb 2014
Posts: 1,220
Likes: 223
G
Very Senior Member
Very Senior Member
G Offline
Joined: Feb 2014
Posts: 1,220
Likes: 223
I took a stab at rewriting the sys23 keyboard to be like the pcxt83 keyboard. It seems to work.


https://github.com/goldnchild/mame/tree/rewrite_sys23_keyboard

1 member likes this: jlopezm
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Hello,

I write again because I am currently repairing the Datamaster of a colleague and he has a different romset than mine, so I would like to make it known that I will be adding it when the ROMs are dumped. I think I have other romsets too, so I'll be complimenting the work with them, too.

Having received a second keyboard and a second floppy controller during this process makes it possible to add a second floppy controller code and opens the possibility to dump the floppy disk microcontroller code too.

EDIT:
The keyboard is AZERTY!

Have a nice day!

Last edited by jlopezm; 04/04/25 08:44 AM.
3 members like this: robcfg, ICEknight, Golden Child
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Hello,

I managed to repair the computer enough for it to display the diagnostics codes, but it gets stuck at test 05h (8275 + 8257). Therefore, I have an important conclusion that will affect the emulation at its core. I have detected a difference in the behaviour of the stock 8275 respect the Datamaster's one respect the interrupts. This means I will have to roll back some of the changes I made in the 8275 device. At the same time, I will have to add another one with the expected behaviour of the Datamaster's CRTC. As I haven't created a variant device yet, do you know if it is hard to do?

EDIT:
Another Datamaster will be coming my way soon, so I will be able to add even more features. This one will be mine, unlike the one I am currently repairing.

EDIT 2:
I am having to patch ROS 02h to rewrite test 05 for compatibility with the stock devices. Could I ask for some help to do so?

EDIT 3:
I have corrected the 8275 device, added the IBM CRTC, and created a second machine with the stock 8275.

Thank you in advance!

Last edited by jlopezm; 04/10/25 12:47 PM.
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Hello,

This is to clarify and correct a few statements I made in the last post.
A Datamaster set of boards arrived yesterday from USA. The computer mostly works, or at least is working more than the French Datamaster I am repairing. I have been able to conduct some tests on the American unit. Apparently my claims that the IBM CRTC is different from the stock 8275 is wrong. The American motherboard accepted the stock 8275 and even the Soviet KR580VG75. This means that I will have to roll back the latest changes and restore the previous values. This means that there is no value for the second emulated machine I made, other than for testing purposes with a 8276, but even that could be made with a single emulated machine running a virtual 8275.

Thank you very much!

1 member likes this: exidyboy
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have news that could expand the development of this emulated machine further.
  • In the first place, I was able to test a French keyboard on my Spanish model and found that the keycodes remain the same, their translation depends exclusively of the configuration switches of the computer.
  • Also, the microcontroller at the disk drive controller card has been successfully identified as 8048 and dumped. Maybe it is time to start studying the card.
  • A package of dumps will be archived during what remains of this week and therefore will contain the first full set of a Datamaster ever dumped (my last version lacked the floppy controller). It will also contain different versions of the firmware. This will be the largest package of Datamaster firmware to be released to this date.
  • In a few weeks I may receive a package of leased boards to dump and study. I don't own these boards, therefore it will bring in new data to my research and more expansions to the machine.

In light of these new developments, I may be able not only to continue the development of my current machine, but to force it to implement interfaces such as the expansion bus.

Thank you for all your support all this time!

1 member likes this: Golden Child
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I have acquired a word-editor card. When I receive it, I will study it in order to bring it to MAME.

2 members like this: Darkstar, robcfg
Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I am thinking about the word-processing card, and it will be a challenge for me. In the first place, it is an optional device, so it will require the pre-ISA bus to be defined. In the second place, it contains a second 8275 CRTC so it means it will generate a "second screen". Finally, that it intercepts the video signal of the motherboard and possibly disables it to supplant it with the second field generated by the auxiliary CRTC. I know there will be some time before this piece of hardware reaches me, but I would like to have some idea of how to treat it when it arrives. Please, could anybody give me some piece of advice or guides on how to proceed with the foresaid stuff?

Thank you in advance!

Joined: Mar 2001
Posts: 17,284
Likes: 268
R
Very Senior Member
Very Senior Member
R Online: Content
Joined: Mar 2001
Posts: 17,284
Likes: 268
The biggest lift there is going to be just defining and attaching the bus. Does this card completely replace the motherboard's video or overlay it? Taking completely over a system's built-in video from a bus card is very doable, I just did it in 0.277.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
I still don't know, the part still has to arrive. Still, considering it has an independent clock from the motherboard I don't think it overlays, but replaces it.

Joined: Dec 2017
Posts: 89
Likes: 12
J
Member
Member
J Offline
Joined: Dec 2017
Posts: 89
Likes: 12
Yesterday I found I/O ports for the NEC 765 and a 8255 in the Floppy disk controller card.
How would I have to do to define the bus, please? This way I could start with the development of the FDC card.

Thank you in advance!

Page 1 of 15 1 2 3 14 15

Link Copied to Clipboard
Who's Online Now
1 members (nerd4gw), 136 guests, and 0 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,373
Posts122,615
Members5,085
Most Online1,529
Jun 7th, 2025
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Powered by UBB.threads™ PHP Forum Software 8.0.0