OK, for the knock sensor noise level, 0 means max noise and 2.5v (128) means minimum. So with a value of zero, you should be getting the noise engine blink code. I'm not sure what the threshold is but I can check the code again. I'll see if I can dig up some numbers for the others too.andyb wrote: Sat Feb 07, 2026 2:31 pm I've implemented almost everything I can think of, but the code still doesn't seem to run correctly. I suspect the values my simulated ADC generates aren't good enough. What I've done:
Chan 0 (knock sensor noise): returns 0
Chan 1 (battery voltage): returns 200
Chan 2 (unknown): returns 0
Chan 3 (TPS supply voltage): returns 40 (I have no idea what a good number would be)
Chan 4 (MAP): returns 0 for full vacuum, 255 for 2 bar
Chan 5 (Knock sensor integrator): returns 0
Chan 6 (unknown): returns 0
Chan 7 (TPS potentiometer output): returns 0 for closed throttle and 255 for wide-open throttle
Can anyone suggest any improvements?
The code does seem to read from channel 2 and 6. I traced where channel 6 goes on my board, and it looks like it goes to ground through a 6 kOhm resistor.
DME/KLR data logging
Slight correction, you would be getting the knock sensor installation blink code, not the noisy engine one. Here's what I've come up with after a quick look. The register r2 holds the blink code value which you can just read off as 2 hex digits - in other words when r2=22, that corresponds to the blink code 2 - 2 as seen in the documentation.
So it looks like 119 is the minimum threshold for the knock sensor signal - any higher than that (i.e. weaker signal) and the KLR assumes the sensor is not connected.
Then 5 is the max - any lower than that (i.e a stronger signal) and the engine is too noisy
Here's the code that effectively decides whether to trigger a blink code - if carry is not set then it doesn't do anything:
Relevant blink codes:
So it looks like 119 is the minimum threshold for the knock sensor signal - any higher than that (i.e. weaker signal) and the KLR assumes the sensor is not connected.
Then 5 is the max - any lower than that (i.e a stronger signal) and the engine is too noisy
Here's the code that effectively decides whether to trigger a blink code - if carry is not set then it doesn't do anything:
Relevant blink codes:
Last edited by johnb on Sat Feb 07, 2026 3:19 pm, edited 1 time in total.
Hi Tom - sounds good. I’ll do a klr schematic if I can get one of your klrs for a few weeks.Tom wrote: Sat Feb 07, 2026 2:25 pmWell, I'm open to helping all if I can, but that was honestly directed to whalenlg since he lives down the road from meandyb wrote: Sat Feb 07, 2026 2:16 pmIf that was addressed to me, that is a very kind offer. But I don't really need one. I've currently got the one from my car on my desk. What I really need to do is to put it back in the car, without its metal box and probe it with a 'scope like John has done. But that would involve getting cold and damp at the moment.![]()
1986 951 - Silicon Valley
- Tom
- Site Admin
- Posts: 8912
- Joined: Fri Jun 25, 2021 2:04 pm
- Location: Silicon Valley, CA
- Has thanked: 931 times
- Been thanked: 3988 times
- Contact:
Awesome. You'll have to post it here of course, with a nice big Carpokes watermark on it...whalenlg wrote: Sat Feb 07, 2026 3:18 pmHi Tom - sounds good. I’ll do a klr schematic if I can get one of your klrs for a few weeks.Tom wrote: Sat Feb 07, 2026 2:25 pmWell, I'm open to helping all if I can, but that was honestly directed to whalenlg since he lives down the road from meandyb wrote: Sat Feb 07, 2026 2:16 pm
If that was addressed to me, that is a very kind offer. But I don't really need one. I've currently got the one from my car on my desk. What I really need to do is to put it back in the car, without its metal box and probe it with a 'scope like John has done. But that would involve getting cold and damp at the moment.![]()
Thanks for that. I guess getting the blink codes to do the right thing in simulation is a good way to test my simulator.johnb wrote: Sat Feb 07, 2026 3:17 pm Slight correction, you would be getting the knock sensor installation blink code, not the noisy engine one. Here's what I've come up with after a quick look. The register r2 holds the blink code value which you can just read off as 2 hex digits - in other words when r2=22, that corresponds to the blink code 2 - 2 as seen in the documentation.
The blink code output was entirely wrong. There were random timings between the on and off edges.
Whilst stepping through the 8048 code you mentioned, I saw that the timer interrupts were failing sometimes. It turns out the 8048 core simulation I got off the internet wasn't entirely correct. I fixed two bugs but was still concerned about the quality of that code. So, after some work, I'm now using the latest 8048 simulation code from MAME, but cut-down to make it do only what is needed for this project. The MAME code looks a lot more likely to be correct (enough).
Now I get more sensible blink code output. Still not convinced its right.
Anyway, I just wanted to say I haven't got bored and given up yet. I've got more things to test.
I think I'm starting to understand this code. Would I be right in saying that I'll only get the either of the knock sensor failure blink codes if the RPM is above about 4000? If it is lower than that, the jump at 0x21a is taken, which skips the knock sensor section. That jump is doing "if ram[0x44] > 28 then jump", which is looking at the RPM axis.johnb wrote: Sat Feb 07, 2026 3:17 pm Slight correction, you would be getting the knock sensor installation blink code, not the noisy engine one. Here's what I've come up with after a quick look. The register r2 holds the blink code value which you can just read off as 2 hex digits - in other words when r2=22, that corresponds to the blink code 2 - 2 as seen in the documentation.
I guess the logic is that it needs high RPM to ensure there's enough noise for the knock sensor to definitely register something.
The good news is I didn't find any bugs in my simulator in this session.
That sounds right, although the threshold of 4000 sounds too high to me now. I'll have to double check the 44h values when I get a chance.andyb wrote: Tue Feb 10, 2026 1:58 pmI think I'm starting to understand this code. Would I be right in saying that I'll only get the either of the knock sensor failure blink codes if the RPM is above about 4000? If it is lower than that, the jump at 0x21a is taken, which skips the knock sensor section. That jump is doing "if ram[0x44] > 28 then jump", which is looking at the RPM axis.johnb wrote: Sat Feb 07, 2026 3:17 pm Slight correction, you would be getting the knock sensor installation blink code, not the noisy engine one. Here's what I've come up with after a quick look. The register r2 holds the blink code value which you can just read off as 2 hex digits - in other words when r2=22, that corresponds to the blink code 2 - 2 as seen in the documentation.
I guess the logic is that it needs high RPM to ensure there's enough noise for the knock sensor to definitely register something.
The good news is I didn't find any bugs in my simulator in this session.
Hi Andy/JohnB,
I am seeing something odd in the disassembly - address 9B contains opcode 31, which is a
ADDC A, R1
But the assembly listing shows:
0x9b xchd a,@r1 (which should be opcode D1)
Any idea which is correct?
I am seeing something odd in the disassembly - address 9B contains opcode 31, which is a
ADDC A, R1
But the assembly listing shows:
0x9b xchd a,@r1 (which should be opcode D1)
Any idea which is correct?
1986 951 - Silicon Valley
Are you talking about the KLR code or the DME?whalenlg wrote: Thu Feb 12, 2026 10:27 am Hi Andy/JohnB,
I am seeing something odd in the disassembly - address 9B contains opcode 31, which is a
ADDC A, R1
But the assembly listing shows:
0x9b xchd a,@r1 (which should be opcode D1)
Any idea which is correct?
EDIT, nevermind, I checked the KLR code and it has 31 at 9B so I checked it in the instruction reference[1]:
and
So 31 is xchd a, @r1
[1] https://jhnbyrn.github.io/951-KLR-PAGES ... _Dec78.pdf
Guess I need to triple check at AI responses:
Google:AI Overview
In the Intel MCS-48 (8048/8049/8748) microcomputer instruction set, the opcode 31 (hexadecimal) corresponds to the instruction:
ADD A, R1
Instruction: Add Register 1 to Accumulator.
Description: The contents of working register R1 are added to the contents of the Accumulator (A). The result is stored in the Accumulator.
Flags Affected: Carry (C), Auxiliary Carry (AC), and Zero (Z) flags are updated based on the result.
Size: 1 byte.
Cycles: 1 machine cycle.
Gemini (also Google!):
Good catch. Opcode 31h is INDEX, or more formally, MOVP A, @A.
This is one of the most powerful instructions in the 8048. In the Porsche 951 KLR, it is used to perform Map Lookups. When the CPU needs to find a specific ignition retard value based on boost pressure or RPM, it puts the "index" into the Accumulator and calls MOVP A, @A to fetch the actual value from a table in the ROM.
1. Implementing MOVP A, @A (Opcode 31h)
This is a 2-cycle instruction because it requires a special read from the Program Memory (ROM) instead of the Data Memory (RAM).
The address it reads from is formed by the current page of the PC and the current value of the Accumulator:
Address bits 0–7: Come from the Accumulator.
Address bits 8–11: Come from the current PC's page.
Google:AI Overview
In the Intel MCS-48 (8048/8049/8748) microcomputer instruction set, the opcode 31 (hexadecimal) corresponds to the instruction:
ADD A, R1
Instruction: Add Register 1 to Accumulator.
Description: The contents of working register R1 are added to the contents of the Accumulator (A). The result is stored in the Accumulator.
Flags Affected: Carry (C), Auxiliary Carry (AC), and Zero (Z) flags are updated based on the result.
Size: 1 byte.
Cycles: 1 machine cycle.
Gemini (also Google!):
Good catch. Opcode 31h is INDEX, or more formally, MOVP A, @A.
This is one of the most powerful instructions in the 8048. In the Porsche 951 KLR, it is used to perform Map Lookups. When the CPU needs to find a specific ignition retard value based on boost pressure or RPM, it puts the "index" into the Accumulator and calls MOVP A, @A to fetch the actual value from a table in the ROM.
1. Implementing MOVP A, @A (Opcode 31h)
This is a 2-cycle instruction because it requires a special read from the Program Memory (ROM) instead of the Data Memory (RAM).
The address it reads from is formed by the current page of the PC and the current value of the Accumulator:
Address bits 0–7: Come from the Accumulator.
Address bits 8–11: Come from the current PC's page.
1986 951 - Silicon Valley
