Sounds good to me, great stuff
I'm still catching up. I've managed to get mame built from github and I can run hard drivin' (compact) and airborne. I've just not hacked the code yet (But I think that's what I need to do to get a feel for what is happening). I'll start experimenting with my wheel at the weekend.
Something that has always bugged me with the compact roms, is that it is not possible (yet, I think) to successfully calibrate the wheel using the service menu. I went and did some reading/investigation, trying to work out what values to expect (When viewing the "Control Inputs" service menu) from a successfully calibrated wheel. I didn't get very far. Thought I'd post my notes as they might be of interest/help:-Code: [Select]Compact harddrivin service manual (HDC_TM-329_2nd.pdf):
041787-02 Steering Encoder Disk.
043807-02 Centering Encoder Disk.
HDC_TM-329_2nd.pdf, From the "Control Inputs" service menu:
As you turn the steering wheel clockwise, the hexadecimal number should increase and change to zero once every turn.
As you turn the wheel counterclockwise, the number should decrease. Everytime the steering wheel passes the center position,
the words center edge should change from blue to green.
HDC_TM-329_2nd.pdf, from a section near the end about installing a new encoder wheel:
Install the steering wheel with the center spoke down. Make sure the single hole on the centering disk is between the opitcal reader on the centering
PCB so the steering wheel will be correctly centered.
From the Race Drivin' Compact Manual, for the Main Board Memory Map, it says:
OPTO: Optical Steering Wheel Reader
400000 (R) OPTORD Read the Optical Counter
404000 (W) OPTORES Reset the Optical Counter
408000 (W) CENRES Reset the Optical Centre Flag
I found a picture of a 041787-02 Steering Encoder Disk, and counted 72 holes. Based on this, I don't think we should see a steering value (When viewing the "Control Inputs" service menu) reported that exceeds 72 (Or maybe 144 if we are counting teeth passing as well has holes). Thus, when turning clockwise you'll see 0 increase to 72 then back to 0 etc... When turning anticlockwise you'll see 72 decrease 0 then back to 72 etc... In mame, I think we see values much greater than 72, this might cause strangeness. I think I'll try and hack things so that I force these 'ideal' values to occur at calibration.
Something odd I noticed, is that in mame when viewing the "Control Inputs" service menu and turning the wheel clockwise, I see the hexadecimal number decrease, not increase...
Wow that is the info we have been looking for!
From the Race Drivin' Compact Manual, for the Main Board Memory Map, it says:
OPTO: Optical Steering Wheel Reader
400000 (R) OPTORD Read the Optical Counter
404000 (W) OPTORES Reset the Optical Counter
408000 (W) CENRES Reset the Optical Centre Flag
Does this part have any relation to this code in the harddriv.cpp file?
Code: [Select]
PORT_START("mainpcb:a80000")
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_CUSTOM ) /* center edge on steering wheel */
I hacked the code about a month ago so that when i press a button i assign in the input assignment menu in mame it activates this function. When i press the button you see the center point indicator light up and the wheel reset back to 0000...............
There is no wheel calibration in street drivin or in hard drivin's airborne like the other games do. It only has the menu that shows the output value of it when your moving it around. I was thinking if i set the port_minmax from 0 to 71 or 143 ( if the games code counts 0 as a value) then trigger the code above to activate each time this reaches the centerpoint the same way it does when i push the button with this code i "hacked"
Code: [Select]
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_TOGGLE PORT_NAME("wheel centre1")
Maybe then it will function correctly........then all we would need to do is implement the proper scaling for a 900/720/270 degree wheel etc so that it only goes up to the max value when you turn it whatever direction it should go like 71/72 or 143/144 for clockwise/counter clockwise max then the opposite for the other direction. I probobly explained that in a confusing way lol.
I'm having another mess around with it today. I made some other code that was implementing the stuff i was doing in the other code i sent you plus it buffers/smooths the wheel output and truncates the last digit from the hex value you so it doesnt fluctuate as quickly when you turn the wheel around and it seems to have fixed the wheel going out of alignment when you turn it fast, that was another issue you could kinda stop from happening if you made smoother wheel turns physicly but sometimes just not possible if you want or need a sharp turn. The recentring logic i did before doesnt work as well in the new code though i dont know if it's because im messing with the values before i apply the offset. Now that i have the info you provided i don't think any of that is even going to be needed lol
Code: [Select]
#include <numeric> // For std::accumulate
// Function to calculate the Exponential Moving Average (EMA)
uint16_t harddriv_state::calculate_ema(uint16_t new_value) {
static float ema_wheel = 0.0; // Persistent storage of EMA across calls
static const float alpha = 0.05; // Smoothing constant
ema_wheel = alpha * new_value + (1 - alpha) * ema_wheel;
return static_cast<uint16_t>(ema_wheel);
}
// Main function to handle wheel input and apply adjustments
uint16_t harddriv_state::hdc68k_wheel_r() {
static const uint16_t g_latchpoint = 0x8000;
static int16_t wheel_offset = 0;
static bool last_wheel_edge = false;
uint16_t new_wheel_raw = m_12badc[0].read_safe(0xffff) << 4;
uint16_t ema_wheel = calculate_ema(new_wheel_raw);
uint16_t new_wheel = ema_wheel + wheel_offset;
// Set wheel edge to 1 if at or crossing the center and it is not already set
if (!m_hdc68k_wheel_edge &&
((m_hdc68k_last_wheel < g_latchpoint && new_wheel_raw >= g_latchpoint) ||
(m_hdc68k_last_wheel > g_latchpoint && new_wheel_raw <= g_latchpoint))) {
m_hdc68k_wheel_edge = 1;
}
// Handle wheel edge reset and offset adjustment
if (last_wheel_edge && !m_hdc68k_wheel_edge) {
int16_t adjustment = g_latchpoint - ema_wheel;
adjustment = (adjustment / 0x10) * 0x10; // Normalize adjustment to remove last digit
wheel_offset += (new_wheel_raw > g_latchpoint) ? -abs(adjustment) : abs(adjustment);
wheel_offset = (wheel_offset / 0x10) * 0x10; // Normalize wheel_offset to remove last digit
new_wheel = ema_wheel + wheel_offset;
new_wheel = (new_wheel / 0x10) * 0x10; // Normalize new_wheel to remove last digit
}
last_wheel_edge = m_hdc68k_wheel_edge; // Store the last state of the wheel edge
m_hdc68k_last_wheel = new_wheel_raw; // Update the last wheel value for comparison in the next cycle
// Continuously show the debugging message
popmessage("Wheel Raw: %04X, EMA Wheel: %04X, Adjusted: %04X, Edge: %d, Offset: %d",
new_wheel_raw, ema_wheel, new_wheel, m_hdc68k_wheel_edge, wheel_offset);
return (new_wheel << 4) | 0xff;
}
Thats where i was last night before i woke up and saw your reply today, i actualy had a look yesterday but none of it was sinking in as i had no sleep for a couple of days lol. I'll get back to you if it's been improved any. Cheers!