EEVblog Electronics Community Forum

EEVblog => EEVblog Specific => Topic started by: EEVblog on November 05, 2018, 12:34:00 am

Title: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: EEVblog on November 05, 2018, 12:34:00 am
David looks at the pins on the Padauk PMS150 programmer for potential reverse engineering.

TLDR; It doesn't look easy to reverse engineer this protocol, it's messy with lots of voltage levels, as Padauk said it would be.
Just buy the programmer for now!
There is also a Flash/EEPROM re-programmable version of the chip, the PFS154C.

https://www.youtube.com/watch?v=4Zw_W0iaGFM (https://www.youtube.com/watch?v=4Zw_W0iaGFM)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: BrianHG on November 05, 2018, 01:02:01 am
Looks like the first generation PIC16C54 programming levels, with fewer active IOs.  The old PICs used to use half the IOs to be programmed with wacko voltage transients and some analog levels thrown in as well.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ataradov on November 05, 2018, 01:16:54 am
Voltage levels on I/Os are probably not important, they are just matching the supply voltage, but it would probably work fine as long as you cross the threshold.

Just use a logic analyzer to grab their logical level. Clamp it with diodes if needed, although I suspect that simple current limiting resistors will be sufficient.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 05, 2018, 02:53:26 am
Regarding the different voltage levels: Old EPROMs required this, too. For example some algorithms verified if it was programmed correctly at 6V and 4V. So might be that the highest voltage phase is the programming phase, and two other low voltage phases are verify, and maybe a normal voltage phase for reading the ID etc.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Smokey on November 05, 2018, 05:33:43 am
Is anyone else a little confused by this?

Did I miss part of the video or something or did you not tell us how long the total programming time is? 
ms, seconds, tens of seconds?  That's kind of important to get an idea of the amount of data capture required.

Also did you intentionally grab the least capable data acquisition device possible?  We all know that lab is jam packed with high end gear that almost never gets used.  I'm pretty sure there are at least a couple multi-thousand-dollar deep memory 4 channel MSOs with real level triggering on the digital channels that should be more than capable.  I'm also pretty sure you can take the couple 4channel Keysight scopes sitting around, time correlate all the analog channels between scopes, and dump all that to a PC for a full time deep memory data dump.

It's one thing if you want to do some simple Arduino project video for beginners and don't want to scare viewers off by using test equipment they probably won't have.  It's another thing to do a real engineering project like reversing an uC programming procedure with only toy test equipment and then sound surprised when it didn't all just work out and you couldn't get all the data you needed.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 05, 2018, 06:34:02 am
In a Youtube comment David said the big scopes are still all in boxes, because of their move.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Smokey on November 05, 2018, 07:17:14 am
In a Youtube comment David said the big scopes are still all in boxes, because of their move.

Ahhh.  Well that explains some things. 
It would be nice to put a big huge disclaimer at the beginning of the video that you actually know the equipment you are using is not the right tool for the job and will probably never have the capabilities to succeed and that you are really just playing.

Question:
Do you guys typically read the youtube comments?  Mark me as a "no".
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: westfw on November 05, 2018, 08:35:11 am
I think you can probably decide that the pins not present on the SOT-6 package (PA0 (7) and PA7 (2)) are not particularly relevant to the programming spec...  (the programmer may check their presence to determine chip type, but if they were needed for the actual programming, there wouldn't be any way to program the SOT-6 version.)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: HKJ on November 05, 2018, 09:08:25 am
I would look for the actual data protocol first, then the voltage levels and I doubt the chip will remember any state after a power cycle.

The first operation is probably reading some sort of chip identification.
Programming may be split into program memory and one or more configuration memories.
At least data memory needs an address and one or more data bytes for each programming pulse (Address may be auto increment).
Verification can be for each byte/block programmed or another run when finished.
Some programming algorithms consist of short pulses with a verification between each, when data match a couple more pulses are done to secure the data.


If this sort of protocol can be determined, it will probably be easier to see what voltage levels are used for each operation.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ali_asadzadeh on November 05, 2018, 11:44:22 am
Maybe their strategy is to sell programmers :-\ :-\! :-\ Maybe they are copying the analog devices blackfin lines, selling the Dev tools and programmers so high that they would kill the product itself eventually, ask them so share the info! like rigol shard their way of hacking their scope to sell even more!!!! 
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: rjp on November 05, 2018, 12:38:25 pm

There is also a Flash/EEPROM re-programmable version of the chip, the PFS154C.
 

https://lcsc.com/product-detail/Others_PADAUK-Tech-PFS154-S16_C317613.html

thats a ripoff, 11c each in small quantities!
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Whales on November 05, 2018, 03:01:34 pm
The padauk IDE, is AFAIK, the only way to create binaries for this platform.

Does this IDE let you access the output binaries yourself?  Or are they sent to the programmer directly without giving you access?  Comparing these binaries to the data waveforms would be useful.  You could observe if data is being shift-clocked in with the need for extra cycles (or similar).

If not, then finding out how the programming protocol works is only a tiny bit of the puzzle  :-/O 
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: modrobert on November 05, 2018, 04:35:06 pm
Perhaps the programmer uses session encryption to the micro based on a unique serial number (read only) in the micro, to mitigate knockoffs (or "midnight batches" in approved factories) being produced.

Look for differences in initial handshake between different micros in the same batch.

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 05, 2018, 04:43:28 pm
The padauk IDE, is AFAIK, the only way to create binaries for this platform.

Does this IDE let you access the output binaries yourself?  Or are they sent to the programmer directly without giving you access?  Comparing these binaries to the data waveforms would be useful.  You could observe if data is being shift-clocked in with the need for extra cycles (or similar).

If not, then finding out how the programming protocol works is only a tiny bit of the puzzle  :-/O

I guess you can use strings in the IDE, and they probably don't encrypt this, otherwise the microcontroller would be too complex. But even without strings, you can use inline assembler ("nop" etc.). Even if you don't know the encoding of the opcodes (but I guess you could look at the programming file), you could use 3 x command A, 4 x command B, and 5 x command C, and then search for a 3 x, 4 x, 5 x pattern. With this you could even reverse engineer the opcode encoding.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: glarsson on November 05, 2018, 05:55:19 pm
Perhaps the programmer uses session encryption to the micro based on a unique serial number (read only) in the micro, to mitigate knockoffs (or "midnight batches" in approved factories) being produced.
This is a 3¢ micro controller. To cheap to serialize during manufacturing.
Also, is there any economy in cloning a 3¢ part?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 05, 2018, 05:56:31 pm
Hi,

I had a quick look with IDA on the IDE generating the PDK output file after compilation.

The PDK file consists of a 256 byte header containing a 32 byte initialization "key" @0x000000E0

After the header is written the compiled binary is obfuscated (the algorithm used can not be called encryption ;-) using the initialization key from header @0x000000E0 and some magic values like "12345678h" and "55AA" and a lot of 16 bit XORs. It reads 32 byte chunks from the binary and obfuscates them in 4 loops, 2 bytes a at once in 4 statements.

It will not take me long to re-create the en/decrypt for this section, just some days I guess.

Small teaser:

I used the default program for 154C and inserted:

A = 'T';
A = 'E';
A = 'S';
A = 'T';

in the FPPA0 function right after the comment "// Insert Initial Code"

The IDE creates a memory segment of the unencrypted compiled binary @0x7EA90000
The binary section was 4kByte in total initialized with static values (seems they fill up the complete memory region the MCU can hold).

This is what I found somewhere in the memory section after compilation:

542F
452F
532F
542F

(54 = T, 45 = E, 53 = S )

-> first opcode we can learn from this is (seems to be a little endian design):

MOV A,<imm>   ->  <imm> 2F


In case somebody wants to play with IDA, the function to write "encrypted" files with header is located @0x0041B0DE


JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 05, 2018, 09:14:35 pm
Some more opcodes... maybe somebody recognizes them (looks like 14 bits are used per opcode, but it not seems to be a PIC)

00 00 : NOP
67 00 : PCADD A
70 00 : WDRESET
72 00 : PUSHAF
73 00 : POPAF
75 00 : RESET
76 00 : STOPSYS
77 00 : STOPEXE
78 00 : ENGINT
79 00 : DISGINT
7A 00 : RET

9[ I ] 01 : MOV PA,A //IO
D[ I ]01 : MOV A,PA //IO

[PTR]1 03 : IDXM A,PTR
[PTR]0 03 : IDXM PTR,A

[M] 0B : MOV [MEM],A
[M] 0F : MOV A,[MEM]

[M] 13 : XCH M

IM 2F : MOV A,IMM

POS 30 : GOTO POS //POS is on WORDS
POS 38 : CALL POS   //POS is on WORDS

FF 3F : ? ? ? used as filler, maybe invalid opcode

----
I defined a function on top of "Project.C and you can just write assembler inside

void fun(void)
{
  MOV A,'T'
label1:
  MOV A,'E'
  GOTO label1
  //...

  //RET is inserted automatically from miniC
}

The function is placed in compiler output memory directly at start. Just 4 bytes in front of it which looks like this:
00 00  //NOP ?
09 30 //GOTO ...

They seem to come from "Project1.PRE" from the ".JMP FPPA0" directive

----

Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FERCSA on November 05, 2018, 11:19:22 pm
Looks like it's a FPPA, Field Programmable Processor Array.

Here is some useful links:
http://fellong.blogspot.com/2007/07/fppa_14.html (http://fellong.blogspot.com/2007/07/fppa_14.html)
http://www.hy-star.com.tw/tech/MCU/mcu.html (http://www.hy-star.com.tw/tech/MCU/mcu.html)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 06, 2018, 04:26:03 am
The FFPA is their MCS11 chip, with 8 cores. Unfortunately I can't find it anywhere to buy. This would be a very interesting chip, similar to the Parallax Propeller, just a bit smaller, and presumably cheaper. The PMS150 has only one core.

But the more I think about it, I guess they developed it on their own and it is not a PIC clone or a clone of any other microcontroller. They couldn't have used the original die anyway, because PICs need 4 cycles and more per instruction, and the Padauk instruction set claims to need only one cycle for most instructions. And while very similar to the PIC instruction set, they have a few more instructions than PIC, especially their MCS11 flagship, like the wait instruction, which stops the CPU until an IO pin changes, which makes perfect sense for 8 cores, because it makes it easier to write fast bitbanging code for protocols like SPI in one dedicated core for the communication. But it is odd that they do such obfuscating, as if they want to hide something.

Maybe all their chips use the same die, and the other 7 cores are just disabled by software in the lower end chips? This would be a good reason for them not to publish the programming protocol :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: free_electron on November 06, 2018, 03:08:55 pm
This multilevel voltage programming is classic for PROM style devices.
This chip may very well be a true prom ( fuse or charge based ) and not a windowless eprom.

The reason for the multilevel voltages is to prevent accidental in-the-field corruption of the prom due to someone wiggling the pins in the wrong sequence.

They have analog comparators on the io pins used for programming ( simple window comparator made from 2 op-amps and a resistive divider. The op-amps aren't even real op-amps .. more like 4 transistors each, kind of how you make a schmitttrigger structure )

You can initialize and probably 'read' while within normal voltage on VCC. Meaning , below programming voltage. But you can't destroy anything.

Once programming voltage is applied other comparators come into play. These work between VCC and VPP (Programming voltage). One level is used for one function , another level for another function.

for example (hypothetical)
- send command to prepare for programming inside the VCC levels.
- turn on vpp
- set 6 volts on control pin : reset programming shifter
- set 7 volts : enable shifter
- now using the other pin : clock in data
- set 12 volts : burn
- set 9 volts : read back bits into shifter
- set 8 volts : turn shifter around ( the digital pin is now an output and you can read back the bits )

so these voltage all mean something : they control the on-chip programming logic.

This reminds me of the mechanism used to control trim bits in many devices. The advantage is that these voltages never will be applied int he fiedl and the entire 'programming' block is disabled.

the 'programmer' is nothing more than a simple shift register.
The fact that you pass from 5 volts VCC to 7 means you transitioned through 6 and thus caused a reset !!!

Then reverse engineering this be mindful of that.. if you see more than 1 level change : they have transitioned through a state !.

They could also use a multilevel self clocking mechanism.
 rise to 8 means  clock in a 0 . drop to 6 means clock in a 1. rising or dropping back to 7 means : advance counter a tick....

so the sequence
Code: [Select]

7878786768676867
 0 0 01 101 101
if the voltage transitions directly form 6 to 8 or 8 to 6 there is an implied '7' meaning : clock !  be weary of these things.
The on-board electronics is kept to a minimum in  area.... to make the chip cheap.

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: glarsson on November 06, 2018, 03:16:47 pm
IF this device is a fusible link PROM device then it probably requires well controlled slopes on the programming pulse. Too fast rise time and the metal splashes over the silicon. Too slow damages the silicon due to localized heating or the bit will not program correctly.

Are fusible link PROMs manufactured today?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: TK on November 06, 2018, 03:31:03 pm
Padauk is not making any money selling the programmer, so why don't ask them for the programming protocol?  Adding support for  universal programmers like TL866 can help sell tons of 3cent microcontrollers.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: PA0PBZ on November 06, 2018, 03:31:27 pm
It looks to me that a lot could be learned from the original programmer, like how the pins are controlled?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ataradov on November 06, 2018, 04:25:55 pm
Padauk is not making any money selling the programmer, so why don't ask them for the programming protocol?
The have been asked and they refused to provide any information.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: SiliconWizard on November 06, 2018, 07:11:09 pm
It's unclear to me what incentive they would have to publicly release the programming protocol though. It usually ends up being more hassle than benefits for a tech company. And here I don't think that the kind of customers interested in devising their own tools are the ones who would buy their MCUs by the millions. So...

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ataradov on November 06, 2018, 07:19:09 pm
It usually ends up being more hassle than benefits for a tech company.
Tell that to Espressif. They were hiding stuff at first too, and then they quickly realized the power of the passionate community.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: drussell on November 06, 2018, 08:31:17 pm
Adding support for  universal programmers like TL866 can help sell tons of 3cent microcontrollers.

No, it won't.  People don't one-off program things like this except in development and prototyping.  These are the kind of chip that you order by the thousands, pre-programmed with whatever code you need for your application.  99.9999% of these chips sold need to be programmed at high speed, in bulk, not one-offs in some desktop programmer, that simply makes no sense.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: drussell on November 06, 2018, 08:34:42 pm
It's unclear to me what incentive they would have to publicly release the programming protocol though. It usually ends up being more hassle than benefits for a tech company. And here I don't think that the kind of customers interested in devising their own tools are the ones who would buy their MCUs by the millions. So...

Well, the people that buy them in the millions are going to get them mass-programmed, which the manufacturer or distributor will be set up with the equipment to do for you.  If you were using millions and wanted to program them in-house for some bizarre reason, they would still help you by either supplying the equipment or the engineering data to do that but that's very different than programming one-offs in a desktop programmer.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 06, 2018, 11:16:08 pm
Hi,

For those curious people I wrote a little deobfuscator for PDK files (the compiled binary you get from IDE).

It's a command line utility called depdk which requires 2 parameters: inputfile and outputfile.

Example: ./depdk input.pdk output.bin

The header from the PDK file is thrown away and just the real (deobfuscated) binary data (which is written to the MCU) is written to the output file.

Compilation with gcc -o depdk depdk.c

Or use the attached compiled executable for Windows.

Have fun,

JS  8)

depdk.c

#include <stdio.h>
 #include <stdint.h>
 #include <string.h>

int main( int argc, const char * argv [] )
{
  if( 3 != argc ) {
    printf("usage: %s inputfile outputfile\n\n", argv[0]);
    return 0;
  }

  FILE* fin = fopen( argv[1], "rb");
  if( !fin ) { printf("Could not open %s for reading.\n", argv[1]); return -1; }

  FILE* fout = fopen( argv[2], "wb");
  if( !fin ) { printf("Could not open %s for writing.\n", argv[2]); return -1; }

  uint8_t hdrdata[0x100];
  if( sizeof(hdrdata) != fread( hdrdata, 1, sizeof(hdrdata), fin ) ) {
    printf("Error reading input file\n");
    return -1;
  }

  uint32_t version = *((uint32_t*)&hdrdata[0x08]);
  uint32_t datalen = *((uint32_t*)&hdrdata[0x20]);

  uint32_t extrahdr = *((uint16_t*)&hdrdata[0x26]) +
                      *((uint16_t*)&hdrdata[0x28]) +
                      *((uint16_t*)&hdrdata[0x2C]) +
                      *((uint16_t*)&hdrdata[0xD0]);
  if( version>=0x1c )
    extrahdr += *((uint8_t*)&hdrdata[0x49]);

  fseek( fin, extrahdr, SEEK_CUR );

  uint16_t key[0x10];
  memcpy( key, &hdrdata[0xE0], sizeof(key) );

  uint16_t kxorw7C92 = key[3]^key[14];
  uint16_t kxorw7E8A = key[7]^key[15];

  if( (version>=0x15) && (version<=0x17) ) {
    kxorw7C92 ^= 0x1234; kxorw7E8A ^= 0x5678;
  }

  uint16_t keyindex = 0;

  for( uint32_t fullpos=0; fullpos<datalen; fullpos+=32 ) {
    uint16_t data[0x20];
    if( sizeof(data) != fread( data, 1, sizeof(data), fin ) )
      break;

    uint32_t dataptr = 0;
    for( uint32_t j=0; j<4; j++ ) {
      uint16_t tmp_xor_key1;
      uint16_t tmp_xor_key2;

      keyindex += kxorw7C92;
      tmp_xor_key1 = data[dataptr];
      data[dataptr] += key[keyindex&0xF];
      dataptr++;
      key[fullpos&0xF] ^= tmp_xor_key1;

      keyindex += tmp_xor_key1;
      tmp_xor_key2 = data[dataptr];
      data[dataptr] = (data[dataptr] + kxorw7E8A ) ^ key[keyindex&0xF];
      dataptr++;
      key[kxorw7E8A&0xF] ^= kxorw7C92;

      keyindex ^= tmp_xor_key2;
      kxorw7C92 = data[dataptr];
      data[dataptr] += key[keyindex&0xF];
      dataptr++;
      key[kxorw7E8A&0xF] ^= 0x55AA;

      keyindex = (keyindex + kxorw7C92)>>1;
      kxorw7E8A = data[dataptr];
      data[dataptr] = (data[dataptr] - tmp_xor_key1) ^ key[keyindex&0xF];
      dataptr++;

      keyindex += kxorw7E8A;
      tmp_xor_key1 = data[dataptr];
      data[dataptr] ^= key[keyindex&0xF];
      dataptr++;
      key[kxorw7C92&0xF] += kxorw7E8A;

      keyindex ^= tmp_xor_key1;
      tmp_xor_key2 = data[dataptr];
      data[dataptr] = (data[dataptr] ^ kxorw7E8A) ^ key[keyindex&0xF];
      dataptr++;
      key[tmp_xor_key2&0xF] ^= tmp_xor_key1;

      keyindex ^= tmp_xor_key2;
      kxorw7C92 = data[dataptr];
      data[dataptr] += key[keyindex&0xF];
      dataptr++;
      key[tmp_xor_key1&0xF] += tmp_xor_key2;

      keyindex += kxorw7C92;
      kxorw7E8A = data[dataptr];
      data[dataptr] = (data[dataptr] + tmp_xor_key1) ^ key[keyindex&0xF];
      dataptr++;

      key[2] ^= tmp_xor_key1;
      key[4] += tmp_xor_key2;
      key[6] += kxorw7E8A;
      key[8] -= kxorw7C92;
      key[1] ^= key[15];
      key[3] ^= key[14];
      key[5] ^= key[13];
      keyindex += j;
    }

    if( sizeof(data) != fwrite( data, 1, sizeof(data), fout ) ) {
      printf("Error writing output file\n");
      return -1;
    }
  }

  fclose(fin);
  fclose(fout);

  return 0;
}

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 06, 2018, 11:53:47 pm
Just some useful info for understanding the MCU family and how to program it:

http://svn2.assembla.com/svn/mcu/ (http://svn2.assembla.com/svn/mcu/)

The examples using older processor types with 8 cores but most of it should be "understandbale"

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: SeoulBigChris on November 07, 2018, 02:27:30 am
It's unclear to me what incentive they would have to publicly release the programming protocol though. It usually ends up being more hassle than benefits for a tech company. And here I don't think that the kind of customers interested in devising their own tools are the ones who would buy their MCUs by the millions. So...

Disclaimer: I’ve never run a semiconductor company.

My reaction is the opposite, when I see policies like this. As far as I know, Paduk is in the business of selling semiconductors, not programmers. I contend that it’s more hassle to maintain a closed programming protocol. This forces you into the chip programmer business, taking your attention away from your core competency. Releasing the protocol so the various chip programmer companies and hobbyists can support your ICs should reduce their hassle, not increase it.

I have a similar take on providing a custom and apparently closed compiler. Do they have aspirations of becoming a compiler company as well?

I suppose it’s possible that the insides of their chips are so revolutionary and proprietary, that opening up these protocols would be akin to revealing their trade secrets. But I think that’s unlikely in this case.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ataradov on November 07, 2018, 02:31:45 am
With western companies there is a pretty benign explanation for why they don't release even the most trivial things - releasing something implies you will provide support. For whatever reason a concept of releasing things "as is" is not accepted.

But I doubt this is a problem for Padauk. Chinese companies have a habit of releasing a product and not providing any obvious support to the general public. And I like it - it lets us have products that we otherwise would not see, even if they are not well documented.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: SiliconWizard on November 07, 2018, 03:19:29 am
With western companies there is a pretty benign explanation for why they don't release even the most trivial things - releasing something implies you will provide support. For whatever reason a concept of releasing things "as is" is not accepted.

Yes, thus my "more hassle than benefits" point above.
Even if it's made clear you won't provide direct support, you're bound to one way or another. You will inevitably run into customers that will ask for tech support and make you waste significant time until they end up admitting they use unsupported tools.

But I doubt this is a problem for Padauk. Chinese companies have a habit of releasing a product and not providing any obvious support to the general public. And I like it - it lets us have products that we otherwise would not see, even if they are not well documented.

Possibly, but again why would they? That would still take some time to gather the bits and pieces in a consumable form for third parties, and possibly bother with uploading updates on a regular basis, etc. They may not even have a proper internal documentation themselves (that would be bad, but yes, that really happens!)

And I doubt they are interested in customers that will buy for a few bucks of their ICs.  ;D I also doubt that, maybe contrary to Espressif that have different products and targets, a large community of small companies or even amateur users would really help their business.
 :-//
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Bud on November 07, 2018, 06:02:35 am
The video was painful to watch. Too many cuts.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 11, 2018, 06:21:36 am
I contacted Padauk, will get a programmer and an ICE (unfortunately you need a different ICE than the one you can use for the PMS150C) for their new PMC884 chip with 8 cores and samples of the chip. Joe from Padauk sent me a datasheet for it. It is a bit strange why they don't publish it on their webpage: He says because it can be too difficult to program, maybe they don't want too many support requests. Anyway, he says the datasheet is not confidential and I'm allowed to show it to others for review:

http://www.frank-buss.de/tmp/pmc884.pdf (http://www.frank-buss.de/tmp/pmc884.pdf)

It is not really a multi-core chip, more like a mult-thread chip, because e.g. if you enable 2 cores and run it at 8 MHz, each core will run effectively at 4 MHz, round-robin. But still very useful for things like bitbanging on one core and application logic on another core, without the overhead of interrupts or complicated programming.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Hypernova on November 11, 2018, 02:47:50 pm
he says the datasheet is not confidential and I'm allowed to show it to others for review

Funny as the red watermark on every page reads "PADAUK confidential document"
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Sjaak on November 11, 2018, 04:52:55 pm
How about disassembling the programmer? Not expecting a regular mcu in there that can be read back but can give some clues howmany voltage levels there are, and even some silkscreen markings that provide info about signalnames.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 12, 2018, 05:40:10 am
Funny as the red watermark on every page reads "PADAUK confidential document"

Maybe it was confidential at some point, but it really doesn't make sense to hide it. This hardware thread concept looks very useful to simplify application development, without much drawbacks for power consumption or issues with real parallel cores, like synchronization and race conditions etc.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: Hypernova on November 12, 2018, 02:44:36 pm
Funny as the red watermark on every page reads "PADAUK confidential document"

Maybe it was confidential at some point, but it really doesn't make sense to hide it. This hardware thread concept looks very useful to simplify application development, without much drawbacks for power consumption or issues with real parallel cores, like synchronization and race conditions etc.

What they made is a Barrel Processor (https://en.wikipedia.org/wiki/Barrel_processor) which is a pretty old concept, so not sure what they have to hide. I have a real dislike for companies that take the confidential-by-default route.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 12, 2018, 08:15:50 pm
This is interesting, I didn't know the barrel processor concept.

The datasheet for the PMC884 says at one position it is patent pending, and at another position it is patented. I couldn't find an existing patent, only this:

https://patents.google.com/patent/US20050166170

Has the same name (FPPA), but looks like something completely different. But with the barrel processor I wonder if this counts as prior art and they can't patent it.

Meanwhile Joe told me the price for the PMC884: it is US$0.40 in larger quantities (but less than 100k). Don't know if this makes sense, because you could get 13 of the cheap 3 cent PMS150C for this price :) But might be still useful if you need it small in one IC.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 14, 2018, 03:34:33 pm
I found some strings in "USB_Driver" folder inside of "Writer.PDK" (can be deobfuscated with small modified depdk).

Looks like the programmer uses 5V, 7.5V for VDD and 8V, 12V for VP (programing)

<<<  IC O.K. >>>
F/W Ver : 1.23 
DC Power Fail. 
DC Low Power.   
DC High Power. 
H/W VDD keep Hi.
H/W VD 5V fail.
H/W VDD 7V5 fail
H/W VDD 5V fail.
H/W VP 8V fail.
H/W VP 12V fail.


Maybe this helps interpreting the captured data.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: atc1441 on November 14, 2018, 06:36:19 pm
Hi, i think i found one Padauk chip in the wild.

It is in one of these STC Auto Programmer USB-TTL but i am not 100% shure eBay auction: #202070246074


As you see in the attachment the pinout is the same it is the tsop8 chip the other one is an CH340 Clone
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 16, 2018, 04:41:58 pm
Hi, I spent some time (actually a lot more than I wanted) to find out and write down all known instructions for the small type (1 core) processors (1 core processors start with a "1" like PMC154. PMC2... has 2 cores and PDK8... has 8 cores ).

The 1 core processors (the cheap ones ;-) ) do have a compact (14-bit) instruction set. The multi core processors seem to have a 16-bit instruction set.
Note: 14/16 bit instructions does not mean it is a 14/16 bit processor. They are all tiny 8 bit processors. Just the length of one instruction is 14/16 bit.

Here is a direct link:

https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html  :) :) :)


I also created a github project. Everybody is invited to contribute:

https://github.com/free-pdk

It just started with a single "documentation" repository. Next might be a disassembler and a simulator.


Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 16, 2018, 04:55:58 pm
That's really nice, you can add me if you like, my github name: FrankBuss
I could try to implement a FPGA emulation for it. This would allow realtime simulation in hardware (except for the ADCs) of the chip with all peripherals.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: rhodges on November 16, 2018, 05:00:15 pm
Quote
Here is a direct link:
https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html  :) :) :)
Nice work! It looks like you might have all the important instructions decoded. Maybe it would be useful to have a program to parse the compiler output every time and alert if a "new" instruction comes out. After a while, we could be pretty confident about the instruction coding.

Thanks! I recently decided to move from PIC to STM8 for personal projects, but you are tempting me to rotate my brain 90 degrees to go back to PIC thinking...
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: chicken on November 16, 2018, 05:10:34 pm
I'm tempted to add support for this architecture to radare2. https://github.com/radare/radare2
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 16, 2018, 05:27:17 pm
It looks like you might have all the important instructions decoded. Maybe it would be useful to have a program to parse the compiler output every time and alert if a "new" instruction comes out. After a while, we could be pretty confident about the instruction coding.

Actually I used the data sheets of all PMC/PMS1xx processors and typed in every possible instruction in the IDE and monitored the compiler output. So for sure the compiler will not generate more / unknown instructions from our code.

The holes are most likely unused spaces or instructions which they planned to implement but did not work out correctly. For instance AND IO,A / AND A,IO / OR IA,A / OR A,IO  are somehow missing and would fit perfectly in the "0x0100...0x017F" hole.

One way to try the "undocumented" instructions is to manually create the binary, inject these instructions and observe the result (like it was done decades ago for 6502).
Since OTP would be a bit painful for this I already ordered the FLASH based PFS154 (now waiting for it to arrive).

On the other hand, if the normal compiler does not create them, also a disassembler does not need to know them. Invalid instructions are a common thing which even exist on modern CPUs like ARM and Intel.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 16, 2018, 05:49:38 pm
Hi thank you for your work thus far.

@ js_12345678_55AA: Could you post the modifications you made to deobfuscate the PDKs in the USB_Driver directory?

Also: in the USB_Driver/USB directory there seems to be the firmware for the programmer (in obfuscated form):

P5SP_BOOT_UPDATER.fw
P5SP_G1.fw
P5SP_G2.fw
P5SP_TESTER.fw

from Dave's video the P5SP files could be for an STM32F072V8T6
and from the strings in the FPPA_IDE.EXE it seems to know how to upload them to the programmer
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 16, 2018, 08:22:00 pm
From the strings in FPPA_IDE.exe you can also gather voltage information from their test program of the programmer (P5SP_tester.fw):

0x63421c 70 69 Please remove all IC, and check VDD,\nVPP(PA5), PA0 / 3 / 4 / 7 is 0 V
0x634264 30 29 Please check VPP (PA5) = 4.6V
0x634284 31 30 Please check VPP (PA5) = 11.3V
0x6342a4 24 23 Please check VDD = 5.5V
0x6342bc 24 23 Please check VDD = 7.5V
0x6342d4 24 23 Please check VDD = 3.3V

and a list of instructions:

0x62dac0 16 15 MOV__A__IO_LIST
0x62dad0 16 15 MOV__IO_LIST__A
0x62dae0 16 15 XOR__A__IO_LIST
0x62daf0 16 15 XOR__IO_LIST__A
0x62db00 14 13 MOV__A__CONST
0x62db10 17 16 MOV__A__RAM_BYTE
0x62db24 17 16 MOV__RAM_BYTE__A
0x62db38 18 17 NMOV__A__RAM_BYTE
0x62db4c 18 17 NMOV__RAM_BYTE__A
0x62db60 18 17 IDXM__A__RAM_WORD
0x62db74 18 17 IDXM__RAM_WORD__A
0x62db88 17 16 LDTABL__RAM_WORD
0x62db9c 17 16 LDTABH__RAM_WORD
0x62dbb0 16 15 PUSHW__RAM_WORD
0x62dbc0 15 14 POPW__RAM_WORD
0x62dbd0 11 10 PUSHW__PCX
0x62dbdc 10 9 POPW__PCX
0x62dbe8 7 6 PUSHAF
0x62dbf0 6 5 POPAF
0x62dbf8 17 16 AND__A__RAM_BYTE
0x62dc0c 17 16 AND__RAM_BYTE__A
0x62dc20 14 13 AND__A__CONST
0x62dc30 16 15 OR__A__RAM_BYTE
0x62dc40 16 15 OR__RAM_BYTE__A
0x62dc50 13 12 OR__A__CONST
0x62dc60 17 16 XOR__A__RAM_BYTE
0x62dc74 17 16 XOR__RAM_BYTE__A
0x62dc88 14 13 XOR__A__CONST
0x62dc98 7 6 NOT__A
0x62dca0 14 13 NOT__RAM_BYTE
0x62dcb0 8 7 NEGC__A
0x62dcb8 7 6 NEG__A
0x62dcc0 15 14 NEGC__RAM_BYTE
0x62dcd0 14 13 NEG__RAM_BYTE
0x62dce0 16 15 CLEAR__RAM_BYTE
0x62dcf0 14 13 XCH__RAM_BYTE
0x62dd00 8 7 SWAP__A
0x62dd08 15 14 SWAP__RAM_BYTE
0x62dd18 6 5 SR__A
0x62dd20 13 12 SR__RAM_BYTE
0x62dd30 6 5 SL__A
0x62dd38 13 12 SL__RAM_BYTE
0x62dd48 7 6 SRC__A
0x62dd50 14 13 SRC__RAM_BYTE
0x62dd60 7 6 SLC__A
0x62dd68 14 13 SLC__RAM_BYTE
0x62dd78 18 17 NADD__A__RAM_BYTE
0x62dd8c 18 17 NADD__RAM_BYTE__A
0x62dda0 8 7 ADDC__A
0x62dda8 15 14 ADDC__RAM_BYTE
0x62ddb8 18 17 ADDC__A__RAM_BYTE
0x62ddcc 18 17 ADDC__RAM_BYTE__A
0x62dde0 8 7 SUBC__A
0x62dde8 15 14 SUBC__RAM_BYTE
0x62ddf8 18 17 SUBC__A__RAM_BYTE
0x62de0c 18 17 SUBC__RAM_BYTE__A
0x62de20 17 16 ADD__A__RAM_BYTE
0x62de34 17 16 ADD__RAM_BYTE__A
0x62de48 14 13 ADD__A__CONST
0x62de58 17 16 SUB__A__RAM_BYTE
0x62de6c 17 16 SUB__RAM_BYTE__A
0x62de80 14 13 SUB__A__CONST
0x62de90 14 13 INC__RAM_BYTE
0x62dea0 14 13 DEC__RAM_BYTE
0x62deb0 15 14 IZSN__RAM_BYTE
0x62dec0 8 7 IZSN__A
0x62dec8 15 14 DZSN__RAM_BYTE
0x62ded8 8 7 DZSN__A
0x62dee0 15 14 COMP__A__CONST
0x62def0 18 17 COMP__A__RAM_BYTE
0x62df04 18 17 COMP__RAM_BYTE__A
0x62df18 13 12 DELAY__CONST
0x62df28 16 15 DELAY__RAM_BYTE
0x62df38 9 8 DELAY__A
0x62df44 9 8 T0SN__CF
0x62df50 9 8 T1SN__CF
0x62df5c 9 8 T0SN__ZF
0x62df68 9 8 T1SN__ZF
0x62df74 9 8 SET0__CF
0x62df80 9 8 SET1__CF
0x62df8c 9 8 SET0__ZF
0x62df98 9 8 SET1__ZF
0x62dfa4 8 7 TOG__ZF
0x62dfac 8 7 TOG__CF
0x62dfb4 17 16 T0SN__IOBIT_LIST
0x62dfc8 17 16 T1SN__IOBIT_LIST
0x62dfdc 17 16 SET0__IOBIT_LIST
0x62dff0 17 16 SET1__IOBIT_LIST
0x62e004 16 15 TOG__IOBIT_LIST
0x62e014 18 17 SWAPC__IOBIT_LIST
0x62e028 18 17 WAIT0__IOBIT_LIST
0x62e03c 18 17 WAIT1__IOBIT_LIST
0x62e050 14 13 T0SN__RAM_BIT
0x62e060 14 13 T1SN__RAM_BIT
0x62e070 14 13 SET0__RAM_BIT
0x62e080 14 13 SET1__RAM_BIT
0x62e090 19 18 CEQSN__A__RAM_BYTE
0x62e0a4 16 15 CEQSN__A__CONST
0x62e0b4 20 19 CNEQSN__A__RAM_BYTE
0x62e0c8 17 16 CNEQSN__A__CONST
0x62e0dc 14 13 GOTO__ADR_ABS
0x62e0ec 14 13 GOTO__ADR_OFS
0x62e0fc 16 15 IGOTO__RAM_WORD
0x62e10c 14 13 CALL__ADR_ABS
0x62e11c 14 13 CALL__ADR_OFS
0x62e12c 16 15 ICALL__RAM_WORD
0x62e13c 15 14 LGOTO__ADR_ABS
0x62e14c 15 14 LCALL__ADR_ABS
0x62e160 5 4 RETI
0x62e168 11 10 RET__CONST
0x62e174 14 13 PMODE__P_MODE
0x62e184 8 7 STOPSYS
0x62e18c 8 7 STOPEXE
0x62e194 16 15 LDT16__RAM_WORD
0x62e1a4 16 15 STT16__RAM_WORD
0x62e1b4 7 6 ENGINT
0x62e1bc 8 7 DISGINT
0x62e1c4 8 7 WDRESET
0x62e1cc 6 5 RESET
0x62e1dc 9 8 PCADD__A

There are also quite a few compiler directives, but they are all over the place
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 16, 2018, 09:20:47 pm
The instruction list above seems to be a generic one, describing all theoretically available instructions.
The actually available instructions for a specific chip are given by the specific inc file in the INC_PDK directory and the symbol file (defined in the inc file and located in the Symbol directory)
(There is a lot of additional data in that file, maybe they also define what address modes can be used and which instruction can also use flags or io's as operands etc.)

example:
PMS150C (44 Instructions)
INSTRUCTION
CALL
GOTO
ADD
SUB
CEQSN
AND
OR
XOR
MOV
T0SN
T1SN
SET0
SET1
ADDC
SUBC
IZSN
DZSN
INC
DEC
CLEAR
XCH
NOT
NEG
SRC
SLC
RET
IDXM
STT16
LDT16
WDRESET
PUSHAF
POPAF
RESET
STOPSYS
STOPEXE
ENGINT
DISGINT
RETI
PCADD
SWAP
TRAP
NOP
LDSPTL
LDSPTH

PFS154 (52 Instructions)
INSTRUCTION
CALL
GOTO
ADD
SUB
CEQSN
CNEQSN
AND
OR
XOR
MOV
T0SN
T1SN
SET0
SET1
ADDC
SUBC
IZSN
DZSN
INC
DEC
CLEAR
XCH
NOT
NEG
SRC
SLC
NADD
COMP
SWAP
STT16
LDT16
IDXM
RET
LDTABL
LDTABH
WDRESET
PUSHAF
POPAF
RESET
STOPSYS
STOPEXE
ENGINT
DISGINT
RETI
MUL
NEGC
PCADD
SWAP
TRAP
NOP
LDSPTL
LDSPTH
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 16, 2018, 11:01:10 pm
Found 2 more instructions which are not in manual:

LDSPTL   0x0006
LDSPTH  0x0007

They are fixed instructions with no arguments.

Speculation...
Looks like it is a syntax which uses L and H 
Since the stack pointer is mapped on IO 0x02 and does not have High or Low, the "SP" inside the name might me misleading

----
There are 2 more undocumented instructions which the IDE knows but refuses to compile. I tried many many different 1xx processors:

WORD data
...

LDTABL  data
LDTABH  data

Compiler always says: "The 'LDTABx' not be supported at PFS154" (for every 1xx processor I tried)

All other instructions from the list are already mapped.

One special exception is the "TRAP" instruction. The IDE just put's a "NOP" inside the binary. I assume this is used for the ICE only... so need to wait for my ICE to arrive ;D
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 16, 2018, 11:12:27 pm
@ js_12345678_55AA: Could you post the modifications you made to deobfuscate the PDKs in the USB_Driver directory?

I updated the initial post (both source and windows binary)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 08:58:02 am
Speaking of ICE
The USB_Driver/USB directory also seems to contain the firmware for the ICE (*.usb and *.hid files)
As far as I can tell this should be firmware for an Cypress EZ-USB FX2LP Chip CY7C68013A (8051 code) it is not obfuscated.

I assume that the ICE*PDK files are for GAL/PAL/FPGA device seen in the video of the ICE. (Cypress even markets the chip as an FPGA companion "Booting an FPGA from FX2LP" so probably an FPGA.

AN63620 - Configuring a Xilinx Spartan-3E FPGA Over USB Using EZ-USB FX2LP™:
"This  application  note  demonstrates  a  technique  for  dynamically  configuring  a  Xilinx  Spartan-3E  Field  Programmable  Gate Array  (FPGA)  over  USB  using  EZ-USB  FX2LP,  a  high-speed  USB  peripheral  controller.  After  the  FPGA  is  configured, FX2LP  can  act  as  a  high-speed  data  path  between  the  USB  host  and  the  FPGA.  This  capability of  FX2LP  enhances 
FPGA-based USB applications such as logical analyzers, oscilloscopes, image processing,
and high-speed data acquisition."

They are all wildly different from each other, which would make sense if they all are for differnt cores.
The file sizes are however all divisible by 64 -> Logic cells/blocks?




ICE_3.usb and WRITER_5.usb on the other hand are almost identical, so I assume thats for the same thing (as far as I understand thats the multicore ICE)

ICE5.fw would then be the obfuscated single core firmware for the ICE that Dave has. It seems that they still use a Cypress FX2 chip, so probably almost identical to ICE_3.usb.
Maybe that helps with deobfuscation.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 17, 2018, 10:55:58 am

@ js_12345678_55AA:

Also: in the USB_Driver/USB directory there seems to be the firmware for the programmer (in obfuscated form):

P5SP_BOOT_UPDATER.fw
P5SP_G1.fw
P5SP_G2.fw
P5SP_TESTER.fw

from Dave's video the P5SP files could be for an STM32F072V8T6

You asked for it... here it is:

It's a command line utility called defw which requires 2 parameters: inputfile and outputfile.

Example: ./defw input.fw output.bin

Compilation with gcc -o defw defw.c

Or use the attached compiled executable for Windows.

Have fun,

JS  8)

P.S. works for all *.fw files and also the *.hid files in "USB_Driver/USB" directory. All other files (*.usb) there seem not to be obfuscated. For the PDK files use "depdk".

defw.c


 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>

int main( int argc, const char * argv [] )
{
  if( 3 != argc ) {
    printf("usage: %s inputfile outputfile\n\n", argv[0]);
    return 0;
  }

  FILE* fin = fopen( argv[1], "rb");
  if( !fin ) { printf("Could not open %s for reading.\n", argv[1]); return -1; }

  FILE* fout = fopen( argv[2], "wb");
  if( !fin ) { printf("Could not open %s for writing.\n", argv[2]); return -1; }
 
  uint16_t data[0x10000];
  int lenwords = fread( data, sizeof(uint16_t), sizeof(data)/sizeof(uint16_t), fin );
  if( lenwords<=0 ) {
     printf("Could not read %s.\n", argv[1]); return -1;
  }

  for( uint32_t i=0; i<lenwords; i++ ) {
    data[ i ] ^= i;
    if( i & 1 ) data[ i ] ^= 0x55;
    else
    if( i & 2 ) data[ i ] ^= 0xAA23;
    else
    if( i & 4 ) data[ i ] ^= 0x3759;
    else
      data[ i ] ^= 0xAFCD;
    data[ i ] ^= (lenwords-i-1)<<3;
  }
   
  if( lenwords != fwrite( data, sizeof(uint16_t), lenwords, fout ) ) {
    printf("Error writing output file\n");
    return -1;
  }

  fclose(fin);
  fclose(fout);

  return 0;
}



... it is indeed STM32 firmware in there :-)


Edit: fixed forum formatting of data[ i ]
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 17, 2018, 11:07:18 am
Hi,

seems youtuber "bigclivedotcom" spotted a PADAUK MCU containing device in the wild:

https://www.youtube.com/watch?v=gJKy20wfIvg (https://www.youtube.com/watch?v=gJKy20wfIvg)

 :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 11:24:16 am
Hey thanks!

Whats interesting is that there is a "simple emulator" that isnt available anywhere:
5S-I-S0 2B

http://www.padauk.com.tw//upload/ICEmanual/5S-ICE_UM_EN_V002_20181105.pdf (http://www.padauk.com.tw//upload/ICEmanual/5S-ICE_UM_EN_V002_20181105.pdf) (page 15)

But: there is an dev board with Cypress FX2 Chip
https://de.aliexpress.com/wholesale?catId=0&SearchText=EZ-USB+FX2LP+CY7C68013A (https://de.aliexpress.com/wholesale?catId=0&SearchText=EZ-USB+FX2LP+CY7C68013A)
for ~3.5 USD

If we can find out what FPGA they use  :popcorn:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 11:29:38 am
small error:
data ^= ...
should read
 data square brackets i ^= ... (Forum doesnt let me post square brackets  :-//)
fixed locally and seems to work
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 11:40:55 am
and more voltages appear:
T:CN5/CN6
VPP_PWR != 11V
T:CN7
T:CN12/CN6/CN5
VPP_PWR != 0V
VDD_PWR != 7.8V
T:CN11
T:CN11/CN4/CN3
VDD_PWR != 0V
HVPP_IC != 11V
T:IC_PA5
T:Q32
VPP_IC != 0V
VDD_IC != 7.8V
T:IC_VDD
T:Q9
VDD_IC != 0V
`pGp
d!/H
VDD_PWR != 3V
 T:CN11
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 12:28:03 pm

seems youtuber "bigclivedotcom" spotted a PADAUK MCU containing device in the wild:


Too bad he doesnt desolder the chip to show the bottom so we can see the package markings.

Just FYI package markings on the chips I have:
PMS150C: YS17 RBAAADO 1839XA0
PMC232-S16A: FS20 FC62450 1737YAD
PFS154-S16: YP56 R2E9691 1609XBD
Bj8P509FNB (supposedly clone of elan 13-bit clone of microchip 12c509): BJY180338
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 17, 2018, 02:34:14 pm
I was thinking about creating a library (may be called "libpdk") which contains all the code one may need to create tools for these MCUs. The lib would contain stuff like the PDK decryption/encryption code, the instruction list with their opcode encoding/decoding rules, etc... then all the tools like disassembler, assembler, emulator, etc... can link to the same library. This would let us have only one codebase where the "important stuff" is so if we need to make changes and adjustments (like adding new instrs etc) we wouldn't have to change every single other tool. I'm starting to layout the instruction list in C++ in a way that can be used both to assemble, disassemble or emulate stuff. Is there a place for people interested in helping with the code to chat with the others so we somehow coordinate the work? Like a Slack or Discord channel or something
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 03:00:49 pm
IMHO it would be more useful to add the padauk controllers to already existing toolchains like radare
similarly to 8051 or 6502 or pic that are already there:

https://github.com/radare/radare2/tree/master/libr/asm/arch/8051 (https://github.com/radare/radare2/tree/master/libr/asm/arch/8051)
https://github.com/radare/radare2/tree/master/libr/asm/arch/6502 (https://github.com/radare/radare2/tree/master/libr/asm/arch/6502)
https://github.com/radare/radare2/tree/master/libr/asm/arch/avr (https://github.com/radare/radare2/tree/master/libr/asm/arch/avr)
https://github.com/radare/radare2/tree/master/libr/asm/arch/pic (https://github.com/radare/radare2/tree/master/libr/asm/arch/pic)

You can also add file formats like this:
https://github.com/radare/radare2/blob/master/libr/io/p/io_ihex.c (https://github.com/radare/radare2/blob/master/libr/io/p/io_ihex.c)

I think it would save you and others a lot of work, because most of the underlying work has already been done and tested.
Also radare has already got quite a few tools build in for analysis, disassembling and low level debugging as you can see here:

https://www.megabeets.net/reverse-engineering-a-gameboy-rom-with-radare2/ (https://www.megabeets.net/reverse-engineering-a-gameboy-rom-with-radare2/)

For compiling it might be interesting to add this architecture to sdcc.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 17, 2018, 04:16:35 pm
Too bad he doesnt desolder the chip to show the bottom so we can see the package markings.

You asked for it...  :)

Just stopped at ALDI and saw them having a similar LED Christmas lights offering for 2.99 EUR.

I bought and opened it (without powering it on, because "Don't turn it on, take it apart!" 8) ) ...

... and yes, PCB and MCU looks same as from bigclivedotcom's video.

But to my surprise it is having a 32kHz crystal so it can do much better than the more cost optimized version bigclivedotcom was testing.

Last picture shows the MCU from back side. I'm pretty sure it is a PMC154 (just the cheapest and the pinout for GND, VDD, crystal also matches).


JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: GeorgeOfTheJungle on November 17, 2018, 04:17:17 pm
(Forum doesnt let me post square brackets  :-//)

Look here: https://wiki.simplemachines.org/smf/Alphabetical_list_of_all_bulletin_board_codes

The ones that might work for that are pre or nobbc, me thinks.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 04:35:59 pm

Last picture shows the MCU from back side. I'm pretty sure it is a PMC154 (just the cheapest and the pinout for GND, VDD, crystal also matches).


I dont think so. The chips I have have 3 lines of markings. This just has the one.
No Bojuxing Industry BJ8P509FNB either because thats more laser carved and the chip marking you have seems inkjetted.

All these chips are probably very interchangable anyhow. Or they just rewrite the code, after all these are throw away products

Maybe ALDI has the premium version for germans  :-DD thus the crystal for milisecond switching precision
(seriously the cheapest crystal I could find on lcsc costs more than the pms150c  :scared: utter madness)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 17, 2018, 10:17:42 pm
This isnt complete but its a start.
If you would like to extend this, youre welcome
Its based on
https://github.com/limkokhole/radare2/wiki/Implementing-a-new-architecture
and by no means any good, but I think its not too hard to get it usable.

create a directory. put the two files in it. install radare2 if you havent already.
make
sudo make install

I also had to
cp /usr/lib/radare2/last/* ~/.config/radare2/plugins
otherwise the plugin isnt recognized

rasm2 -L should list it at the end
and then you can
rasm2 -a PADAUK -d 0x0069
to get:  neg a

padauk.c

Code: [Select]
/* Padauk disassembler plugin for radare */

 #include <r_asm.h>
 #include <r_lib.h>
 #include <string.h>

static struct {
ut8 op1;
ut8 op2;
char *name;
} ops[] = {
{0x00, 0x00, "nopi"},
{0x00, 0x60, "addc a"},
{0x00, 0x61, "subc a"},
{0x00, 0x62, "izsn a"},
{0x00, 0x63, "dzsn a"},
{0x00, 0x64, "?"},
{0x00, 0x65, "?"},
{0x00, 0x66, "?"},
{0x00, 0x67, "pcadd a"},
{0x00, 0x68, "not a"},
{0x00, 0x69, "neg a"},
{0x00, 0x6a, "sr a"},
{0x00, 0x6b, "sl a"},
{0x00, 0x6c, "src a"},
{0x00, 0x6d, "slc a"},
{0x00, 0x6e, "swap a"},
{0x00, 0x6f, "?"},
{0x3f, 0xff, NULL}};

static int _PADAUKDisass (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int i;
op->size = 2;
for (i=0; ops[i].name != NULL; i++) {
if (ops[i].op1 == buf[0]) {
if (ops[i].op2 == buf[1]) {
sprintf (op->buf_asm, "%s", ops[i].name);
break;
}
}
}
return op->size;
}

RAsmPlugin r_asm_plugin_padauk = {
        .name = "PADAUK",
        .arch = "PADAUK",
        .license = "LGPL3",
        .bits = 16,
        .desc = "Padauk disassembler",
        .disassemble = &_PADAUKDisass,
};

 #ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
        .type = R_LIB_TYPE_ASM,
        .data = &r_asm_plugin_padauk
};
 #endif

Makefile

Code: [Select]
NAME=padauk
R2_PLUGIN_PATH=$(shell r2 -hh|grep LIBR_PLUGINS|awk '{print $$2}')
CFLAGS=-g -fPIC $(shell pkg-config --cflags r_asm)
LDFLAGS=-shared $(shell pkg-config --libs r_asm)
OBJS=$(NAME).o
SO_EXT=$(shell uname|grep -q Darwin && echo dylib || echo so)
LIB=$(NAME).$(SO_EXT)

all: $(LIB)

clean:
rm -f $(LIB) $(OBJS)

$(LIB): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(LIB)

install:
cp -f $(NAME).$(SO_EXT) $(R2_PLUGIN_PATH)

uninstall:
rm -f $(R2_PLUGIN_PATH)/$(NAME).$(SO_EXT)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 18, 2018, 12:27:02 pm
This is a slightly improved version tested with radare 3.1 git.
The documentation for radare is shall we say "sparse" and every backend seems to have multiple layers of indirection and slightly different ways of going about it, especially for the assembler.
But once you found a way it works quite nicely. This is also not very complete and thus minimalistic because I dont know what the best way to de/encode the instructions is.
The table approach has the advantage of being inversible i.e the dissassembler is the inverse of the assembler, but its quite pointless to do it in this manor for instructions that take addresses etc.

Use the makefile from above.
make && sudo make install
and then you can do
rasm2 -a padauk -d 0x0073
to get "popaf" or
rasm2 -a padauk 'addc a'
to get "0x0060"
and you also get stuff like this
rasm2 -a padauk 'nop; ret; reti; addc a; sr a;'
rasm2 -a padauk -d 0x0000006000720073
for free

padauk.c
Code: [Select]
/* Padauk (dis)assembler plugin for radare 3.1 git - DocBen 2018 */

 #include <r_asm.h>
 #include <r_lib.h>
 #include <string.h>

static struct {
ut16 op;
char *name;
} ops[] = {
{0x0000, "nop"},
{0x0060, "addc a"},
{0x0061, "subc a"},
{0x0062, "izsn a"},
{0x0063, "dzsn a"},
{0x0064, "?"},
{0x0065, "?"},
{0x0066, "?"},
{0x0067, "pcadd a"},
{0x0068, "not a"},
{0x0069, "neg a"},
{0x006c, "src a"},
{0x006d, "slc a"},
{0x006a, "sr a"},
{0x006b, "sl a"},
{0x006e, "swap a"},
{0x006f, "?"},
{0x0070, "wdreset"},
{0x0071, "?"},
{0x0072, "pushaf"},
{0x0073, "popaf"},
{0x0074, "?"},
{0x0075, "reset"},
{0x0076, "stopsys"},
{0x0077, "stopexe"},
{0x0078, "engint"},
{0x0079, "disgint"},
{0x007b, "reti"},
{0x007a, "ret"},
{0x007c, "mul"},
{0x007d, "?"},
{0x007e, "?"},
{0x007f, "?"},
{0x4000, NULL}};

int _PADAUKDisass (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int i;
op->size = 2;
const char *buf_asm = "unknown";
for (i=0; ops[i].name != NULL; i++) {
if (ops[i].op == 0x100 * buf[0] + buf[1]) {
buf_asm = sdb_fmt ("%s", ops[i].name);
break;
}
}
r_strbuf_set (&op->buf_asm, buf_asm);
return op->size;
}

int _PADAUKAss (RAsm *a, RAsmOp *op, const char *buf) {
int i;
op->size = 2;
ut16 opbuf = 0x4000;
const char *buf_hex = "unknown";
for (i = 0; ops[i].name != NULL; i++) {
if (!strncmp(ops[i].name, buf, strlen(ops[i].name))) {
opbuf = ops[i].op;
buf_hex = sdb_fmt ("0x%.4X\n", opbuf);
break;
}
}
r_strbuf_set (&op->buf_hex, buf_hex);
return op->size;
}

RAsmPlugin r_asm_plugin_padauk = {
        .name = "padauk",
        .arch = "padauk",
        .license = "LGPL3",
        .bits = 16,
        .desc = "Padauk (dis)assembler",
        .disassemble = &_PADAUKDisass,
        .assemble = &_PADAUKAss,
};

 #ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
        .type = R_LIB_TYPE_ASM,
        .data = &r_asm_plugin_padauk
};
 #endif
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 18, 2018, 08:15:18 pm
Playing further with radare I noticed that there are mostly disassembler backends but only a few assemblers.
I kind of like the idea of having something table driven that allows for a certain symmetry of assembler and disassembler.
Also looks more like a datasheet. Again not complete but recognizes the instructions given, if you want more instructions its literally copy and paste from the website somewhere above.

Don't know if I'll be able to finish this soon though. Just to give an idea that this could be generalized I did the same for pic12 and at least it looks good ;)

Code: [Select]
/* Padauk (dis)assembler plugin for radare 3.1 git - DocBen 2018
now looking more like a datasheet
*/

 #include <r_asm.h>
 #include <r_lib.h>
 #include <string.h>

static struct {
char *op;
char *name;
ut8 args;
char *comment;
} ops[] = {
// memory mapped io i (6-bit)
// nth bit n (3-bit)
// memory address m (6 bit)
// memory address M (7 bit)
// immediate c (8 bit)
// address k (11 bit)
//"binary representation","mnemonic"(,"num parameters (could be inferred)"),"comment"
"0000.0000.0000.0000", "nop", 0, "does nothing (tm)",
"0000.0000.0110.0000", "addc a", 1, "A ← A + CF",
"0000.0000.11ii.iiii", "xor io,a", 2, "IO ← IO ^ A",
"0000.0001.10ii.iiii", "mov io,a", 2, "IO ← A",
"0000.0001.11ii.iiii", "mov a,io", 2, "A ← IO",
"0000.0010.cccc.cccc", "ret c", 1, "",
"0000.0011.1MMM.MMM0", "idxm M, a", 2, "[M] ← A (last bit of M set to 0, M must be word aligned, 2 cycles)",
"0000.0011.1MMM.MMM1", "idxm a, M", 2, "a ← [M] (last bit of M set to 1, M must be word aligned, 2 cycles)",
"0000.010n.nnii.iiii", "swapc io.n", 2, "",
"0000.0110.0MMM.MMMM", "comp a, M", 2, "",
"0010.000n.nnmm.mmmm", "t0sn m.n", 2, "",
"0011.0kkk.kkkk.kkkk", "goto k", 1, "goto address",
"0011.1kkk.kkkk.kkkk", "call k", 1, "call address",
"2222.2222.2222.2222", NULL, 0, "",
};


void bitstring(uint16_t val, char buffer[]) {
int size = 20;
buffer[--size] = 0;
while (size > 0) {
buffer[--size] = (val % 2 ? '1' : '0');
if ( size % 5 == 0 && size > 0) buffer[--size] = '.';
val = val >> 1;
}
}

int _PADAUKDisass (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int i;
op->size = 2;
const char *buf_asm = "unknown";
char buf_bin[40];
bitstring(0x100 * buf[0] + buf[1], buf_bin);
for (i=0; ops[i].name != NULL ; i++) {
for (int j = 0; j < 20; j++) {
if (ops[i].op[j] != buf_bin[j]) {
if (ops[i].op[j] != '0' && ops[i].op[j] != '1') { // treat all letters as dont care
continue;
} else {
break;
}
}
if (j == 19) {
buf_asm = sdb_fmt ("%s = %s ; %s", buf_bin, ops[i].name, ops[i].comment);
r_strbuf_set (&op->buf_asm, buf_asm);
return op->size;
}
}
}
r_strbuf_set (&op->buf_asm, buf_asm);
return op->size;
}

int _PADAUKAss (RAsm *a, RAsmOp *op, const char *buf) {
int i;
op->size = 2;
ut16 opbuf = 0x4000;
const char *buf_hex = "unknown";
for (i = 0; ops[i].name != NULL; i++) {
if (!strncmp(ops[i].name, buf, strlen(ops[i].name))) {
//opbuf = ops[i].op;
buf_hex = sdb_fmt ("0x%.4X\n", opbuf);
break;
}
}
r_strbuf_set (&op->buf_hex, buf_hex);
return op->size;
}

RAsmPlugin r_asm_plugin_padauk = {
        .name = "padauk2",
        .arch = "padauk2",
        .license = "LGPL3",
        .bits = 16,
        .desc = "Padauk (dis)assembler",
        .disassemble = &_PADAUKDisass,
        .assemble = &_PADAUKAss,
};

 #ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
        .type = R_LIB_TYPE_ASM,
        .data = &r_asm_plugin_padauk
};
 #endif

PIC12
Code: [Select]
static struct {
char *op;
char *name;
ut8 args;
char *comment;
} ops[] = {
// direction d (1 bit)
// tri-state register t (2 bit)
// nth bit b (3-bit)
// register bank (3 bit)
// register f (5 bit)
// immediate c (8 bit)
// address k (8 bit)
// address K (9 bit)
//"binary representation","mnemonic"(,"num parameters"), "comment"
"0000.0000.0000.0000", "nop", 0, "No operation (MOVW 0,W)",
"0000.0000.0000.0010", "option", 0, "Copy W to OPTION register",
"0000.0000.0000.0011", "sleep", 0, "Go into standby mode",
"0000.0000.0000.0100", "clrwdt", 0, "Restart watchdog timer",
"0000.0000.0000.01tt", "tris t", 0, "Copy W to tri-state register (f = 1, 2 or 3)",
"0000.0000.0001.0BBB", "movlb k", 1, "Set bank select register to k",
"0000.0000.0001.1110", "return", 0, "Return from subroutine, W unmodified",
"0000.0000.0001.1111", "retfie", 0, "Return from interrupt; return & enable interrupts",
"0000.0000.001f.ffff", "movwf f", 1, "dest ← W",
"0000.0000.01df.ffff", "clr f,d", 2, "dest ← 0, usually written CLRW or CLRF f",
"0000.0000.10df.ffff", "subwf f,d", 2, "dest ← f−W (dest ← f+~W+1)",
"0000.0000.11df.ffff", "decf f,d", 2, "dest ← f−1",
"0000.0001.00df.ffff", "iorwf f,d", 2, "dest ← f | W, logical inclusive or",
"0000.0001.01df.ffff", "andwf f,d", 2, "dest ← f & W, logical and",
"0000.0001.10df.ffff", "xorwf f,d", 2, "dest ← f ^ W, logical exclusive or",
"0000.0001.11df.ffff", "addwf f,d", 2, "dest ← f+W",
"0000.0010.00df.ffff", "movwf f,d", 2, "dest ← f",
"0000.0010.01df.ffff", "comf f,d", 2, "dest ← ~f, bitwise complement",
"0000.0010.10df.ffff", "incf f,d", 2, "dest ← f+1",
"0000.0010.11df.ffff", "decfsz f,d", 2, "dest ← f−1, then skip if zero",
"0000.0011.00df.ffff", "rrf f,d", 2, "dest ← CARRY<<7 | f>>1, rotate right through carry",
"0000.0011.01df.ffff", "rlf f,d", 2, "dest ← F<<1 | CARRY, rotate left through carry",
"0000.0011.10df.ffff", "swapf f,d", 2, "dest ← f<<4 | f>>4, swap nibbles",
"0000.0011.11df.ffff", "incfsz f,d", 2, "dest ← f+1, then skip if zero",
"0000.0100.bbbf.ffff", "bcf f,b", 2, "Clear bit b of f",
"0000.0101.bbbf.ffff", "bsf f,b", 2, "Set bit b of f",
"0000.0110.bbbf.ffff", "btfsc f,b", 2, "Skip if bit b of f is clear",
"0000.0111.bbbf.ffff", "btfss f,b", 2, "Skip if bit b of f is set",
"0000.1000.cccc.cccc", "retlw c", 2, "Set W ← k, then return from subroutine",
"0000.1001.kkkk.kkkk", "call k", 2, "Call subroutine, 8-bit address k",
"0000.101K.KKKK.KKKK", "goto k", 2, "Jump to 9-bit address k",
"0000.1100.cccc.cccc", "movlw c", 2, "W ← c",
"0000.1101.cccc.cccc", "iorlw c", 2, "W ← c | W, bitwise logical or",
"0000.1110.cccc.cccc", "andlw c", 2, "W ← c & W, bitwise and",
"0000.1111.cccc.cccc", "xorlw c", 2, "W ← c ^ W, bitwise exclusive or",
"2222.2222.2222.2222", NULL, 0, "",
};
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 10:11:11 am
Nice job, would it be possible to make a github repo out of it?

Anyhow my idea for a "universal" instruction table was to have a list of objects like this, if this can somehow interest you:

opcode (16bit)
opcode_mask (16bit)
parameters (array)
[
  {
    type {IO/MEM/IMM/...}
    length (in bits)
    pos (bit n#)
  }
]

There are not a lot of instructions that have more than one parameter encoded, but there are still some, so having an array of parameters descriptions covers everything. Let's call the object above "instr_t". You could write functions to create an instr_t from an assembly line, from an opcode or whatever. Also you could write functions to convert it to an opcode, to an assembly line or to emulate the thing (or maybe the emulator is just a big switch on the opcode and you do everything manually, idk). The point is, this should cover everything and be pretty flexible and somewhat clean.

It may be faster than your current approach (which I like anyway, it is very readable IMHO) but by pattern matching like that may not be the most efficient thing, also you'll have to reconstruct the parameter values and other stuff which would be easier with a table like mine, at least that's what I anticipate.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 10:20:31 am
Also you may want the make install rule to install the plugin under the user plugins directory (on my Linux system it's ~/.local/share/radare2/plugins) which is a bit less invasive ;)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: david.given on November 19, 2018, 01:58:23 pm
The architecture's engagingly minimal --- memory/memory architecture, one register! I actually have a self-hosting tiny compiler (<plug> http://cowlark.com/cowgol (http://cowlark.com/cowgol) </plug>) which would map very nicely onto this thing. Sadly, it doesn't have enough RAM to run the compiler on itself...

If anyone comes up with a simulator which will run PDK files, I'd love to know about it!
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 02:37:44 pm
Uhm, I just noticed the PMS150/PMS150C opcodes are different from the PMS154C ones, while still being 14-bit wide. Seems like there are multiple encodings for the same instructions.

For instance:

mov A, 0xAA       -> 0x17AA
mov <addr>, A    -> 0x05C.. something like that
pcadd a               -> 0x0017
wdreset                -> 0x0030

But they're not totally different, most of the time it's just one bit off. Also the PDK fill pattern is 0x1FFF instead of 0x3FFF.

This may need some investigation.

edit: actually no value goes beyond 0x1FFF, I should have noticed that before. Seems like they shaved one bit off and the opcodes are 13-bit (?) if that makes any sense.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 19, 2018, 03:11:50 pm
If anyone comes up with a simulator which will run PDK files, I'd love to know about it!

Maybe it could be added as a target for QEMU. It has already all kinds of infrastructure functions to implement a new target without too much effort, and it is very fast, because it translates the code to native assembler code on the fly, like a JIT compiler. And it has already functions for timers, interrupts etc.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 19, 2018, 03:27:18 pm
If anyone comes up with a simulator which will run PDK files, I'd love to know about it!

I intend to get support for some Padauk devices into SDCC. For this, they'd need to be supported in the asxxxx fork that SDCC uses, the linker and the uCsim simulator. Support for the Single-Core devices will probably come first (as the lack of sp-relative addressing is a serious restriction for the multicore devices, requiring careful though on how to work around it).

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 19, 2018, 03:35:43 pm
Uhm, I just noticed the PMS150/PMS150C opcodes are different from the PMS154C ones, while still being 14-bit wide. Seems like there are multiple encodings for the same instructions.

For instance:

mov A, 0xAA       -> 0x17AA
mov <addr>, A    -> 0x05C.. something like that
pcadd a               -> 0x0017
wdreset                -> 0x0030

But they're not totally different, most of the time it's just one bit off. Also the PDK fill pattern is 0x1FFF instead of 0x3FFF.

This may need some investigation.

edit: actually no value goes beyond 0x1FFF, I should have noticed that before. Seems like they shaved one bit off and the opcodes are 13-bit (?) if that makes any sense.

There are 3 different instruction sets¹ (each with some minor variation such as possible presence of mul). I assumed them to be 14, 15 and 16 bits. But from what you found it seems that they are 13, 14 and 16 bits. The 13-bit instruction set would be used on devices that have up to 1 kiloword of program memory, the 14-bit instruction set for up to 2 kilowords of program memory. The 16-bit instruction set would then be for larger and multicore devices.

Philipp

¹ According to an email by Padauk.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DDunfield on November 19, 2018, 04:49:12 pm
Hi Guys,

Just found this thread. Seems like we've been duplicating some work.

I was planning to develop a PC based simulator to allow code to be quickly
tested and debugged, and also perhaps an STM32 based one which would allow
code to be tested "in circuit" with downloadability and decent debugging
capability. Would also like to eventually include device programming in
the STM32 but I've not looked really looked into it yet.

Here's what I've figured out about the instruction set:
I've added some notes and questions at the end, if anyone can help clarify
these points, please let me know.

The PMS/C150 uses a 13 bit opcode:

00000 101ppppp  MOV       A,io-addr
00000 100ppppp  MOV       io-addr,A
10111 dddddddd  MOV       A,imm-data
00111 11aaaaaa  MOV       A,ram-addr
00101 11aaaaaa  MOV       ram-addr,A
00000 110aaaa1  LDT16     ram-addr-even
00000 110aaaa0  STT16     ram-addr-even
00000 111aaaa1  IDXM      A,ram-addr-even
00000 111aaaa0  IDXM      ram-addr-even,A
01001 11aaaaaa  XCH       ram-addr
00000 00110010  PUSHAF
00000 00110011  POPAF
10000 dddddddd  ADD       A,imm-data
00110 00aaaaaa  ADD       A,ram-addr
00100 00aaaaaa  ADD       ram-addr,a
00000 00010000  ADDC      A
00110 10aaaaaa  ADDC      A,ram-addr
00100 10aaaaaa  ADDC      ram-addr,A
10001 dddddddd  SUB       A,imm-data
00110 01aaaaaa  SUB       A,ram-addr
00100 01aaaaaa  SUB       ram-addr,a
00000 00010001  SUBC      A
00110 11aaaaaa  SUBC      A,ram-addr
00100 11aaaaaa  SUBC      ram-addr,A
01001 00aaaaaa  INC       ram-addr
01001 01aaaaaa  DEC       ram-addr
01001 10aaaaaa  CLEAR     ram-addr
00000 00011010  SR        A
01010 10aaaaaa  SR        ram-addr
00000 00011100  SRC       A
01011 00aaaaaa  SRC       ram-addr
00000 00011011  SL        A
01010 11aaaaaa  SL        ram-addr
00000 00011101  SLC       A
01011 01aaaaaa  SLC       ram-addr
00000 00011110  SWAP      A
10100 dddddddd  AND       A,imm-data
00111 00aaaaaa  AND       A,ram-addr
00101 00aaaaaa  AND       ram-addr,A
10101 dddddddd  OR        A,imm-data
00111 01aaaaaa  OR        A,ram-addr
00101 01aaaaaa  OR        ram-addr,A
10110 dddddddd  XOR       A,imm-data
00111 10aaaaaa  XOR       A,ram-addr
00101 10aaaaaa  XOR       ram-addr,A
00000 011ppppp  XOR       io-addr,A
00000 00011000  NOT       A
01010 00aaaaaa  NOT       ram-addr
00000 00011001  NEG       A
01010 01aaaaaa  NEG       ram-addr
01110 bbbppppp  SET0      io-addr.bit
01111 bbbppppp  SET1      io-addr.bit
00011 bbb0aaaa  SET0      ram-addr.bit
00011 bbb1aaaa  SET1      ram-addr.bit
10010 dddddddd  CEQSN     A,imm-data
01011 10aaaaaa  CEQSN     A,ram-addr
01100 bbbppppp  T0SN      io-addr.bit
01101 bbbppppp  T1SN      io-addr.bit
00010 bbb0aaaa  T0SN      ram-addr.bit
00010 bbb1aaaa  T1SN      ram-addr.bit
00000 00010010  IZSN      A
00000 00010011  DZSN      A
01000 10aaaaaa  IZSN      ram-addr
01000 11aaaaaa  DZSN      ram-addr
110aa aaaaaaaa  GOTO      code-addr
111aa aaaaaaaa  CALL      code-addr
00001 dddddddd  RET       imm-data
00000 00111010  RET
00000 00111011  RETI
00000 00000000  NOP
00000 00010111  PCADD     A
00000 00111000  ENGINT
00000 00111001  DISGINT
00000 00110110  STOPSYS
00000 00110111  STOPEXE
00000 00110101  RESET
00000 00110000  WDRESET
00000 00000000  TRAP     // Assembler accepts, but same as NOP

General notes:
--------------
Full ram-addr range is 0x00-0x3B (60 bytes).

Instructions requiring ram-addr-even allow only 0x00-0x1E, lowest bit
is *NOT* encoded and is assumed to be zero.

Bit set/clear instructions on ram-addr allow only 0x00-0x0F.

Full io-addr range is 0x00-0x1F.


Instruction set notes:
----------------------
According to the data sheet, there are 4 flags: OV, Z, C, AC

Other than 'C' which can be accessed in the ADDC, SUBC, SRC and SLC
instructions, it is not clear what role the OV, Z and AC flags play.
There does not appear to be any instructions which access them.
The only conditionals are "compare ACC" and skip.

The only way I can see to access the other flags is via PUSHAF and then
reading them from memory (you would need to know exactly where SP points).

I'm wondering if this is "cut/paste" error and this processor does not
actually have OV, Z and AC (would make writing the simulator easier).

Perhaps someone with the actual part could write some test code using
arithmetic instructions and PUSHAF to test if these flags are actually
implemented on the PMS150?


The data sheet also says (page 18): (sic)
"The OTP program memory may contains the data, tables and interrupt entry."

I can see no capability in the instruction set to read data/tables from
program memory (other than immediate data).
Perhaps I have missed something?


The instruction set allows for a MAXIMUM of 64 bytes of RAM ... RAM
addresses are encoded in 6 bits. Yet, the indirect instruction IDXM uses
"pointer" values in memory which are two bytes in size. This makes no
sense to me as RAM is a very limited resource, and only one byte is needed
to address all of it. It also wastes instructions clearing the unused top
byte of the pointer - also a limited resource.

Perhaps "special" values in the upper byte allow indexed access to other
things, such as CODE memory or IO space ... but I can find no mention of
any such capability. Anyone know better?


PADAUK assembler notes:
-----------------------
HB@,LB@/HD@,LD@ can be used to access high/low byte of word data:
   MOV A,hb@word_symbol

HA@,LA@ can be used to get high/low symbol address as immediate-data:
   MOV A,ha@symbol

IO. can be used to specify an arbitrary IO address:
   MOV A,io.2

I've not found a prefix for force a RAM access. The only way I've found
to access ROM is by explicitly declaring symbols with "word" and "byte"
directives. Anyone know better?


Regards,
Dave

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: david.given on November 19, 2018, 04:57:52 pm
Incidentally, some interesting ISA quirks I've noticed:


So if you wanted C-style stack frames, god help you, your function preamble/postamble would look like:

Code: [Select]
mov a, lb@fp ; read old frame pointer
pushaf ; save
mov a, sp ; read stack pointer
mov fp, a ; set new frame pointer
add A, 8 ; allocate stack frame
mov SP, A ; update stack pointer
...main code here...
mov a, fp ; read current frame pointer
mov sp, a ; retrack over frame
popaf ; load old frame pointer
mov fp, a ; reload old frame pointer
ret
 

Blech.

To read a value from the frame, you'd need:

Code: [Select]
mov a, 4 ; frame offset
add a, fp ; add frame pointer
mov lb@ptr, a
idxm a, ptr

...which is equally grim. Running traditional C on this would be a mug's game, of course.

Cowgol doesn't use stack frames, though, so it's golden.

You might be able to do some incredibly basic Forth, based around an opcode interpreter, with some hoops to jump through to be able to read words out of RAM as well as program memory, but it's probably only worth it for the lols --- I expect it would eat most of the program space and be slow to boot, and with the very limited I/O capability you wouldn't be able to interact with it once you'd done it. Admittedly, running Forth on a 3c machine would make for some pretty serious lols.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: david.given on November 19, 2018, 05:05:46 pm
Yay, so much talking across people...

Re data tables: I think they're referring to this sort of thing:

Code: [Select]
; index in A, returns value in A
load_value_from_table:
  pcadd a ; jump to pc + a
  ret 42
  ret 99
  ret -6
  ret 127
  ...etc...

I haven't seen anything for accessing program data. I assume the assembler knows whether to generate an IO or RAM instruction by the type of the symbol you're addressing.

Re the other flags: the flags byte is at IO address 0, so you can test any individual but with t1sn IO.3 or similar. I don't think we can get away with ignoring them...
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DDunfield on November 19, 2018, 05:12:50 pm
Re the other flags: the flags byte is at IO address 0, so you can test any individual but with t1sn IO.3 or similar. I don't think we can get away with ignoring them...

Thanks, I hadn't picked up on that little detail yet (been busy working out the instructions). That explains it.

Dave
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 05:48:10 pm
Seems like we've been duplicating some work.

I would like to insist on finding a way to better collaborate on this. Something like Slack could help since we would have a decent chat platform to keep everything organized and coordinate stuff. We could have various channels for RE of the programmer, RE of the ISA, tools implementation, etc... would anyone be interested?

Cowgol doesn't use stack frames, though, so it's golden.

Your small language seems really interesting. I also do not see a lot of sense in porting "full" C for this architecture, IMHO it's just less of an hassle to write assembly. A mixed language with assembly+some high level constructs is the best thing, which is in fact what PADAUK did with their Mini-C. If we make an open source toolchain it wouldn't be bad to have our own language for this thing. Of course the self-hosting capability of your compiler (while being really cool) here is pointless, but I see myself liking a language like Cowgol with the possibility to interleave assembly code like PADAUK's Mini-C lets you do. I mean, instead of replicating their Mini-C we could take the opportunity to try something else.

Of course if someone manages to make C compile for this MCUs through SDCC or whatever, that would be really cool, but I would like to see how much overhead it is added, especially regarding function calls.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gslick on November 19, 2018, 05:52:34 pm
Hi Guys,

Just found this thread. Seems like we've been duplicating some work.

I was planning to develop a PC based simulator to allow code to be quickly
tested and debugged, and also perhaps an STM32 based one which would allow
code to be tested "in circuit" with downloadability and decent debugging
capability. Would also like to eventually include device programming in
the STM32 but I've not looked really looked into it yet.

Regards,
Dave

Are you the ImageDisk Dave? Interesting to see you pop up on this thread and looking at these low cost microcontrollers.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 19, 2018, 06:24:31 pm
Hi Dave,

Great that you did the 13 bit instruction set. This is no duplicated work. I did the 154C which uses 14 bit instructions.

Please have a look at the github project I started:

https://github.com/free-pdk

If you like I can add you to the developer list.

Regarding FLAGs:

Have a look at the ".INC" include file in IDE. You can see that IO @ 0x00 holds all the flags:

Code: [Select]
FLAG IO_RW 0x00
OV IO_RW FLAG.3
AC IO_RW FLAG.2
CF IO_RW FLAG.1
ZF IO_RW FLAG.0

So with simple bit tests like T0SN IO.n  and T1SN IO.n you can check and skip next instructions with flags.

Example: To test for OV flag following code can be used:

Code: [Select]
T1SN OV
GOTO OVCLEAR
NOP
NOP
OVCLEAR:

You also could use  T1SN  FLAG.3

In the .INC file you also see that SP is emulated as an IO register and more interesting stuff.


In the next few days I will write a simulator for the 14 bit core. This should not take long at all.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 19, 2018, 06:26:48 pm
Your small language seems really interesting. I also do not see a lot of sense in porting "full" C for this architecture, IMHO it's just less of an hassle to write assembly. A mixed language with assembly+some high level constructs is the best thing, which is in fact what PADAUK did with their Mini-C. If we make an open source toolchain it wouldn't be bad to have our own language for this thing. Of course the self-hosting capability of your compiler (while being really cool) here is pointless, but I see myself liking a language like Cowgol with the possibility to interleave assembly code like PADAUK's Mini-C lets you do. I mean, instead of replicating their Mini-C we could take the opportunity to try something else.

Of course if someone manages to make C compile for this MCUs through SDCC or whatever, that would be really cool, but I would like to see how much overhead it is added, especially regarding function calls.

The Padauks aren't the only architecture on which stack access is inefficient. For other such architectures (e.g. MCS-51), SDCC makes functions non-reentrant by default (i.e. unless the function is marked __reentrant or the --stack-auto command-line argument is supplied), placing local variables at fixed memory locations.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 07:13:48 pm
SDCC makes functions non-reentrant by default (i.e. unless the function is marked __reentrant or the --stack-auto command-line argument is supplied), placing local variables at fixed memory locations.

Thanks for telling, I never used SDCC before actually and didn't know it supported even this kind of architectures. Nice to know.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 19, 2018, 07:44:14 pm
By popular demand ;)
https://github.com/mypdk/radare_plugins

Anyhow my idea for a "universal" instruction table was to have a list of objects like this, if this can somehow interest you:

It may be faster than your current approach (which I like anyway, it is very readable IMHO) but by pattern matching like that may not be the most efficient thing, also you'll have to reconstruct the parameter values and other stuff which would be easier with a table like mine, at least that's what I anticipate.

You're absolutely right your instruction table is more precise but it is a lot less generic and requires more work.
My idea was to simply let the computer figure these things out a later point. The basic idea is to have something as easy to read and maintain as possible for these little buggers.
Later a parser can look at the definitions and write something like your structs automatically or generate an optimized assembler/disassembler.

I'm an engineer and thus obligated to be as lazy as possible   :popcorn:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 08:07:48 pm
I'm an engineer and thus obligated to be as lazy as possible   :popcorn:

I'm still not an engineer, just half-way through, so I can still be not lazy sometimes :P

I'm implementing the method I described, currently my table is defined like this:

Code: [Select]
static const auto PMS154_INSTRUCTIONS_SPEC = std::vector<instr_spec_t>
{
  // {mnemonic, opcode, opcode_mask, {args...}}

  {"nop",     0x0000, 0x3FFF, {}},

  {"addc",    0x0060, 0x3FFF, {{Accumulator, 0, 0}}},
  {"subc",    0x0061, 0x3FFF, {{Accumulator, 0, 0}}},
  {"izsn",    0x0062, 0x3FFF, {{Accumulator, 0, 0}}},
  {"izsn",    0x0063, 0x3FFF, {{Accumulator, 0, 0}}},

  // ...

  {"wdreset", 0x0070, 0x3FFF, {}},

  {"pushaf",  0x0072, 0x3FFF, {}},
  {"popaf",   0x0073, 0x3FFF, {}},

  // ...

  {"xor",     0x00C0, 0x3FC0, {{IO, 0, 6}, {Accumulator, 0, 0}}},
  {"mov",     0x0180, 0x3FC0, {{IO, 0, 6}, {Accumulator, 0, 0}}},
  {"mov",     0x01C0, 0x3FC0, {{Accumulator, 0, 0}, {IO, 0, 6}}},

  {"ret",     0x0200, 0x3F00, {{Immediate, 0, 8}}},

  {"stt16",   0x0300, 0x3F81, {{Memory, 0, 7}}},
  {"ldt16",   0x0301, 0x3F81, {{Memory, 0, 7}}},
  {"idxm",    0x0380, 0x3F81, {{Memory, 0, 7}, {Accumulator, 0, 0}}},
  {"idxm",    0x0381, 0x3F81, {{Accumulator, 0, 0}, {Memory, 0, 7}}},

  {"swapc",   0x0400, 0x3E00, {{IO, 0, 6}, {Bit_N, 6, 3}}},

  {"comp",    0x0600, 0x3F80, {{Accumulator, 0, 0}, {Memory, 0, 7}}},
  {"comp",    0x0680, 0x3F80, {{Memory, 0, 7}, {Accumulator, 0, 0}}},
  {"nadd",    0x0700, 0x3F80, {{Accumulator, 0, 0}, {Memory, 0, 7}}},
  {"nadd",    0x0780, 0x3F80, {{Memory, 0, 7}, {Accumulator, 0, 0}}},

  // ...
};

Which I hope you agree is still pretty readable thanks to various new C++ things that allow it to be written like that. Maybe with opcodes written in binary would have been easier but well...

And the hearth of the disassembler code is literally 60 lines of code, for the assembler will just be a little bit more. Once you have such a table you can just iterate over all the table and find whatever matches. If you are disassembling you check the opcode with the mask, if you are assembling you check the mnemonic and the parameters in their respective order. If you need to assemble for a variant of the instruction set you just pass another table.

Anyway I'm following my initial idea to create a "libpdk" which does everything as I previously described. That doesn't mean my approach is orthogonal to what you are doing with radare2, i.e. you could then use the library with the assembling/disassembling capabilities to create the plugin pretty easily just by calling in the library code.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DDunfield on November 19, 2018, 08:27:23 pm
Are you the ImageDisk Dave? Interesting to see you pop up on this thread and looking at these low cost microcontrollers.

I am.

Perhaps more relevant to these discussions is my past-life of creating development tools for little processors (mostly 8-bit). C compilers, assemblers, debuggers, simulators etc.
If you're bored, you can look under "sample projects" at www.dunfield.com (http://www.dunfield.com) to see some of the similar/related stuff I used to support myself with.

MCUs in the "few cents" range are an interesting development!

Regards,
Dave

** Mostly retired now, but always up for an interesting project!
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 09:00:38 pm
I got a disassembler for the 14-bit ISA working in a preliminary state based on the work that js_12345678_55AA did REing the opcodes. There are some strange things in the code generated by the IDE however, such as:

- sometimes there are calls to 0x07f... which are in the "0x3FFF filled" part of the ROM, 0x3FFF is "call @0x7ff", and at 0x7ff there's "izsn [0x44]" which doesn't make a lot of sense (?)
- there are some opcodes we don't know about, such as 0x0006 or 0x0007
- the code flow doesn't make sense in general in some cases, for instance the "GOTO FPPA0 instruction" at 0x0001 (I'm reading from the datasheet of the PMS154C) is "goto @0xc", at that address there's some code that then calls @0x7f6 which doesn't make sense, shouldn't the user program start?

I can however locate the code I wrote. The void func(void) is at 0x0002 till 0x000b and the FPPA0 is at 0x0086 (there's a goto going there at 0x0013).

This is the code I compiled from the IDE

Code: [Select]
#include "extern.h"

void func(void)
{
byte x = 5;
byte y = 6;
byte c;

c = x + y - ~x;
}

void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/2 // SYSCLK=IHRC/2

func();

byte c = 0;

while (1)
{
c++;
}
}

I attacched the disassembled ROM if someone wants to take a look.

Has someone figured out this stuff yet? I guess there's most likely something wrong with the opcodes RE, but IDK, I still have to take a look. I'm posting so that anyone can check if interested.

edit: just realized the 0x0006 and 0x0007 where the undocumented instructions js_12345678_55AA found https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg1970672/#msg1970672 (https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg1970672/#msg1970672) , makes sense
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 19, 2018, 09:12:02 pm
Hi,

@gdelazzari

Read about how IDE / WRITER inserts the "rolling code" (is in help / manual of IDE).

For 154 the example says to read the serial numer / rolling code by this:
Code: [Select]
call _SYS(ADR.ROLL);
call _SYS(ADR.ROLL)+1;
call _SYS(ADR.ROLL)+2;

Writer will insert "RET 0xAB  RET 0xCD  RET =0xEF" at those addresses which are located at the end of the ROM.

One call I could not figure out is to (last instruction possible -1) 0x3FFE. Maybe Writer will insert another RET 0x12  there.

I need to wait for my writer to arrive so I can write and read back.

The very last ROM word contains the values to setup IHRC , Security Fuse, ... (everything you setup with .ADJUST_IC).

.ADJUST_IC also will put a lot of init code inside (even contains delay loops, in case you setup something for SYSCLK other than "DISABLED").



Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 09:22:14 pm
Thanks, this now makes more sense. By the way I have my disassembler implemented with an instruction table like the one I posted before which I believe is a pretty flexible approach, adding an assembler and an emulator based on that should be pretty easy. I'm sure you're almost there to a complete disassembler too (and maybe other tools). What approach did you use? I'm trying to understand if my code could be useful or not, I guess I'll wait for you to upload your disassembler to the GitHub org?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 19, 2018, 09:36:00 pm
I try to build a cycle accurate simulator which is ultra fast and can synchronize to real time (even on STM32 :-)). I took some inspiration from already existing tiny fast 6502 simulators.

Right now I try to figure out (imagine) how the AC and OV flags are set. The user manual of the processors does not describe it in an understandable way for me.


Here is a part of the source of already finished code for some opcodes (eA holds A, ePC the PC, eF the FLAGs, eSP the SP)

Code: [Select]
  uint8_t  eF = CPUioGet(0x00);             //get flags from emulated IO port, mapped like in IO flags: (- - - - V A C Z)
  uint8_t  eSP = CPUioGet(0x02);            //get SP from emulated IO port
  uint16_t opcode = CPUcodeGet( ePC++ );    //fetch next opcode and advance PC
  eCurrentCycle++;                          //increment current cycle counter

  if( 0x3FFE == opcode ) //special opcode ?
  {
    //TODO... find out what it does. IDE inserts when using ADJUST_CHIP
  }
  else
  //14 bit opcodes 0x0000 - 0x00BF
  if( opcode<=0x00BF )
  {
    switch( opcode )
    {
      case 0x0000: break; //NOP

      ...
  }
  ...
  else
  //6 bit opcodes 0x02.. , 0x2800 - 0x2FFF
  if( (0x0200 == (opcode&0x3F00)) || (0x2800 == (opcode&0x3800)) )
  {
    switch( opcode & 0x3F00 )
    {
      case 0x0200: eA = opcode&0xFF; ePC=(((uint16_t)CPUmemGet(--eSP))<<8); ePC|=CPUmemGet(--eSP); break; //RET k
 
      case 0x2800: eA += opcode&0xFF; eF=(eA>255)<<1;eA&=0xFF;eF|=!eA; break; //ADD A,k //TODO: OV, AC
      case 0x2900: eA -= opcode&0xFF; eF=(eA>=0)<<1;eA&=0xFF;eF|=!eA; break; //SUB A,k //TODO: OV, AC

      case 0x2A00: //CEQSN A,k
      case 0x2B00: //CNEQSN A,k
        T = eA-(opcode&0xFF);            //TODO: A-k or k-A ?
        if( ((0x2A00==(opcode&0x3F00)) && !T) ||
            ((0x2B00==(opcode&0x3F00)) && T) )
        {
          ePC++; eCurrentCycle++;
        }
        eF=(T>255)<<1;T&=0xFF;eF|=!T; //TODO: OV,AC (based on T)
        break;

      case 0x2C00: eA &= opcode&0xFF; eF&=~1;eF|=!eA; break; //AND A,k
      case 0x2D00: eA |= opcode&0xFF; eF&=~1;eF|=!eA; break; //OR A,k
      case 0x2E00: eA ^= opcode&0xFF; eF&=~1;eF|=!eA; break; //XOR A,k
      case 0x2F00: eA  = opcode&0xFF; break; //MOV A,k
    }
  }               
  else
  //5 bit opcodes 0x0400 - 0x0500, 0x1800 - 0x27FF
  if( (0x0400 == (opcode&0x3E00)) || ((opcode>=0x1800) && (opcode<=0x27FF)) )
  {
    uint8_t bit = 1<<((opcode>>6)&7);
    uint8_t addr = opcode&0x3F;
    switch( opcode & 0x3E00 )
    {
      case 0x0400: T=CPUioGet(addr);CPUioPut(addr,eF&2?T|bit:T&~bit); eF&=~2;eF|=(T&bit)?2:0; break; //SWAPC IO.n
      case 0x1800: if( !(CPUioGet(addr)&bit) ) { ePC++; eCurrentCycle++; } break;                    //T0SN IO.n
      case 0x1A00: if( CPUioGet(addr)&bit ) { ePC++; eCurrentCycle++; } break;                       //T1SN IO.n
      case 0x1C00: CPUioPut(addr,CPUioGet(addr)&~bit); break;                                        //SET0 IO.n
      case 0x1E00: CPUioPut(addr,CPUioGet(addr)|bit); break;                                         //SET1 IO.n
      case 0x2000: if( !(CPUmemGet(addr)&bit) ) { ePC++; eCurrentCycle++; } break;                   //T0SN M.n
      case 0x2200: if( CPUmemGet(addr)&bit ) { ePC++; eCurrentCycle++; } break;                      //T1SN M.n
      case 0x2400: CPUmemPut(addr,CPUmemGet(addr)&~bit);break;                                       //SET0 M.n
      case 0x2600: CPUmemPut(addr,CPUmemGet(addr)|bit);break;                                        //SET1 M.n
    }
  }
  else
  //3 bit opcodes 0x3000 - 0x3FFF
  if( (0x3000 == (opcode&0x3000)) )
  {

    if( opcode & 0x0800 ) //CALL needs to put current PC on stack
    {
      CPUmemPut( eSP++, ePC & 0xFF ); //TODO: check if on stack is little endian
      CPUmemPut( eSP++, ePC>>8 );     //TODO: check if on stack is little endian
    }
    eCurrentCycle++;
    ePC = opcode & 0x07FF;
  }
  else
  {
    //unknown instruction
    CPUexceptionEmulation("Unknown instruction", opcode );
  }

  CPUioPut(0x02,eSP);  //store SP to emulated IO port
  CPUioPut(0x00,eF);   //store flags to emulated IO port

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: david.given on November 19, 2018, 09:40:18 pm
Is there any possibility of there being an internal ROM with more code in it? That would explain the weird jumps and calls.

Do any of these things have SPI or I2C? Because if we ever figure out the programming protocol, and you could make one of these processors program another, you could incredibly cheaply build a hypercube cluster of the flash versions of these things, all bootstrapped from one processor at the corner attached to the outside world... it'd be useless, but fascinating. Sadly, without some sort of fast comms it's probably not worth it.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 19, 2018, 09:54:00 pm
If you are seeking for really fast emulation, why not a lookup table of function pointers? Keep in mind that, since it's an harvard architecture + OTP + no way to read raw data from ROM, it is feasible to pre-process the ROM code as you wish if that helps you encode the instructions in such a way that results in a faster interpretation, given you don't need the original content for other purposes other than interpreting the code.

For instance (just writing down what is passing through my mind right now, will need a lot of refinement, but the idea is this):

- map each instruction to an id (arbitrarly, whatever order you like) starting from 0 to the num of instr-1 so you can have a C array of pointers to functions that execute the instruction
- preprocess the ROM by "disassembling" the 14-bits or whatever-bits opcodes and representing them, for instance, as 3 bytes: one for the id, one for the first parameter and one for the second (if any)
- loop over the processed ROM and lookup the corresponding emulation function like instr_funcs[instr_id]();, place the two parameters in a couple of globals or just let the emulation functions pick them up relative to the PC (which is global ofc)
- the emulated function does it stuff and returns

not sure how to cleanly handle cycle-accurate though, I'll have to think about that.

This may be a bit slower than your fastest if (opcode ...) evaluation, but you gain a constant and predictable time for all instructions, which I think is preferrable especially if the code that runs a cycle of the emulated CPU is inside an interrupt handler which fires at <x> MHz. All of this is assuming you're not on Cortex-M7 i.e. there's no cache in between, that messes everything up obviously.

Another (reeeeeally cool) thing to do would be JIT, I have no idea if that could be feasible given how different the architectures are, and of course you would lock yourself to ARM Cortex, but that would be indeed really cool.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 19, 2018, 10:12:10 pm
Is there any possibility of there being an internal ROM with more code in it? That would explain the weird jumps and calls.

Do any of these things have SPI or I2C? Because if we ever figure out the programming protocol, and you could make one of these processors program another, you could incredibly cheaply build a hypercube cluster of the flash versions of these things, all bootstrapped from one processor at the corner attached to the outside world... it'd be useless, but fascinating. Sadly, without some sort of fast comms it's probably not worth it.

The is a reserevd are of, depeding on the device 8 to 32 words at the end of the ROM. Not a place to hide a lot of code, but, as already explained (and stated in the documentation) for checksums, rolling code, oscillator calibration data, code options. Since the 13-bit and 14-bit instruction sets do not have the ltabh and ltabl instructions, on those devies the rollign code is implemented as ret k instruction. You jump into the code, immediately jump back, and get the data byte in the accumulator.

The devices do not have I²C or SPI. But it can easily be emulated in software. That's actually one of the good things about the multicore design: You let one core handle some I/O protocol, and another core handles your normal program. IMO, this can be a good alternative to hardware peripherals. It makes the hardware simpler, cheaper, and all the gates can be used for the tasks at hand, instead of many of them sitting idle.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 19, 2018, 10:14:24 pm
Perhaps more relevant to these discussions is my past-life of creating development tools for little processors (mostly 8-bit). C compilers, assemblers, debuggers, simulators etc.
[…]
** Mostly retired now, but always up for an interesting project!

Would you be interested in contributing to SDCC, a free C compiler targeting small devices? There is a bit of a lack of developers and developer time recently. SDCC is still progressing, but some backends have fallen a bit behind (and of course there is work to do in the frontend, too).

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: david.given on November 19, 2018, 10:36:27 pm
Wait, are you the Dunfield C Dunfield?

I think way back when when I was looking for a portable C compiler I kept running into your C page and thinking it looked ideal and then cursing its closed source-ness... then Amsterdam Compiler Kit got open sourced, and it was so awful to build I begged a copy of the source repository from Ceriel Jacobs, uploaded it to SourceForge, and became the maintainer for it. (I think I now have the oldest genuine timestamps on github.)

With modern eyes I see now that Micro-C is K&R, so it wouldn't have been any good to me back then, but it's still amazingly small. If you're ever thinking of releasing the source I'd be fascinated to see how it works. (Cowgol's a lot larger, and I needed to split it into eight different compiler passes to make it run on a 6502...)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 19, 2018, 10:56:31 pm
Padauk is not making any money selling the programmer, so why don't ask them for the programming protocol?
The have been asked and they refused to provide any information.

It could make sense to reverese-engineer the protocol for the Flash-based devices first:

1) These devices are probably more interesting to us than the OTP ones
2) The protocol is simpler (less voltages, max 8V on ICVPP)
3) The pins used are documented with signal names (VDD, GND, ICVPP, ICPDA, ICPCK)

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: david.given on November 19, 2018, 11:49:52 pm
I don't know if the protocol's the same, but ICPCK/ICPDA are the same names that Holtek use for their line of ludicrously cheap microcontrollers.

http://www.holtek.com/documents/10179/106680/Holtek_Flash_MCU_Quick_Start_Guide_V100_en.pdf (http://www.holtek.com/documents/10179/106680/Holtek_Flash_MCU_Quick_Start_Guide_V100_en.pdf)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DDunfield on November 20, 2018, 03:34:45 pm
Would you be interested in contributing to SDCC, a free C compiler targeting small devices?

Probably not, I've not seen much open-source code I'd be happy working on... but that's a different discussion.


Wait, are you the Dunfield C Dunfield?

Mea culpa!

Regarding the source, I've not made it publicly available, but I've been known to give it out to interested parties.

For things not pertaining to the Padauk discussion, please contact me off list. Either through the messaging here (I'll try to check it at least every couple of days), or to my email at:

  my-first-name{dot}my-last-name{@}gmail{dot}com


Regarding simulation:

With modern tools, "switch" can be as efficient as a function call table, and you can avoid the overhead of functions entry/exit on each instruction (which can be several instructions to establish and release a stack frame).

I find the most difficult part doing the flags... C has a disadvantage of not having visibility to the processor flags, so when coding a simulator in C you need to work out the flag updates manually. This is usually more operations than performing the main operation of the simulated instruction.

Back in the day, when PC's were not a whole lot faster than the embedded systems we were emulating, I coded the simulation functions in assembly language, where I could reduce decoding to a very simple jump table, and access the flags set by the operation directly (which are usually at least similar to the setting of flags on the target processor.

My EMILY52 simulator could emulate an 8051/52 in real time on a Pentium1 (or even a decent 486). The simulation engine was coded in 8086 assembly and had an advantage that the 8051 flags were very similar to the 8086 flags. Instruction that didn't set flags would jump directly back to the next decode, instructions which set flags jumped to one of several routines which saved the flags in question (I think there were 3 or 4 different combinations of flags set by instructions) before heading on back to the next decode.

For instructions which used the flags, I simply loaded the 8086 flags from the saved flags before executing the instruction. When the flags were read as a byte, I used a lookup table to translate the saved 8086 flags into the corresponding 8051 flags positions.

8051 registers were only saved/restored to 8086 registers when the simulation stopped or started ... while running, they resided in 8086 registers and did not have to be loaded "per instruction".

Thing ran fast! - on more modern systems, it runs considerably faster than a hardware 805x ... It was so "streamlined" that the simulation engine had no "test for exit" .. just a tight instruction decode loop. When the user hit "STOP" I would plant a JMP instruction into the loop to break it which was then patched back by the exit handler.

Another technique I've used in the past to achieve high-speed simulation, which works well if:
 1) You can live with variance in the speed the first time a block of code gets executed,
 2) You don't support or accept higher overhead for self-modifying code

Is to have an array of JMP targets for every address (easy if you processor has 1024 words of code memory, harder if it has megs)... At the beginning, each JMP targets a routine which decodes the instruction and updates the JMP target to point to the handler for that instruction before launching it.

On subsequent passes the JMP branches directly to the correct instruction handler, and never even has to look at the opcode.

This is particularity effective if the opcodes are complex to decode words. For simple opcodes, a simple JMP table will be nearly as fast and much simpler to debug.


On a PC I'd probably use a simple JMP table for the PMS150, 13 bit = 8k words (32k bytes) and would give you one simple direct jump to the correct handler.

On the STM with 64K of code, 32K would be a bit much, I'd probably divide the opcodes into blocks based on which bits are used and decode with ANDs and a few switches.

But I haven't really looked into it that far yet...

Dave


Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 21, 2018, 09:11:58 pm
Hi,

I disassembled and commented the code which the IDE inserts at the start of the OTP.

This code is used for calibration of the internal high speed RC oscillator.

It looks like WRITER is doing the following:

1. write the complete OTP and set the calibration value to 0xFF (actually a RET 0xFF)
2. reset the IC and wait for IC to execute the calibration measurement program (handshake and bit bang protocol using WRITER_CLK:PA.3 / WRITER_DAT_OUT:PA.5 / WRITER_DAT_IN:PA.6)
3. write the calibration value over the 0xFF value

=> This is a trick. The OTP is intial all '1'. Programing can change a '1' to a '0' ... but never back to one. So writing 0xFF leaves this cell all '1' and later when the real value is present it can be written there.

As you can see the (quite big) calibration code wastes some valuable OTP.
There is also a small programing mistake inside (near the end of the calibration)  8). ==> @PADAUK: maybe you want to fix it :-) (the mistake is harmless since WRITER can just reset the IC in order to restart a calibration, again ==> @PADAUK: you can save some valuable space here by just removing instructions from 0x004F - 0x0052)
With a little bit of practice the code also could be stripped here and there. Something we can do in future  :)


0x0000:   0x0070    WDRESET                     ;reset watchdog

0x0001:   0x2f00    MOV A, 0x00     
0x0002:   0x0182    MOV IO(0x02), A  ;SP        ;set SP to memory start (0)

0x0003:   0x3fed    CALL 0x7ED                  ;get IHRCR (value inserted from WRITER)
0x0004:   0x018b    MOV IO(0x0B), A  ;IHRCR     ;setup IHRCR

0x0005:   0x3fee    CALL 0x7EE
0x0006:   0x019a    MOV IO(0x1A), A             ;BGTR? (not in datasheet)

0x0007:   0x2f00    MOV A, 0x00                 ;setup low voltage detector (value inserted from IDE .CHIP)
0x0008:   0x019b    MOV IO(0x1B), A             ;MISC_LVR 4V/3V5/3V/2V75/2V5/1V8/2V2/2V

0x0009:   0x2f34    MOV A, 0x34     
0x000a:   0x0183    MOV IO(0x03), A  ;CLKMD     ;setup clock mode (value inserted from IDE .ADJUST_IC)

0x000b:   0x3ffe    CALL 0x7FE                  ;get stored calibration value (stored during programing of OTP)

;This is a nice trick. The OTP reads all as '1' when not programmed. Programing will change the relevant bits to '0'.
;The trick is that you can program the OTP multiple times. It is always possible to change '1' to '0' but never the other way around.
;So they store 0x02FF in code memory at position 0x7FE which translates to RET 0xFF. Later programer can change the 0xFF return value by
;overwriting it with the final value (0xFF still all bits '1').
;This means all the code follows is used for calibration during programing only (big waste of OTP)

0x000c:   0x2aff    CEQSN A, 0xFF               ;Check if is 0xFF (nothing written there?)
0x000d:   0x3054    GOTO 0x054                  ;Jump over calibration routine to user program

0x000e:   0x3fed    CALL 0x7ED                  ;get IHRCR (value inserted from programmer)
0x000f:   0x0b81    MOV [0x01], A               ;store it in memory @0x01

0x0010:   0x1f91    SET1 IO(0x11).6  ;PAC.6     ;configure PA.6 as output

;calibration routine
0x0011:   0x2f20    MOV A, 0x20     
0x0012:   0x0b80    MOV [0x00], A               ;store 0x20 in memory @0x00

0x0013:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x0014:   0x3013    GOTO 0x013                  ;wait until PA.3 is high

0x0015:   0x1f90    SET1 IO(0x10).6  ;PA.6      ;set PA.6 to HIGH                <-- send response to WRITER

0x0016:   0x0063    DZSN A                      ;1c big delay, underflows after first loop
0x0017:   0x3016    GOTO 0x016                  ;2c inner loop apx. 3*256 cycles = 768 cycles
0x0018:   0x1180    DZSN [0x00]                 ;1c
0x0019:   0x3016    GOTO 0x016                  ;2c outer loop apx. 32*(768+3) = 24672 cycles,
                                                ;-224 cycles from first inner loop (was init with 32 instead of 255) = 24448 cycles total delay

0x001a:   0x1d90    SET0 IO(0x10).6  ;PA.6      ;set PA.6 to LOW                 <-- stop sending response to WRITER

0x001b:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x001c:   0x301b    GOTO 0x01B                  ;wait until PA.3 is low

0x001d:   0x2f01    MOV A, 0x01     
0x001e:   0x1950    T0SN IO(0x10).5  ;PA.5      ;if PA.5 is LOW ==> A=0x01 , HIGH ==> A=0xFF <-- WRITER sets ? ? ? value to 1/255 by setting PA.5
0x001f:   0x2fff    MOV A, 0xFF     

0x0020:   0x0c01    ADD A, [0x01]               ;add to IHRCR (value inserted from programmer) 1 or 255 (see above)
0x0021:   0x018b    MOV IO(0x0B), A  ;IHRCR     ;set new IHRCR
0x0022:   0x0b81    MOV [0x01], A               ;store new IHRCR value in memory @0x01

0x0023:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x0024:   0x3023    GOTO 0x023                  ;wait until PA.3 is high

0x0025:   0x1b50    T1SN IO(0x10).5  ;PA.5      ;check for HIGH signal at PA.5   <-- WRITER signals all done?
0x0026:   0x304f    GOTO 0x04F                  ;jump to end of calibration code

0x0027:   0x2f04    MOV A, 0x04     
0x0028:   0x0188    MOV IO(0x08), A  ;MISC      ;disable low voltage detector

0x0029:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x002a:   0x3029    GOTO 0x029                  ;wait until PA.3 is low

;start measurment
0x002b:   0x2f02    MOV A, 0x02
0x002c:   0x0182    MOV IO(0x02), A  ;SP        ;setup SP to memory @0x02

0x002d:   0x1304    CLEAR [0x04]                ;zero memory @0x04
0x002e:   0x1305    CLEAR [0x05]                ;zero memory @0x05
0x002f:   0x2f55    MOV A, 0x55
0x0030:   0x0b82    MOV [0x02], A               ;store 0x55 in memory @0x02
0x0031:   0x2f00    MOV A, 0x00     
0x0032:   0x0b83    MOV [0x03], A               ;store 0x00 in memory @0x03

;16 bit loop (0x0055) times some operations with internal value LDSPTL:LDSPTH (timing register?)
0x0033:   0x0006    LDSPTL                      ;?load from timing register L
0x0034:   0x0b04    XOR [0x04], A
0x0035:   0x0007    LDSPTH                      ;?load from timing register H
0x0036:   0x0805    ADD [0x05], A

0x0037:   0x1584    SL [0x04]                   ;rotate left 16 bit value
0x0038:   0x1685    SLC [0x05]
0x0039:   0x1004    ADDC [0x04]

0x003a:   0x1282    DECM [0x02]                 ;memory low byte -1
0x003b:   0x1083    SUBC [0x03]                 ;memory high byte -1 if carry set
0x003c:   0x1a40    T1SN IO(0x00).1  ;FLAG.CF   ;test for carry (0x0000 -1 => carry set)
0x003d:   0x3033    GOTO 0x033                  ;loop

0x003e:   0x1f90    SET1 IO(0x10).6  ;PA.6      ;set PA.6 to HIGH                <-- send response to WRITER (measurement finished)


;send bit by bit the 16 bit measured value
0x003f:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x0040:   0x303f    GOTO 0x03F                  ;wait until PA.3 is high

0x0041:   0x1584    SL [0x04]                   ;16 bit shift left
0x0042:   0x1685    SLC [0x05]

0x0043:   0x0590    SWAPC IO(0x10).6 ;PA.6      ;set PA.6 according to carry (highest bit from 16 bit value before shift)

0x0044:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x0045:   0x3044    GOTO 0x044                  ;wait until PA.3 is low

0x0046:   0x1950    T0SN IO(0x10).5  ;PA.5      ;check if PA.5 is LOW            <-- WRITER signals to send next bit
0x0047:   0x303f    GOTO 0x03F


0x0048:   0x1d90    SET0 IO(0x10).6  ;PA.6      ;set PA.6 to LOW

0x0049:   0x1ad0    T1SN IO(0x10).3  ;PA.3      ;check for HIGH signal at PA.3   <-- check for handshake signal for WRITER
0x004a:   0x3049    GOTO 0x049                  ;wait until PA.3 is high

0x004b:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3    <-- wait for WRITER to stop sending handshake signal
0x004c:   0x304b    GOTO 0x04B                  ;wait until PA.3 is low

0x004d:   0x1b50    T1SN IO(0x10).5  ;PA.5      ;check for HIGH signal at PA.5   <-- WRITER signals to redo measurement
0x004e:   0x302b    GOTO 0x02B                  ;if PA.5 is LOW do the measurement again

;here seems to be an error in the program from PADAUK, very unlikely PA.3 went hight during last 2 instructions, should be HIGH check for sure
0x004f:   0x18d0    T0SN IO(0x10).3  ;PA.3      ;check for LOW signal at PA.3
0x0050:   0x304f    GOTO 0x04F                  ;wait until PA.3 is low

0x0051:   0x1b50    T1SN IO(0x10).5  ;PA.5      ;check for HIGH signal at PA.5   <-- WRITER signals all done?
0x0052:   0x3011    GOTO 0x011                  ;if PA.5 is LOW do the complete calibration again (including all handshakes)

0x0053:   0x3053    GOTO 0x053                  ;calibration successful, endless loop (chip needs reset + writing of calibration value from WRITER)

;----------------------------------------------------------------------------------------------------------------------------------------------

0x0054:   0x018b    MOV IO(0x0B), A  ;IHRCR     ;normal program start, set IHRCR

0x0055:   0x3055    GOTO 0x055                  ;the user program (was just a "while(1){}" loop)


Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 21, 2018, 09:37:49 pm
Nice job js_12345678_55AA, really interesting. Will take an in depth look.

At the moment I also got the 13-bit ISA implemented in my infrastructure so I can disassemble PMS150 (C) ROMs. I noticed an interesting thing (I still have to look at the disasm). The PMS150 (without the C) has an order of magnitude less init code compared to the PMS150C (which seems to have code that more or less does the same stuff the 154C is doing).

I'm attaching the two listings if someone wants to take a look and start figuring it out.

(to discriminate what's "my" code and PADAUK's code, in both ROMs I only have the main which is simply incrementing a byte in memory, you'll find the inc [0x...]; goto @0x... as the last two instructions in both listings, that are the only two things not part of the init code)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 22, 2018, 12:02:57 am
After checking the disassembly of the calibration again some things look suspicious:


;start measurment
0x002b:   0x2f02    MOV A, 0x02
0x002c:   0x0182    MOV IO(0x02), A  ;SP        ;setup SP to memory @0x02

0x002d:   0x1304    CLEAR [0x04]                ;zero memory @0x04
0x002e:   0x1305    CLEAR [0x05]                ;zero memory @0x05
0x002f:   0x2f55    MOV A, 0x55
0x0030:   0x0b82    MOV [0x02], A               ;store 0x55 in memory @0x02
0x0031:   0x2f00    MOV A, 0x00     
0x0032:   0x0b83    MOV [0x03], A               ;store 0x00 in memory @0x03

;16 bit loop (0x0055) times some operations
0x0033:   0x0006    LDSPTL                      ;load from memory where SP is pointing to A
0x0034:   0x0b04    XOR [0x04], A
0x0035:   0x0007    LDSPTH                      ;load from memory where SP is pointing to A
0x0036:   0x0805    ADD [0x05], A

0x0037:   0x1584    SL [0x04]                   ;rotate left 16 bit value
0x0038:   0x1685    SLC [0x05]
0x0039:   0x1004    ADDC [0x04]

0x003a:   0x1282    DECM [0x02]                 ;memory low byte -1
0x003b:   0x1083    SUBC [0x03]                 ;memory high byte -1 if carry set
0x003c:   0x1a40    T1SN IO(0x00).1  ;FLAG.CF   ;test for carry (0x0000 -1 => carry set)
0x003d:   0x3033    GOTO 0x033                  ;loop


At the beginning the SP is setup to point to a new location. SP / stack is never used anywhere after this point in calibration program.
So the only use could be from the undocumented instructions LDSPTL and LDSPTH. Also SP points to the memory which is initialized
with static values.

This lets me think LDSPTL/LDSPTL stands for "LoaD from SP Table Low" / "LoaD from SP Table High":
  LDSPTL   =>   A = [SP]
  LDSPTH   =>   A = [SP+1]

Then the above loop would be again some "obfuscation" crypto from PADAUK (XOR 0x55 ... smells like the magic value they love, known from IDE obfuscation).

The result in this case is just 0x11E4 which is then sent out via bitbang to the WRITER to "verify"  :-DD

The loop also serves the purpose to run for several cycles, so WRITER can measure the time it takes and use it for calibration.


JS

EDIT: The loop runs for exact 1040 cycles (including loop init)  :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: amyk on November 22, 2018, 03:54:49 am
I sorted the 13-bit instructions in opcode order; some interesting patterns emerge (notice ADD SUB ADDC SUBC AND OR XOR MOV), as well as possible present-but-undocumented instructions:

Code: [Select]
00000 00000000  NOP
00000 00000000  TRAP     // Assembler accepts, but same as NOP
00000 00000001
 ..      ..     ??
00000 00001111
00000 00010000  ADDC      A
00000 00010001  SUBC      A
00000 00010010  IZSN      A
00000 00010011  DZSN      A
00000 00010100
 ..      ..     ??
00000 00010110
00000 00010111  PCADD     A
00000 00011000  NOT       A
00000 00011001  NEG       A
00000 00011010  SR        A
00000 00011011  SL        A
00000 00011100  SRC       A
00000 00011101  SLC       A
00000 00011110  SWAP      A
00000 00011111
 ..      ..     ??
00000 00101111
00000 00110000  WDRESET
00000 00110001  ?
00000 00110010  PUSHAF
00000 00110011  POPAF
00000 00110100  ?
00000 00110101  RESET
00000 00110110  STOPSYS
00000 00110111  STOPEXE
00000 00111000  ENGINT
00000 00111001  DISGINT
00000 00111010  RET
00000 00111011  RETI
00000 00111100
 ..      ..     ??
00000 01011111
00000 011ppppp  XOR       io-addr,A
00000 100ppppp  MOV       io-addr,A
00000 101ppppp  MOV       A,io-addr
00000 110aaaa0  STT16     ram-addr-even
00000 110aaaa1  LDT16     ram-addr-even
00000 111aaaa0  IDXM      ram-addr-even,A
00000 111aaaa1  IDXM      A,ram-addr-even
00001 dddddddd  RET       imm-data
00010 bbb0aaaa  T0SN      ram-addr.bit
00010 bbb1aaaa  T1SN      ram-addr.bit
00011 bbb0aaaa  SET0      ram-addr.bit
00011 bbb1aaaa  SET1      ram-addr.bit
00100 00aaaaaa  ADD       ram-addr,a
00100 01aaaaaa  SUB       ram-addr,a
00100 10aaaaaa  ADDC      ram-addr,A
00100 11aaaaaa  SUBC      ram-addr,A
00101 00aaaaaa  AND       ram-addr,A
00101 01aaaaaa  OR        ram-addr,A
00101 10aaaaaa  XOR       ram-addr,A
00101 11aaaaaa  MOV       ram-addr,A
00110 00aaaaaa  ADD       A,ram-addr
00110 01aaaaaa  SUB       A,ram-addr
00110 10aaaaaa  ADDC      A,ram-addr
00110 11aaaaaa  SUBC      A,ram-addr
00111 00aaaaaa  AND       A,ram-addr
00111 01aaaaaa  OR        A,ram-addr
00111 10aaaaaa  XOR       A,ram-addr
00111 11aaaaaa  MOV       A,ram-addr
01000 00000000
 ..      ..     ??
01000 01111111
01000 10aaaaaa  IZSN      ram-addr
01000 11aaaaaa  DZSN      ram-addr
01001 00aaaaaa  INC       ram-addr
01001 01aaaaaa  DEC       ram-addr
01001 10aaaaaa  CLEAR     ram-addr
01001 11aaaaaa  XCH       ram-addr
01010 00aaaaaa  NOT       ram-addr
01010 01aaaaaa  NEG       ram-addr
01010 10aaaaaa  SR        ram-addr
01010 11aaaaaa  SL        ram-addr
01011 00aaaaaa  SRC       ram-addr
01011 01aaaaaa  SLC       ram-addr
01011 10aaaaaa  CEQSN     A,ram-addr
01011 11000000
 ..      ..     ??
01011 11111111
01100 bbbppppp  T0SN      io-addr.bit
01101 bbbppppp  T1SN      io-addr.bit
01110 bbbppppp  SET0      io-addr.bit
01111 bbbppppp  SET1      io-addr.bit
10000 dddddddd  ADD       A,imm-data
10001 dddddddd  SUB       A,imm-data
10010 dddddddd  CEQSN     A,imm-data
10011 00000000
 ..      ..     ??
10011 11111111
10100 dddddddd  AND       A,imm-data
10101 dddddddd  OR        A,imm-data
10110 dddddddd  XOR       A,imm-data
10111 dddddddd  MOV       A,imm-data
110aa aaaaaaaa  GOTO      code-addr
111aa aaaaaaaa  CALL      code-addr
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 22, 2018, 06:51:54 am
Nice job js_12345678_55AA, really interesting. Will take an in depth look.

At the moment I also got the 13-bit ISA implemented in my infrastructure so I can disassemble PMS150 (C) ROMs. I noticed an interesting thing (I still have to look at the disasm). The PMS150 (without the C) has an order of magnitude less init code compared to the PMS150C (which seems to have code that more or less does the same stuff the 154C is doing).

I'm attaching the two listings if someone wants to take a look and start figuring it out.

(to discriminate what's "my" code and PADAUK's code, in both ROMs I only have the main which is simply incrementing a byte in memory, you'll find the inc [0x...]; goto @0x... as the last two instructions in both listings, that are the only two things not part of the init code)

Could you also add the 13-bit instructions to the documentation on GitHub?

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 22, 2018, 06:56:36 am
After checking the disassembly of the calibration again some things look suspicious:


;start measurment
0x002b:   0x2f02    MOV A, 0x02
0x002c:   0x0182    MOV IO(0x02), A  ;SP        ;setup SP to memory @0x02

0x002d:   0x1304    CLEAR [0x04]                ;zero memory @0x04
0x002e:   0x1305    CLEAR [0x05]                ;zero memory @0x05
0x002f:   0x2f55    MOV A, 0x55
0x0030:   0x0b82    MOV [0x02], A               ;store 0x55 in memory @0x02
0x0031:   0x2f00    MOV A, 0x00     
0x0032:   0x0b83    MOV [0x03], A               ;store 0x00 in memory @0x03

;16 bit loop (0x0055) times some operations
0x0033:   0x0006    LDSPTL                      ;load from memory where SP is pointing to A
0x0034:   0x0b04    XOR [0x04], A
0x0035:   0x0007    LDSPTH                      ;load from memory where SP is pointing to A
0x0036:   0x0805    ADD [0x05], A

0x0037:   0x1584    SL [0x04]                   ;rotate left 16 bit value
0x0038:   0x1685    SLC [0x05]
0x0039:   0x1004    ADDC [0x04]

0x003a:   0x1282    DECM [0x02]                 ;memory low byte -1
0x003b:   0x1083    SUBC [0x03]                 ;memory high byte -1 if carry set
0x003c:   0x1a40    T1SN IO(0x00).1  ;FLAG.CF   ;test for carry (0x0000 -1 => carry set)
0x003d:   0x3033    GOTO 0x033                  ;loop


At the beginning the SP is setup to point to a new location. SP / stack is never used anywhere after this point in calibration program.
So the only use could be from the undocumented instructions LDSPTL and LDSPTH. Also SP points to the memory which is initialized
with static values.

This lets me think LDSPTL/LDSPTL stands for "LoaD from SP Table Low" / "LoaD from SP Table High":
  LDSPTL   =>   A = [SP]
  LDSPTH   =>   A = [SP+1]

Then the above loop would be again some "obfuscation" crypto from PADAUK (XOR 0x55 ... smells like the magic value they love, known from IDE obfuscation).

The result in this case is just 0x11E4 which is then sent out via bitbang to the WRITER to "verify"  :-DD

The loop also serves the purpose to run for several cycles, so WRITER can measure the time it takes and use it for calibration.


JS

EDIT: The loop runs for exact 1040 cycles (including loop init)  :)

Well, 0x55 is a value commonly used in self tests (you'll also see it used as a pattern in memory testers, etc). It has every other bit set, so if there is any interference between adjacent lines it can help detect that. Maybe the program above is one that their test enginers designed to test the ALU? E.g. by making the final result depend on nearly all logic gates or connections in the ALU working correctly?

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 22, 2018, 07:15:19 am
SP / stack is never used anywhere after this point in calibration program.
So the only use could be from the undocumented instructions LDSPTL and LDSPTH.

Uhm, don't assume that because the init code initializes the SP it means that he init code uses the stack/SP register. The init code may very well be just initializing it for the user program and stuff.

Also SP points to the memory which is initialized with static values.

It may just be that they had to store some values and instead of touching the upper memory where the MiniC compiler usually places user variables (at least that's what I noticed) they preferred to use the first locations given they will be overwritten by the first push on the stack so "who cares". Maybe for a more "defined" undefined behaviour  :-DD
I mean, unless you fill your ram with vars and you have variables in 0x00, 0x01, ... you'll never end up reading by accident the values that the init code put somewhere, which is coherent with the fact that they're trying to totally hide the init code and its internal working/effects from the user.

This doesn't mean your hypothesis is wrong, IMHO it is very likely that those two instructions act on the stack in that way. But I just wanted to share my thoughts to look at that in a more objective way.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 22, 2018, 07:21:43 am
Could you also add the 13-bit instructions to the documentation on GitHub?

Even better, as soon as I have some time I'll try to find a rule to derive the 13-bit ISA from the 14-bit one. Trust me, after writing by hand dozens of instructions to implement them in the disasm, I can tell there is A LOT of symmetry. I still didn't go in depth but seems it is just something like one bit missing. As soon as I figure that out I'll probably write a tool to do a mass-conversion from the 14-bit docs already up and eventually adjust by hand. Unless someone is already documenting the 13-bit one.

Also, js_12345678_55AA, I had a pull on the docs repo fixing some stuff that is still unfixed after your last commit (a couple of instr swapped IIRC), maybe you want to check that out.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 22, 2018, 12:06:21 pm
Also, js_12345678_55AA, I had a pull on the docs repo fixing some stuff that is still unfixed after your last commit (a couple of instr swapped IIRC), maybe you want to check that out.

Sorry, I did not see the pull request. I merged it now and added you as a project member to github.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 22, 2018, 12:33:20 pm
After reading your comments, resting a bit and looking at the init code again I think I found the real purpose.

It is a CHECKSUM of the code in ROM.

-> the value 0x0055 is the code size (it grows and shrinks when I compile programs with more/less code, verified with IDE)
-> LDSPTL and LDSPTH needs to be 2 different instructions so it can load indirect the low and high byte of the code memory
-> Since code memory can be bigger than 8 bit the pointer to load from needs to be 16bit -> they use the memory where SP is pointing to to store 2 bytes (the pointer to code memory)
-> the XOR, ADD and ROR is just the checksum algorithm they use

LDSPTL: A = LowByte(CodeMem([SP 16bit]))
LDSPTH: A = HighByte(CodeMem([SP 16bit]))

The 16 bit loop counter in init code also serves as pointer into code mem. So it calculates backwards a checksum of all *used* code memory (excluding unused space and special data at end of chip, IDE inserts the real code length in init code).

Only question left is... What are the MSB of LDSPTH when we only have 14 bit stored. Either they read as '1' or as '0'. Experiments with real hardware will show.


Since reading code memory is always a potential thread for chip readout security it would be understandable why this instructions are not in PADAUK user manual.

But with this method we can now store 14 bit tables instead of 8 bit only per instruction word

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 22, 2018, 03:37:14 pm
The checksum thing makes sense only if the programmer is not able to read back the OTP whenever it likes (which I guess is the case). Does that mean you can only verify the code if you disabled "security" or before the calibration phase?

Also worth noting that the PMS150 (non-C version) doesn't have any code like that by looking at its listing (I uploaded it some posts ago). That in fact makes sense, I just checked and the non C version doesn't have the "security" feature you can enable/disable. This mean the programmer can get away calculating the checksum just by reading the OTP which can always be read.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 22, 2018, 04:14:12 pm
There might be an explanation why they do all these checks from another post:

Back in 2006 I was talking to a uC manufacturer in China about their 4 bit uC then costing $0,11 and lower with high volume we were discussing. It could replace $0,40 of logic on our boards so quite interesting with massproduction.
There were some bizar quirks in those things. They were manufactured for one single goal: cheap toys.
The manufacturing process was not as you expect from fabs these days with a result that in your firmware at boottime you had to test the ram since unknown bits would (not could) be dead and you had to make a map so not to use that byte in ram. Also upto 2% of the devices would have problems in the alu or other critical parts. I asked how I could know that the first code would run ok if the ram was not to be trusted. The answer was you could tell from the end product if it worked or not. :-DD
I couldnt believe this but had it b&w in an email.
They probably also sell 100% tested uCs that had no flaws but that was pricewise much less interesting.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 22, 2018, 05:07:54 pm
Actually they even hint to that in their product description. That or low ESD tolerance as that doesnt seem to be selling argument for the cheapest chips.
I guess we will see once someone has programmed a few.

PMC150:
**Very stable performance.
**Using 0.5um OTP process with High EFT proprietary design
**Allow using at high EFT requirement products such as home-appliances and durables etc.
**Operating temperature range: -40°C ~ 85°C

PMS150:
**Valuable price
**Using 0.5um OTP process
**Good for battery or DC power based products but required higher noise immunity
**Not supposed to use in AC RC step-down powered or high EFT requirement applications
**Operating temperature range: -20°C ~ 70°C

PMS150C:
**Very Competitive price
**Using 0.18um OTP process
**Good for battery or DC power based products, such as toys or premiums etc.
**Not supposed to use in AC RC step-down powered or high EFT requirement applications
**Operating temperature range: -20°C ~ 70°C
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 23, 2018, 12:01:06 pm
Hi,

I just got my ICE today... and when you connect it and start debugging you can bring up a disassembly window (no opcodes of course but good to verify our stuff).

I created a new project (name "P2") for PFS154 with the following sample code in "P2.C" (no real purpose, just to check the init code):
Code: [Select]

 #include  "extern.h"



void<>FPPA0 (void)
{
  .ADJUST_IC  SYSCLK=IHRC/2    //  SYSCLK=IHRC/2


  while (1){}
}

Then I compiled it and now we got 2 outputs:
 
  - "P2_IDE_LST.txt" is what I got from IDE).

  - "P2_DIS_LST.txt" is from my disassembler using the opcodes we found out


You can see that they hide the "secret" checksum calculation part by inserting a bunch of NOPs (actually ICE really executes NOPs only there). There are also some funny instructions in their output (e.g. when there is an undefined IO)

left from IDE / right from custom disassembler
Code: [Select]
...
00000008     MOV ---- A      /         0x0008:   0x019b    MOV IO(0x1B), A  ;
...
00000033     NOP             /         0x0033:   0x0006    LDSPTL       
00000034     NOP             /         0x0034:   0x0b04    XOR [0x04], A
00000035     NOP             /         0x0035:   0x0007    LDSPTH       
00000036     NOP             /         0x0036:   0x0805    ADD [0x05], A
00000037     NOP             /         0x0037:   0x1584    SL [0x04]   
00000038     NOP             /         0x0038:   0x1685    SLC [0x05]   
00000039     NOP             /         0x0039:   0x1004    ADDC [0x04] 
0000003A     NOP             /         0x003a:   0x1282    DECM [0x02] 
0000003B     NOP             /         0x003b:   0x1083    SUBC [0x03] 
...


Unfortunately when I try to make a program with the undocumented instructions LDSPTL and LDSPTH it compiles fine, but ICE also inserts NOPs there so I can not test their behavior (I need to wait for PFS154 to arrive so I can play with the real IC).

Anyway, our opcode table looks very accurate. :)

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 03:21:32 pm
Hi,

I just got my ICE today... and when you connect it and start debugging you can bring up a disassembly window (no opcodes of course but good to verify our stuff).


Is there any way you could determine the type of fpga they are using?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 23, 2018, 03:34:09 pm
Is there any way you could determine the type of fpga they are using?

I will try. Without removing the cover it looks like the surface of the big IC was "chinese polished" (with Dremel  :)).

Will post some pictures later.

JS

EDIT:
USB enumeration shows this:
VID: 0x0797
PID: 0x7002
Device String: "LGS_DEV FX2-HID 0.01"

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 03:50:43 pm
EDIT:
USB enumeration shows this:
VID: 0x0797
PID: 0x7002
Device String: "LGS_DEV FX2-HID 0.01"

The FPPA_IDE.exe has some strings in it refering to:
L.G.S. TECHNOLOGY CO. ,LTD
K.K.K. TECHNOLOGY CO. ,LTD
Kent Lee Developer Studio Version 2014 and an email adress lgs.........@yahoo.com.tw
http://home.kimo.com.tw/lgs............/WEB_EXE_.jpg (http://home.kimo.com.tw/lgs............/WEB_EXE_.jpg)
D:\\KentLee\\Custom\\PDK80\\Source\\Refer\\Test_IC\\Wrt_ROM\\Wrt_ROM.txt

Also the device string you found is included in the exe along with some others:
x6337ec 17 16 IDW-360 FX2-HID
0x633800 17 16 PDK-ICE FX2-HID
0x633814 17 16 LGS-DEV FX2-HID
0x633828 17 16 LGS_DEV FX2-HID

0x6338d4 21 20 Writer : PDK3S-P-002
0x6338ec 30 29 Writer : PDK3S-P-002 (No Cap)
0x63390c 21 20 ICE    : PDK3S-I-002
0x633924 21 20 ICE    : PDK3S-I-003
0x63393c 17 16 SOCKET : EV3-004
0x633950 24 23 ICE    : PDK3S-I-004(*)
0x633968 21 20 ICE    : PDK5S-I-S01
0x633980 21 20 ICE    : PDK5S-I-S02
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 04:03:07 pm
BTW the FX2 chip used has its firmware programmed on the fly (ie when connecting to USB into its onboard RAM), so it should be possible to experiment with it without any risk of bricking it.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 23, 2018, 04:09:45 pm
I got my ICE today as well. Here is a high resolution image: https://i.imgur.com/8yef37g.jpg (https://i.imgur.com/8yef37g.jpg)

The FPGA has no markings. It might be possible to capture the JTAG init sequence, if it doesn't store the configuration data inside the FPGA, because looks like there is no external configuration flash memory.

The USB device is a CY7C68013A, with high speed USB (480 Mbps) and an integrated 8051 CPU, that can be booted through USB (there is an interesting project, which implements a communication through such a Cypress chip to a FPGA over USB, FPGALink (http://www.swaton.ukfsn.org/docs/fpgalink/vhdl_paper.pdf)). So this could be a very flexible construction, booting first the firmware of the 8051, then booting the FPGA bitstream, all over USB. But I think it might be easier to develop a new emulator than trying to reverse engineer this. Would be nearly impossible to decode the FPGA bitstream back to the HDL code.

"usb-devices" shows the same as js_12345678_55AA wrote:

Code: [Select]
T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=03 Dev#=  9 Spd=480 MxCh= 0                                                                                                                                             
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1                                                                                                                                                 
P:  Vendor=0797 ProdID=7002 Rev=80.01                                                                                                                                                                         
S:  Manufacturer=PADAUK                                                                                                                                                                                       
S:  Product=LGS_DEV FX2-HID 0.01                                                                                                                                                                             
C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=500mA                                                                                                                                                                       
I:  If#= 0 Alt= 0 #EPs= 2 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid   
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 04:17:33 pm
I got my ICE today as well. Here is a high resolution image: https://i.imgur.com/8yef37g.jpg (https://i.imgur.com/8yef37g.jpg)

The FPGA has no markings. It might be possible to capture the JTAG init sequence, if it doesn't store the configuration data inside the FPGA, because looks like there is no external configuration flash memory.


Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 23, 2018, 04:33:56 pm
I got my ICE today as well. Here is a high resolution image: https://i.imgur.com/8yef37g.jpg (https://i.imgur.com/8yef37g.jpg)

The FPGA has no markings. It might be possible to capture the JTAG init sequence, if it doesn't store the configuration data inside the FPGA, because looks like there is no external configuration flash memory.


Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.

I just ordered one of these PLCC remover from China. Will report back in 4 weeks when it arrives :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 04:55:10 pm
I just ordered one of these PLCC remover from China. Will report back in 4 weeks when it arrives :)

I try to anticipate these things and ordered my 3.5$ FX2 dev board a week ago  ;)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: mikeselectricstuff on November 23, 2018, 05:55:27 pm
Hi,

I just got my ICE today... and when you connect it and start debugging you can bring up a disassembly window (no opcodes of course but good to verify our stuff).


Is there any way you could determine the type of fpga they are using?
Could be a CPLD - plenty of PLC44 options showing on Digikey for that package. If there is 5V anywhere that would narrow it down a lot.

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 06:16:36 pm
Could be a CPLD - plenty of PLC44 options showing on Digikey for that package. If there is 5V anywhere that would narrow it down a lot.

I'm kind of hoping for a XC9572XL. It could very well be a cpld because the newest version (5S
-I-S02B dated 2017/7/24) of the ice also uses a socketed plcc44.

On second thought a CPLD probably does not have enough memory on board to emulate a full chip so must be something else.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: gdelazzari on November 23, 2018, 06:46:12 pm
I'm reporting a conversation between me and js_12345678_55AA regarding planning of what to do next (and how) if anyone wants to share its thoughts. Not sure why I didn't directly post here in the forum thread, sorry for that  :-//

The things of most interest are probably the assembler and the syntax

Quote
Hi,

>Hi, do you have any plans to upload your disassembler (and eventually assembler if you have one) to the GitHub organization?

Sure I will do (I just want to structure it a bit more, will take 1-2 days)


>I also have tools in a preliminary state working with the 13-bit and 14-bit ISAs, which unfortunately is duplicate work but I wanted to disasm some listings so I proceeded anyway in implementing them, but that was not a lot of work so it's not a problem for me to trash everything if we want to keep your infrastructure.

All of the code I did is also just for experimentation. Most likely it will be replaced by better implementations later. So no need to keep / stick to something from me right now.


>Also I think we should define a bit how we want to proceed with the assembler.

I did not start with an assembler implementation. Maybe this is something you/somebody else want to try?
I'm already busy reversing stuff and find out how things are connected.
Today my WRITER and SIMULATOR arrived. So now I can start to work with real hardware :-)


>Some stuff to be discussed may be:
>- syntax quirks (how to represent various kind of values/addresses), asm directives, macros, defines, includes, etc...

I did not really investigated on this. I just used a syntax which I thought was good enough for first tests.
Mainly I used the syntax PADAUK used in their manuals. Just to distinguish between RAM / ROM / IO we would need to invent something. Note: The "." syntax is mainly used to represent a special bit (8051 assembly). "[ ]" are used for normal memory access. "WORD PTR" is usually used for 16 bit address references, ... I think we should adapt already known schemes so it easier for others to understand

Creating a document defining the syntax of the assembler would be a good starting point.

I think during implementation of assembler some changes will be required. Since the disassembler is fairly easy to adapt I consider it to follow any syntax changes the assembler creator might need to do.


>- whether to deviate from PADAUK's ASM syntax and implement something of our own, or whether to implement their same syntax for compatibility; or even both at the same time (i.e. a flag to choose the syntax)

One syntax please :-). As close as possible to PADAUK syntax with just some extensions for direct memory/io access.


>- what binary format we want to use across the open source toolchain, i.e. just the raw ROM content on a .bin file, or keeping their PDK format for compatibility with their OTP Writer, or have our own format, or a mix of these three things, or whatever :)

I think we should use the PDK format. The creation for a "liberated" WRITER seems to be the most difficult part which most likely will take the longest time.


>- if it makes sense to keep the ISA description open enough so that it can be imported by someone that wants to implement for instance an SDCC backend or a radare2 plugin to disasm, etc... or just keep it simple and hard coded in the tools

The ISA is so small and simple, everyone can adapt and implement it for a disasm within a few hours. So I think there is no need to be generic here.


>Also, regarding an hypothetical PC simulator (not real time, maybe cycle accurate, or even not) for debugging only:

Why "hypothetical PC simulator"? I finished this task already  8)


>- how that would be presented to the user, i.e.
>- a GUI? With what features? I/O interaction?
>- some kind of simulation you launch and outputs a waveform file in some standard format for inspection later (and that can also accept an input waveform file or some kind of description of what to do with the inputs - i.e. after 0.1s set PA.3 high etc...)
>- a command line tool like GDB where you can single step, inspect memory and regs, run, pause, etc...
>- a combination of some of the things above
>- ...

I was having a look at a 8051 emulator which uses ncurses ( https://github.com/jarikomppa/emu8051 ). This simulator I plan to repurpose for the front end.


>- we'll need our own init code if we want to create a full toolchain you can use from start to finish without touching PADAUK's tools, what should be done in that regard? Should we replicate PADAUK's code (eventually improving it) or do something else? Maybe have different init code options i.e. if you don't need precise clock speeds you can free up space by not having the calibration code, or you can chose to have it, you can have the ROM checksum or not, etc...

The init code is tied to the WRITER which I think we should stay compatible with (see comment above).
Usually this kind of things (init code) is implemented in include (.INC) files which the developer gets automatically in his project when he starts a new project (e.g. from a empty project template).
Then it up to the developer to modify / delete stuff from init code or use different/optimized implementations.


>- least important thing in this message but cool: a library of pre-made routines for stuff like SPI, UART, etc... could be made and optimized by the community. Like a collection of include files "spi.inc" "uart.inc" you can just bring in and use would be pretty cool

Personally I prefer simple sample projects with code snippets I can just cut and paste to my project. I don't like big libraries (like Arduino or STM32). Especially when every byte counts.


>The STM32 emulator you're working on is also vital in the toolchain I think, so keep that up. I started to play around with some methods of efficiently emulating the code on ARM Thumb by checking what assembly GCC generates for various approaches, and it seems like writing the time critical parts in assembly may be the easiest route... GCC insists on keeping the PC/ACC/ecc in RAM but having 12 general purpose registers I think the best thing is to assign the ACC, PC, SP, etc... to a couple of regs and avoid all the LDRs that just slow things down. Of course I may be wrong and there may be a way to write the C code in such a way that GCC does this by itself, but I still didn't find a way. I thought we could map every PADAUK's cycle to 8 cortex cycles with a CPU clock of 64MHz which sounds a reasonable choice given there's the ultracheap STM32F103C8T6 everywhere on eBay, Aliexpress, etc... that fits that frequency, staying in an 8 cycle frame might be viable if most of the stuff is in registers since most instructions take 1 cycle only. Did you make any progress regarding emulation on STM32?

After implementing the FLAG solver for AC and OV i recognized emulation will be quite complex.
Also keep in mind that you need to emulate the CLOCK, IO, PWM, INTERRUPTS, TIMER, WATCHDOG, ...
So I don't think a near real time emulation on STM32 will be possible.

But why not using FPGA? Simple ones are also very cheap. And one guy here in forum already said he would be able to create a FPGA version.


>Let me know what you think about my points and how we should proceed. If we can coordinate at least a bit the work that should be done (and how it should be done) I can start working on some tools.

Creating the assembler would be nice.
I really would love to have an assembler as soon as possible so I can automate tests for the simulator :-)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 23, 2018, 08:04:05 pm
Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.

Here comes the money shot:

Picture shows the ICE main IC (PLCC 44) from bottom.

Based on the top shape / edge / dot / corner  and the "SCD" marking on the bottom it most probably is a Xilinix.

Shape matches exact this drawing: https://japan.xilinx.com/support/documentation/package_specs/pc44.pdf  Most other PLCC44 FPGA/CLPD have marks on top / 2 edges / no dot in middle / ...



Happy hunting!

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 23, 2018, 08:32:03 pm
Reverse engineering the writer firmware might be a good idea, but to be sure maybe would be good to record a programming sequence as well.

I did some tests. I have only some free PMC884 samples at the moment which Padauk sent me. I also bought some PMS150C chips from lcsc.com, as recommended by Padauk, but needs some time until I get them.

First I programmed a blinky program, with all 8 FFPAs and different output frequencies. This is the main file (full project is attached) :

Code: [Select]
// define pin names
Out0 BIT PB.0;
Out1 BIT PB.1;
Out2 BIT PB.2;
Out3 BIT PB.3;
Out4 BIT PB.4;
Out5 BIT PB.5;
Out6 BIT PB.6;
Out7 BIT PB.7;

// FPPA0 is started first
void FPPA0 (void)
{
.ADJUST_IC SYSCLK=IHRC/2, IHRC=16MHz, VDD=5V, Bandgap=On;

// set pins to output
$ Out0 High, Out;
$ Out1 High, Out;
$ Out2 High, Out;
$ Out3 High, Out;
$ Out4 High, Out;
$ Out5 High, Out;
$ Out6 High, Out;
$ Out7 High, Out;

// see datasheet "pmode": FPPA duty cycle, 1/8 for all 8 FPPAs
pmode 31;

// enable all FPPAs
fppen = 0xFF;

// generate test output
while (1) {
Out0 = 0;
.delay 1;
Out0 = 1;
.delay 1;
}
}

void FPPA1 (void)
{
// generate test output
while (1) {
Out1 = 0;
.delay 10;
Out1 = 1;
.delay 10;
}
}

void FPPA2 (void)
{
// generate test output
while (1) {
Out2 = 0;
.delay 100;
Out2 = 1;
.delay 100;
}
}

void FPPA3 (void)
{
// generate test output
while (1) {
Out3 = 0;
.delay 1000;
Out3 = 1;
.delay 1000;
}
}

void FPPA4 (void)
{
// generate test output
while (1) {
Out4 = 0;
.delay 10000;
Out4 = 1;
.delay 10000;
}
}

void FPPA5 (void)
{
// generate test output
while (1) {
Out5 = 0;
.delay 100000;
Out5 = 1;
.delay 100000;
}
}

void FPPA6 (void)
{
// generate test output
while (1) {
Out6 = 0;
.delay 1000000;
Out6 = 1;
.delay 1000000;
}
}

void FPPA7 (void)
{
// generate test output
while (1) {
Out7 = 0;
.delay 10000000;
Out7 = 1;
.delay 10000000;
}
}

/*
void Interrupt (void)
{
pushaf;

if (Intrq.T16)
{ // T16 Trig
// User can add code
Intrq.T16 = 0;
//...
}

popaf;
}

*/

I measured the following frequencies (AVDD needs to be connected as well, otherwise looks like the internal oscillator doesn't run) :

Code: [Select]
PB0: 203 kHz
PB1: 44 kHz
PB2: 5 kHz
PB3: 508 Hz
PB4: 50.8 Hz
PB5: 5.08 Hz
PB6: 0.5 Hz
PB7: 0.05 Hz

Nice about the PMC884 is that you can select the duty cycle scheme, e.g. if you want to run FFPA0 more than the other FFPAs. So this was just a first test to see if everything works.

Then I tried to measure the programming signals (as David already noted in his video, you can program the OTP chip as often as you want, if it is the same bitstream). But connecting GND of the scope to the GND pin of the microcontroller was not a good idea, because the programmer tests all pins for shorts and then doesn't start the programming sequence. But here is a nice GND point near the jumpers at the back:

(https://i.imgur.com/dA7DO93.jpg)

Then I measured some pins. In David's video it was difficult or impossible to see the timescale. Here is an example for pin 3, this time with proper time scale, for the whole programming cycle:

(https://i.imgur.com/XQ2UNWY.png)

This is a data pin. Pin 19 is a clock pin. When I zoom in, it looks like this:

(https://i.imgur.com/J5Li93k.png)

Looks like about 1 us is the shortest signal length. Might be good to sample it with 10 MHz for higher resolution.

I don't know how many signals I need to scan in parallel, 2 might be enough with multiple passes, but maybe 4 would be better and easier to analyze later. If I use an 8 bit ADC, this would mean a data rate of 320 Mbits/s. Might be possible with high speed USB to transfer it in realtime on a PC. As you can see in the first scope image, the whole programming cycle needs about 800 ms (the spikes before and after are the detection of the programmer if there is a chip, which does it all the time). So a full sample with 4 channels would need only 32 MB. This could be even done with a BeagleBone and its PRUs, a simple external board with 4 ADCs and input stages for dividing the input voltage, and then recording it to memory.

But I don't have much time at the moment to build the board and program the Beagle Bone. Is there already such a thing I can buy, which records 4 channels with 8 bit at 10 MHz for 1 second?

PS: Anyone who wants to swap some PMS150C (or other Padauk) chips for PMC884? I have 100 x PMC884. Here (http://www.frank-buss.de/tmp/pmc884.pdf) is the datasheet.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 09:00:43 pm
Does the FPGA have markings on the bottom? It doesnt look dremeled on the top to me.

Here comes the money shot:

Picture shows the ICE main IC (PLCC 44) from bottom.

Based on the top shape / edge / dot / corner  and the "SCD" marking on the bottom it most probably is a Xilinix.

Shape matches exact this drawing: https://japan.xilinx.com/support/documentation/package_specs/pc44.pdf  Most other PLCC44 FPGA/CLPD have marks on top / 2 edges / no dot in middle / ...



Happy hunting!

JS

Thank you very much!

judging from lcsc pictures xilinx chips dont have bottom markings.
Also I think that padauk might have put their own markings on the bottom because it would match their package marking scheme

However I have the strong feeling this is neither a fpga nor a cpld but an 8051, because the beginning of the deobfuscated pdk files looks like this, which kind of looks like a jump table:

X0000:   add   a,r2
X0001:   xrl   rb0r2,a
   anl   a,r6
   xrl   a,r4
   jnz   X005e
   jnc   X005b
   jnc   X006a
   jnc   X0061
X000d:   jnc   X0062
   jnc   X0020
   acall   X0357
   jnc   X0064
   jnc   X0076
X0017:   jnc   X006d
   jnc   X005e
   jnc   X0060
   jnc   X0038
   acall   X0357
   jnc   X0075
   jnc   X0084
   jnc   X007b
   jnc   X0074
   jnc   X0070
   jnc   X005e
X002d:   jnc   X0057
   acall   X0357
   jnc   X0085

the markings in the circles in the corners look similar to those of stc 8051 chips on lcsc (up to 80 Mhz apperantly). Maybe they do software emulation on an 8051?  :-//

Is that feasible? Are the files in USB_Driver/USB/ICE* really 8051ish code?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on November 23, 2018, 09:17:05 pm
Is that feasible? Are the files in USB_Driver/USB/ICE* really 8051ish code?

The 8051 code might be for the Cypress USB microcontroller, which can load firmware over USB for itself as well.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 23, 2018, 09:24:52 pm
There are *.hid files for that which fill the complete 8 to 16kb for the fx2

But its really hard to say, the first part of the *pdk (unobfuscated) could very well also be lets say I/O mappings of an FPGA.

However its very hard to find any in an plcc44, cpld dont really fit the profile because they dont have sufficient memory to emulate ram/rom of the micro, and that basically leaves other microcontrollers.

Weird.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: westfw on November 23, 2018, 09:49:58 pm
I'm a bit surprised that I don't see any voltage switching circuits between the PLCC and the connector that leads to the chip?   That would sort-of imply that the chip has some analog capability rather than being a digital FPGA?
(oh wait - is this "ICE Only" box with no programmer?  If so, never mind...)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 24, 2018, 09:09:41 am
I'm reporting a conversation between me and js_12345678_55AA regarding planning of what to do next (and how) if anyone wants to share its thoughts. Not sure why I didn't directly post here in the forum thread, sorry for that  :-//

The things of most interest are probably the assembler and the syntax

Quote
Hi,

>Hi, do you have any plans to upload your disassembler (and eventually assembler if you have one) to the GitHub organization?

Sure I will do (I just want to structure it a bit more, will take 1-2 days)


>I also have tools in a preliminary state working with the 13-bit and 14-bit ISAs, which unfortunately is duplicate work but I wanted to disasm some listings so I proceeded anyway in implementing them, but that was not a lot of work so it's not a problem for me to trash everything if we want to keep your infrastructure.

All of the code I did is also just for experimentation. Most likely it will be replaced by better implementations later. So no need to keep / stick to something from me right now.


>Also I think we should define a bit how we want to proceed with the assembler.

I did not start with an assembler implementation. Maybe this is something you/somebody else want to try?
I'm already busy reversing stuff and find out how things are connected.
Today my WRITER and SIMULATOR arrived. So now I can start to work with real hardware :-)


>Some stuff to be discussed may be:
>- syntax quirks (how to represent various kind of values/addresses), asm directives, macros, defines, includes, etc...

I did not really investigated on this. I just used a syntax which I thought was good enough for first tests.
Mainly I used the syntax PADAUK used in their manuals. Just to distinguish between RAM / ROM / IO we would need to invent something. Note: The "." syntax is mainly used to represent a special bit (8051 assembly). "[ ]" are used for normal memory access. "WORD PTR" is usually used for 16 bit address references, ... I think we should adapt already known schemes so it easier for others to understand

Creating a document defining the syntax of the assembler would be a good starting point.

I think during implementation of assembler some changes will be required. Since the disassembler is fairly easy to adapt I consider it to follow any syntax changes the assembler creator might need to do.


>- whether to deviate from PADAUK's ASM syntax and implement something of our own, or whether to implement their same syntax for compatibility; or even both at the same time (i.e. a flag to choose the syntax)

One syntax please :-). As close as possible to PADAUK syntax with just some extensions for direct memory/io access.


>- what binary format we want to use across the open source toolchain, i.e. just the raw ROM content on a .bin file, or keeping their PDK format for compatibility with their OTP Writer, or have our own format, or a mix of these three things, or whatever :)

I think we should use the PDK format. The creation for a "liberated" WRITER seems to be the most difficult part which most likely will take the longest time.


>- if it makes sense to keep the ISA description open enough so that it can be imported by someone that wants to implement for instance an SDCC backend or a radare2 plugin to disasm, etc... or just keep it simple and hard coded in the tools

The ISA is so small and simple, everyone can adapt and implement it for a disasm within a few hours. So I think there is no need to be generic here.


>Also, regarding an hypothetical PC simulator (not real time, maybe cycle accurate, or even not) for debugging only:

Why "hypothetical PC simulator"? I finished this task already  8)


>- how that would be presented to the user, i.e.
>- a GUI? With what features? I/O interaction?
>- some kind of simulation you launch and outputs a waveform file in some standard format for inspection later (and that can also accept an input waveform file or some kind of description of what to do with the inputs - i.e. after 0.1s set PA.3 high etc...)
>- a command line tool like GDB where you can single step, inspect memory and regs, run, pause, etc...
>- a combination of some of the things above
>- ...

I was having a look at a 8051 emulator which uses ncurses ( https://github.com/jarikomppa/emu8051 ). This simulator I plan to repurpose for the front end.


>- we'll need our own init code if we want to create a full toolchain you can use from start to finish without touching PADAUK's tools, what should be done in that regard? Should we replicate PADAUK's code (eventually improving it) or do something else? Maybe have different init code options i.e. if you don't need precise clock speeds you can free up space by not having the calibration code, or you can chose to have it, you can have the ROM checksum or not, etc...

The init code is tied to the WRITER which I think we should stay compatible with (see comment above).
Usually this kind of things (init code) is implemented in include (.INC) files which the developer gets automatically in his project when he starts a new project (e.g. from a empty project template).
Then it up to the developer to modify / delete stuff from init code or use different/optimized implementations.

[…]

>Let me know what you think about my points and how we should proceed. If we can coordinate at least a bit the work that should be done (and how it should be done) I can start working on some tools.

Creating the assembler would be nice.
I really would love to have an assembler as soon as possible so I can automate tests for the simulator :-)


My plans so far:

Things I will help with (I know someone who might want to do part of this):

What I'd like to see but don't want to do myself:

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DDunfield on November 24, 2018, 10:42:26 am
I have a simulator implemented and somewhat working (have not tested all
instructions yet), and trying to run the startup code generated by the
assembler exposed a "weirdness" I had not noticed before:

The assembler insists that you put these startup macros in, so I used the
samples found in Demo/Dummy/Dummy.asm :

------------------- Cut here -------------
.CHIP PMS150
//{{PADAUK_CODE_OPTION
        .Code_Option    Under_20mS_VDD_Ok       No
        .Code_Option    LVR             2.5V
        .Code_Option    Security        Disable// Security Disable
//}}PADAUK_CODE_OPTION
.WRITER O_S
        .ADJUST_IC      SYSCLK=IHRC/8, IHRC=16MHz, VDD=5V;
------------------- Cut here -------------

Here is a disassembly of what it generates:

0000: 1700   MOV     A,0x00
0001: 0085   MOV     IO.0x05,A
0002: 0FE4   SET1    IO.0x04.7   // B7 documented as "reserved"
0003: 1700   MOV     A,0x00
0004: 0082   MOV     IO.0x02,A
0005: 1700   MOV     A,0x00
0006: 008B   MOV     IO.0x0B,A
0007: 173C   MOV     A,0x3C
0008: 0083   MOV     IO.0x03,A
0009: 1FFE   CALL    03FE       // ?? This is the problem ??
000A: 12FF   CEQSN   A,0xFF
000B: 181C   GOTO    001C
000C: 0FD1   SET1    IO.0x11.6
000D: 0981   CLEAR   MEM.0x01
000E: 1709   MOV     A,0x09
000F: 05C0   MOV     MEM.0x00,A
0010: 0D90   T1SN    IO.0x10.4
0011: 1810   GOTO    0010
0012: 0FD0   SET1    IO.0x10.6
0013: 0013   DZSN    A
0014: 1813   GOTO    0013
0015: 08C0   DZSN    MEM.0x00
0016: 1813   GOTO    0013
0017: 0ED0   SET0    IO.0x10.6
0018: 0901   INC     MEM.0x01
0019: 07C1   MOV     A,MEM.0x01
001A: 008B   MOV     IO.0x0B,A
001B: 180E   GOTO    000E
 // .. user code goes here
03F8: 0000   NOP     
03F9: 0000   NOP     
03FA: 0000   NOP     
03FB: 0000   NOP     
03FC: 0000   NOP     
03FD: 0000   NOP     
03FE: 1FFF   CALL    03FF
03FF: 1F9D   CALL    039D

As you can see, it generates a CALL to address 0x3FE which contains all
ones which is the default value for unused locations, and happens to
translate to "CALL 03FF".

Prior to doing this, they set Bit7 of IO.4 which is the interrupt enable
register, and Bit7 is documented as "reserved".

Following the CALL 03FE they test the accumulator value for 0xFF, and
going in to the call, it is clearly 0x3C - so they expect that this CALL
can modify the accumulator.

I'm wondering if setting IO.4.7 is mapping some special code, perhaps
"RET immediate" into the reserved area in order to retrieve some chip
dependant value, but I have no way to test this. It is also possible
that the progammer automatically programs some calibration value into
this location, however that leads to two questions:

1) What does the ICE do in this case?
2) The obtained value is only used to either 1) continue the startup
   code, or 2) jump directly to the user code bypassing the remainder
   of the startup code, why would the writer be making this decision
   For that matter why would anything not under user control be
   doing this?, it does not appear to be a calibration value as it is
   lost 4 instructions later having not been used.

Could someone with the ICE look into this and see what is happening?

Thanks,
Dave
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 24, 2018, 11:53:05 am
Hello DDunfield,

I posted a complete commented disassembly of the init code some posts back in this thread.

If you look in the .INC file of a regular project you can see more IO definitions (e.g. IO 0x0b is called "IHRCR"  which is the InternalHighspeedRC-Register").

IO 0x0B (IHRCR) will hold a "tuning" value to tune the internal high speed oscillator.


The complete init code is used to set a specific value and go up and down commanded by WRITER so it can measure and tuning the oscillator.

At first write WRITER places a "RET 0xFF" at last position of ROM-1 (0x3FE in your case).

So when WRITER starts the IC init code is executed. Then it uses bit bang protocol on PA to get data in (+/-1 of current IHRCR value) and out (checksum of code) and can measure the timing of the process.
When WRITER is done it overwrites the "RET 0xFF" with "RET 0xXY" so all later starts of the IC will not execute the init code at all. Just the defined IHRC value is written to IHRCR.

The overwriting of OTP is possible only when you change '1' bits to '0' so you can change value 0xFF to anything (but not the other way around, 0x00 can not be changed to anything anymore).
The OTP writing just can change '1' bits to '0' permanently.

Have fun,

JS.


Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 25, 2018, 01:56:32 pm
Here is some C++ code that will decode and encode the MCU firmware contained within a PDK file. This operates in-place in memory. Derived from code posted by js_12345678_55AA.

The encoder/decoder...
Code: [Select]
void xcode_pdk_data(TPDKinfo &info, bool encode)
{
    if (info.length & 31) return; // Must be a multiple of 32 words

    uint16_t const x0 = 0x55AA;
    CKey key(info.key);
    uint16_t x1 = key[3] ^ key[14];
    uint16_t x2 = key[7] ^ key[15];
    if ((info.version >= 0x15) && (info.version <= 0x17))
        x1 ^= 0x1234, x2 ^= 0x5678;
    uint16_t t1 = 0, t2 = 0;
    unsigned ki = 0, n = 0;
    uint16_t *d = info.data;

    while (n < info.length) {
        for (unsigned j = 0; j < 4; ++j) {
            if (encode) {
                t1 = *d++ = (*d - key[ki += x1])     ;    key[ n] ^= t1;
                t2 = *d++ = (*d ^ key[ki += t1]) - x2;    key[x2] ^= x1;
                x1 = *d++ = (*d - key[ki ^= t2])     ;    key[x2] ^= x0;
                x2 = *d++ = (*d ^ key[ki = kx(ki, x1)]) + t1;
                t1 = *d++ = (*d ^ key[ki += x2])     ;    key[x1] += x2;
                t2 = *d++ = (*d ^ key[ki ^= t1]) ^ x2;    key[t2] ^= t1;
                x1 = *d++ = (*d - key[ki ^= t2])     ;    key[t1] += t2;
                x2 = *d++ = (*d ^ key[ki += x1]) - t1;
            } else {
                *d++ = ((t1 = *d)     ) + key[ki += x1];   key[ n] ^= t1;
                *d++ = ((t2 = *d) + x2) ^ key[ki += t1];   key[x2] ^= x1;
                *d++ = ((x1 = *d)     ) + key[ki ^= t2];   key[x2] ^= x0;
                *d++ = ((x2 = *d) - t1) ^ key[ki = kx(ki, x1)];
                *d++ = ((t1 = *d)     ) ^ key[ki += x2];   key[x1] += x2;
                *d++ = ((t2 = *d) ^ x2) ^ key[ki ^= t1];   key[t2] ^= t1;
                *d++ = ((x1 = *d)     ) + key[ki ^= t2];   key[t1] += t2;
                *d++ = ((x2 = *d) + t1) ^ key[ki += x1];
            }
            key[1] ^= key[15]; key[2] ^= t1;
            key[3] ^= key[14]; key[4] += t2;
            key[5] ^= key[13]; key[6] += x2;
            key[8] -= x1;
            ki += j;
        }
        n += 32;
    }
}

The other stuff...
Code: [Select]
struct TPDKinfo
{
    unsigned version;
    unsigned length;
    uint16_t *key;
    uint16_t *data;
};

class CKey
{
private:
    uint16_t k[16];
public:
    CKey(uint16_t *_k) { memcpy(k, _k, sizeof(k)); }
    inline uint16_t & operator [] (unsigned const i) { return k[i & 15]; }
};

static inline unsigned kx(unsigned const k, unsigned const i) { return ((k & 0xFFFF) + (i & 0xFFFF)) >> 1; }


/* xcode_pdk_data() goes here */


int get_pdk_info(uint8_t *bd, unsigned len, TPDKinfo &info)
{
    // Note: this will only work on little endian CPUs due to the use of
    //          uint16_t and uint32_t reinterpret casts

    memset(&info, 0, sizeof(info));

    if (len < 256) return -1; // Header too short

    uint16_t *wd = reinterpret_cast<uint16_t *>(bd); // Word (16 bit) data pointer
    uint32_t *ld = reinterpret_cast<uint32_t *>(bd); // Long (32 bit) data pointer

    uint32_t const version = ld[4 >> 1];
    info.version = version;

    uint32_t const datalen = ld[16 >> 1];
    if (datalen & 31) return -2; // Data size is not a multiple of 32
    info.length = datalen;

    uint32_t const extrahdr = wd[0x13] + wd[0x14] + wd[0x16] + wd[0x68] + (version > 0x1C ? wd[0x24] >> 8 : 0);
    if (extrahdr & 1) return -3; // Data is not word aligned

    uint32_t const hdrlen = 256 + extrahdr;
    if (len < hdrlen + (datalen << 1)) return -4; // Not enough data

    info.key = wd + 0x70;
    info.data = reinterpret_cast<uint16_t *>(bd + hdrlen);

    return 0;
}

void decode_fw(uint16_t *d, unsigned len)
{
    uint16_t const o[8] = { 0xAFCD, 0x0055, 0xAA23, 0x0055, 0x3759, 0x0055, 0xAA23, 0x0055 };
    unsigned j = len << 3;
    unsigned i = 0;
    do *d++ ^= o[i & 7] ^ i++ ^ (j -= 8); while (j);
}

int main()
{
    // Read a PDK file into memory
    FILE *f;
    errno_t e = fopen_s(&f, "test.pdk", "rb");
    if (e) return -1;
    uint8_t x[9000];
    unsigned const l = fread(x, 1, sizeof(x), f);
    fclose(f);
    if (!l) return -2;

    // Get info from the header
    TPDKinfo info;
    if (get_pdk_info(x, l, info)) return -3;
    printf("PDK version: %i\nPDK data size: %i words\n", info.version, info.length);

    // Decode it
    xcode_pdk_data(info);

    // Write the decoded file
    e = fopen_s(&f, "test_decode.bin", "wb");
    if (e) return -4;
    fwrite(x, 1, l, f);
    fclose(f);

    // Encode it
    xcode_pdk_data(info, true);

    // Write the encoded file
    e = fopen_s(&f, "test_encode.bin", "wb");
    if (e) return -4;
    fwrite(x, 1, l, f);
    fclose(f);

    return 0;
}
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 25, 2018, 04:42:10 pm
16 bit instruction set encoding used by PMS234

The encoding allows for addressing of up to 64 byte IO, 512 byte RAM and 8192 word program.

EDIT: Added a few instructions that I missed (skipped a page in the manual)

Code: [Select]
0000_0000_0000_0000  nop
0000_0000_0001_0000  addc     a
0000_0000_0001_0001  subc     a
0000_0000_0001_0010  izsn     a
0000_0000_0001_0011  dzsn     a
0000_0000_0001_0111  pcadd    a
0000_0000_0001_1000  not      a
0000_0000_0001_1001  neg      a
0000_0000_0001_1010  sr       a
0000_0000_0001_1011  sl       a
0000_0000_0001_1100  src      a
0000_0000_0001_1101  slc      a
0000_0000_0001_1110  swap     a
0000_0000_0001_1111  delay    a
0000_0000_0011_0000  wdreset
0000_0000_0011_0010  pushaf
0000_0000_0011_0011  popaf
0000_0000_0011_0101  reset
0000_0000_0011_0110  stopsys
0000_0000_0011_0111  stopexe
0000_0000_0011_1000  engint
0000_0000_0011_1001  disgint
0000_0000_0011_1010  ret
0000_0000_0011_1011  reti
0000_0000_10pp_pppp  mov      IO,a
0000_0000_11pp_pppp  mov      a,IO
0000_0001_kkkk_kkkk  cneqsn   a,I
0000_001w_wwww_www0  stt16    word
0000_001w_wwww_www1  ldt16    word
0000_100w_wwww_www0  idxm     index,a
0000_100w_wwww_www1  idxm     a,index
0000_101w_wwww_www0  ldtabl   word
0000_101w_wwww_www1  ldtabh   word
0000_1110_kkkk_kkkk  delay    I
0000_1111_kkkk_kkkk  ret      I
0001_0000_00pp_pppp  xor      IO,a
0001_0000_01pp_pppp  xor      a,IO
0001_011m_mmmm_mmmm  cneqsn   a,M
0001_1000_kkkk_kkkk  add      a,I
0001_1001_kkkk_kkkk  sub      a,I
0001_1010_kkkk_kkkk  ceqsn    a,I
0001_1011_kkkk_kkkk  comp     a,I
0001_1100_kkkk_kkkk  and      a,I
0001_1101_kkkk_kkkk  or       a,I
0001_1110_kkkk_kkkk  xor      a,I
0001_1111_kkkk_kkkk  mov      a,I
0010_000b_bbpp_pppp  t0sn     IO.n
0010_001b_bbpp_pppp  t1sn     IO.n
0010_010b_bbpp_pppp  set0     IO.n
0010_011b_bbpp_pppp  set1     IO.n
0010_100b_bbpp_pppp  tog      IO.n
0010_101b_bbpp_pppp  wait0    IO.n
0010_110b_bbpp_pppp  wait1    IO.n
0010_111b_bbpp_pppp  swapc    IO.n
0011_000m_mmmm_mmmm  nmov     M,a
0011_001m_mmmm_mmmm  nmov     a,M
0011_010m_mmmm_mmmm  nadd     M,a
0011_011m_mmmm_mmmm  nadd     a,M
0011_100m_mmmm_mmmm  ceqsn    M,a
0011_101m_mmmm_mmmm  ceqsn    a,M
0011_110m_mmmm_mmmm  comp     M,a
0011_111m_mmmm_mmmm  comp     a,M
0100_000m_mmmm_mmmm  add      M,a
0100_001m_mmmm_mmmm  add      a,M
0100_011m_mmmm_mmmm  sub      a,M
0100_100m_mmmm_mmmm  addc     M,a
0100_101m_mmmm_mmmm  addc     a,M
0100_010m_mmmm_mmmm  sub      M,a
0100_111m_mmmm_mmmm  subc     a,M
0100_110m_mmmm_mmmm  subc     M,a
0101_000m_mmmm_mmmm  and      M,a
0101_001m_mmmm_mmmm  and      a,M
0101_010m_mmmm_mmmm  or       M,a
0101_011m_mmmm_mmmm  or       a,M
0101_100m_mmmm_mmmm  xor      M,a
0101_101m_mmmm_mmmm  xor      a,M
0101_110m_mmmm_mmmm  mov      M,a
0101_111m_mmmm_mmmm  mov      a,M
0110_000m_mmmm_mmmm  addc     M
0110_001m_mmmm_mmmm  subc     M
0110_010m_mmmm_mmmm  izsn     M
0110_011m_mmmm_mmmm  dzsn     M
0110_100m_mmmm_mmmm  inc      M
0110_101m_mmmm_mmmm  dec      M
0110_110m_mmmm_mmmm  clear    M
0110_111m_mmmm_mmmm  xch      M
0111_000m_mmmm_mmmm  not      M
0111_001m_mmmm_mmmm  neg      M
0111_010m_mmmm_mmmm  sr       M
0111_011m_mmmm_mmmm  sl       M
0111_100m_mmmm_mmmm  src      M
0111_101m_mmmm_mmmm  slc      M
0111_110m_mmmm_mmmm  swap     M
0111_111m_mmmm_mmmm  delay    M
1000_bbbm_mmmm_mmmm  t0sn     M.n
1001_bbbm_mmmm_mmmm  t1sn     M.n
1010_bbbm_mmmm_mmmm  set0     M.n
1011_bbbm_mmmm_mmmm  set1     M.n
110a_aaaa_aaaa_aaaa  goto     label
111a_aaaa_aaaa_aaaa  call     label
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 25, 2018, 05:02:00 pm
16 bit instruction set encoding used by PMS234

...

Code: [Select]
0000_0000_0001_1111  delay    a
...

Maybe delay instruction is also available in 14 bit ? There is an empty space in opcode list there...

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 25, 2018, 06:05:56 pm
PMS234 startup code

Code: [Select]
000  C002  goto    0x002
001  C049  goto    0x049
002  1F00  mov     a,0x00
003  0082  mov     SP,a
004  1F00  mov     a,0x00
005  008B  mov     IHRCR,a
006  EFFD  call    0x3FD
007  00B8  mov     A_IHRC,a
008  1F3C  mov     a,0x3C
009  0083  mov     CLKCMD,a
00A  1F0F  mov     a,0x0F
00B  5C01  mov     M001,a
00C  1FFE  mov     a,0xFE
00D  5C00  mov     M000,a
00E  0A00  ldtabl  M000
00F  1AFF  ceqsn   a,0xFF
010  C040  goto    0x040
011  2791  set1    PAC.6
012  6C01  clear   M001
013  1F20  mov     a,0x20
014  5C00  mov     M000,a
015  2D10  wait1   PA.4
016  2790  set1    PA.6
017  001F  delay   a
018  6600  dzsn    M000
019  C017  goto    0x017
01A  2590  set0    PA.6
01B  2210  t1sn    PA.0
01C  C03C  goto    0x03C
01D  1FA4  mov     a,0xA4
01E  00A0  mov     ADCC,a
01F  1F84  mov     a,0x84
020  00A1  mov     ADCM,a
021  1F80  mov     a,0x80
022  5C00  mov     M000,a
023  5E00  mov     a,M000
024  00B9  mov     BGTR,a
025  27A0  set1    ADCC.6
026  2DA0  wait1   ADCC.6
027  27A0  set1    ADCC.6
028  2DA0  wait1   ADCC.6
029  00E2  mov     a,ADCRH
02A  5C01  mov     M001,a
02B  00E3  mov     a,ADCRL
02C  2CD0  wait1   PA.3
02D  001B  sl      a
02E  7A01  slc     M001
02F  2F90  swapc   PA.6
030  2AD0  wait0   PA.3
031  2010  t0sn    PA.0
032  C02C  goto    0x02C
033  2150  t0sn    PA.5
034  C025  goto    0x025
035  1FBC  mov     a,0xBC
036  00A0  mov     ADCC,a
037  21D0  t0sn    PA.7
038  6800  inc     M000
039  23D0  t1sn    PA.7
03A  6A00  dec     M000
03B  C023  goto    0x023
03C  6801  inc     M001
03D  5E01  mov     a,M001
03E  008B  mov     IHRCR,a
03F  C013  goto    0x013
040  008B  mov     IHRCR,a
041  0A01  ldtabh  M000
042  00B9  mov     BGTR,a

; FPPA0 User Code
043  1F00  mov     a,0x00
044  0082  mov     SP,a
045  0030  wdreset
046  0E64  delay   0x64
047  2810  tog     PA.0
048  C045  goto    0x045

; FPPA1 User Code
049  1F04  mov     a,0x04
04A  0082  mov     SP,a
04B  0EC8  delay   0xC8
04C  2850  tog     PA.1
04D  C04B  goto    0x04B
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 25, 2018, 07:54:15 pm
I think it might be better to refer to the opcodes by their symbol than their bitsize or the device
Which apparently can be different for IDE and ICE and can also be redefined in the same file (PMS150.INC for example)
The symbol files are probably also the reason why the ICE cannot assemble certain instructions and outputs NOPs instead (but probably also enables TRAP)
Unfortunately they are somewhat binary.

./PMS132.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK22C13.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PMC131.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./XN1210.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC234.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PES502C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS134.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./PDK22C58A.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PMS132B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./P201CS16A.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS271.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS150B.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PFS154.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK82S_EV.INC
.Assembly   INSTRUMENT   SYM_82A
./PDK82C12.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./P234C.INC
.Assembly   INSTRUMENT   SYM_83A
./P232CS20.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS234.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PFC154.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC156.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMC882.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PDK82C13.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./XN1320B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS232.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS154C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./P232C.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS131.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMS155C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC251.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMC150.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMS154.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS156.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PES502D.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC166.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./ip5dB.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PES503.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS155.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK3S_EV.INC
.Assembly   INSTRUMENT   SYM_83A
./P234CS24.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS130.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PDK22C58.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./PMS171.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS171B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./MCU371.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./PMR210.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_86A
./PMS165C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS153.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PES501.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK_EV5.INC
.Assembly   INSTRUMENT   SYM_86A
./XN1210B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC884.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMC232.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./PMS152.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS150C.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_86A
./PMS164.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PDK22C13A.INC
.Assembly   INSTRUMENT   SYM_82A
.Assembly   ICE_INSTR   SYM_83A
./ip5dC.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_86A
./PMS132K.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./XN1320D.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS133.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./XN1210D.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMS154B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC153.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PFS173.INC
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_86A
./XN1210C.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PMC271.INC
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_83A
./P201CS14A.INC
.Assembly   INSTRUMENT   SYM_83A
./PMS150.INC
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
./PMS155B.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
./PES502.INC
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ICE_INSTR   SYM_86A
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 25, 2018, 08:48:12 pm
A comparison of the 13, 14, and 16 bit instruction sets.

Code: [Select]
add      a,I        1_0000_kkkk_kkkk    10_1000_kkkk_kkkk    0001_1000_kkkk_kkkk
add      a,M        0_0110_00mm_mmmm    00_1100_0mmm_mmmm    0100_001m_mmmm_mmmm
add      M,a        0_0100_00mm_mmmm    00_1000_0mmm_mmmm    0100_000m_mmmm_mmmm
addc     a          0_0000_0001_0000    00_0000_0110_0000    0000_0000_0001_0000
addc     a,M        0_0110_10mm_mmmm    00_1101_0mmm_mmmm    0100_101m_mmmm_mmmm
addc     M                              01_0000_0mmm_mmmm    0110_000m_mmmm_mmmm
addc     M,a        0_0100_10mm_mmmm    00_1001_0mmm_mmmm    0100_100m_mmmm_mmmm
and      a,I        1_0100_kkkk_kkkk    10_1100_kkkk_kkkk    0001_1100_kkkk_kkkk
and      a,M        0_0111_00mm_mmmm    00_1110_0mmm_mmmm    0101_001m_mmmm_mmmm
and      M,a        0_0101_00mm_mmmm    00_1010_0mmm_mmmm    0101_000m_mmmm_mmmm
call     label      1_11aa_aaaa_aaaa    11_1aaa_aaaa_aaaa    111a_aaaa_aaaa_aaaa
ceqsn    a,I        1_0010_kkkk_kkkk    10_1010_kkkk_kkkk    0001_1010_kkkk_kkkk
ceqsn    a,M        0_1011_10mm_mmmm    01_0111_0mmm_mmmm    0011_101m_mmmm_mmmm
ceqsn    M,a                                                 0011_100m_mmmm_mmmm
clear    M          0_1001_10mm_mmmm    01_0011_0mmm_mmmm    0110_110m_mmmm_mmmm
cneqsn   a,I                            10_1011_kkkk_kkkk    0000_0001_kkkk_kkkk
cneqsn   a,M                            01_0111_1mmm_mmmm    0001_011m_mmmm_mmmm
comp     a,I                                                 0001_1011_kkkk_kkkk
comp     a,M                            00_0110_0mmm_mmmm    0011_111m_mmmm_mmmm
comp     M,a                            00_0110_1mmm_mmmm    0011_110m_mmmm_mmmm
dec      M          0_1001_01mm_mmmm    01_0010_1mmm_mmmm    0110_101m_mmmm_mmmm
delay    a                                                   0000_0000_0001_1111
delay    I                                                   0000_1110_kkkk_kkkk
delay    M                                                   0111_111m_mmmm_mmmm
disgint             0_0000_0011_1001    00_0000_0111_1001    0000_0000_0011_1001
dzsn     a          0_0000_0001_0011    00_0000_0110_0011    0000_0000_0001_0011
dzsn     M          0_1000_11mm_mmmm    01_0001_1mmm_mmmm    0110_011m_mmmm_mmmm
engint              0_0000_0011_1000    00_0000_0111_1000    0000_0000_0011_1000
goto     label      1_10aa_aaaa_aaaa    11_0aaa_aaaa_aaaa    110a_aaaa_aaaa_aaaa
idxm     a,index    0_0000_111w_www1    00_0011_1www_www1    0000_100w_wwww_www1
idxm     index,a    0_0000_111w_www0    00_0011_1www_www0    0000_100w_wwww_www0
inc      M          0_1001_00mm_mmmm    01_0010_0mmm_mmmm    0110_100m_mmmm_mmmm
izsn     a          0_0000_0001_0010    00_0000_0110_0010    0000_0000_0001_0010
izsn     M          0_1000_10mm_mmmm    01_0001_0mmm_mmmm    0110_010m_mmmm_mmmm
ldspth                                  00_0000_0000_0111
ldsptl                                  00_0000_0000_0110
ldt16    word       0_0000_110w_www1    00_0011_0www_www1    0000_001w_wwww_www1
ldtabh   word                                                0000_101w_wwww_www1
ldtabl   word                                                0000_101w_wwww_www0
mov      a,I        1_0111_kkkk_kkkk    10_1111_kkkk_kkkk    0001_1111_kkkk_kkkk
mov      a,IO       0_0000_101p_pppp    00_0001_11pp_pppp    0000_0000_11pp_pppp
mov      a,M        0_0111_11mm_mmmm    00_1111_1mmm_mmmm    0101_111m_mmmm_mmmm
mov      IO,a       0_0000_100p_pppp    00_0001_10pp_pppp    0000_0000_10pp_pppp
mov      M,a        0_0101_11mm_mmmm    00_1011_1mmm_mmmm    0101_110m_mmmm_mmmm
mul                                     00_0000_0111_1100
nadd     a,M                            00_0111_0mmm_mmmm    0011_011m_mmmm_mmmm
nadd     M,a                            00_0111_1mmm_mmmm    0011_010m_mmmm_mmmm
neg      a          0_0000_0001_1001    00_0000_0110_1001    0000_0000_0001_1001
neg      M          0_1010_01mm_mmmm    01_0100_1mmm_mmmm    0111_001m_mmmm_mmmm
nmov     a,M                                                 0011_001m_mmmm_mmmm
nmov     M,a                                                 0011_000m_mmmm_mmmm
nop                 0_0000_0000_0000    00_0000_0000_0000    0000_0000_0000_0000
not      a          0_0000_0001_1000    00_0000_0110_1000    0000_0000_0001_1000
not      M          0_1010_00mm_mmmm    01_0100_0mmm_mmmm    0111_000m_mmmm_mmmm
or       a,I        1_0101_kkkk_kkkk    10_1101_kkkk_kkkk    0001_1101_kkkk_kkkk
or       a,M        0_0111_01mm_mmmm    00_1110_1mmm_mmmm    0101_011m_mmmm_mmmm
or       M,a        0_0101_01mm_mmmm    00_1010_1mmm_mmmm    0101_010m_mmmm_mmmm
pcadd    a          0_0000_0001_0111    00_0000_0110_0111    0000_0000_0001_0111
popaf               0_0000_0011_0011    00_0000_0111_0011    0000_0000_0011_0011
pushaf              0_0000_0011_0010    00_0000_0111_0010    0000_0000_0011_0010
reset               0_0000_0011_0101    00_0000_0111_0101    0000_0000_0011_0101
ret                 0_0000_0011_1010    00_0000_0111_1010    0000_0000_0011_1010
ret      I          0_0001_kkkk_kkkk    00_0010_kkkk_kkkk    0000_1111_kkkk_kkkk
reti                0_0000_0011_1011    00_0000_0111_1011    0000_0000_0011_1011
set0     IO.n       0_1110_bbbp_pppp    01_110b_bbpp_pppp    0010_010b_bbpp_pppp
set0     M.n        0_0011_bbb0_mmmm    10_010b_bbmm_mmmm    1010_bbbm_mmmm_mmmm
set1     IO.n       0_1111_bbbp_pppp    01_111b_bbpp_pppp    0010_011b_bbpp_pppp
set1     M.n        0_0011_bbb1_mmmm    10_011b_bbmm_mmmm    1011_bbbm_mmmm_mmmm
sl       a          0_0000_0001_1011    00_0000_0110_1011    0000_0000_0001_1011
sl       M          0_1010_11mm_mmmm    01_0101_1mmm_mmmm    0111_011m_mmmm_mmmm
slc      a          0_0000_0001_1101    00_0000_0110_1101    0000_0000_0001_1101
slc      M          0_1011_01mm_mmmm    01_0110_1mmm_mmmm    0111_101m_mmmm_mmmm
sr       a          0_0000_0001_1010    00_0000_0110_1010    0000_0000_0001_1010
sr       M          0_1010_10mm_mmmm    01_0101_0mmm_mmmm    0111_010m_mmmm_mmmm
src      a          0_0000_0001_1100    00_0000_0110_1100    0000_0000_0001_1100
src      M          0_1011_00mm_mmmm    01_0110_0mmm_mmmm    0111_100m_mmmm_mmmm
stopexe             0_0000_0011_0111    00_0000_0111_0111    0000_0000_0011_0111
stopsys             0_0000_0011_0110    00_0000_0111_0110    0000_0000_0011_0110
stt16    word       0_0000_110w_www0    00_0011_0www_www0    0000_001w_wwww_www0
sub      a,I        1_0001_kkkk_kkkk    10_1001_kkkk_kkkk    0001_1001_kkkk_kkkk
sub      a,M        0_0110_01mm_mmmm    00_1100_1mmm_mmmm    0100_011m_mmmm_mmmm
sub      M,a        0_0100_01mm_mmmm    00_1000_1mmm_mmmm    0100_010m_mmmm_mmmm
subc     a          0_0000_0001_0001    00_0000_0110_0001    0000_0000_0001_0001
subc     a,M        0_0110_11mm_mmmm    00_1101_1mmm_mmmm    0100_111m_mmmm_mmmm
subc     M                              01_0000_1mmm_mmmm    0110_001m_mmmm_mmmm
subc     M,a        0_0100_11mm_mmmm    00_1001_1mmm_mmmm    0100_110m_mmmm_mmmm
swap     a          0_0000_0001_1110    00_0000_0110_1110    0000_0000_0001_1110
swap     M                                                   0111_110m_mmmm_mmmm
swapc    IO.n                           00_010b_bbpp_pppp    0010_111b_bbpp_pppp
t0sn     IO.n       0_1100_bbbp_pppp    01_100b_bbpp_pppp    0010_000b_bbpp_pppp
t0sn     M.n        0_0010_bbb0_mmmm    10_000b_bbmm_mmmm    1000_bbbm_mmmm_mmmm
t1sn     IO.n       0_1101_bbbp_pppp    01_101b_bbpp_pppp    0010_001b_bbpp_pppp
t1sn     M.n        0_0010_bbb1_mmmm    10_001b_bbmm_mmmm    1001_bbbm_mmmm_mmmm
tog      IO.n                                                0010_100b_bbpp_pppp
wait0    IO.n                                                0010_101b_bbpp_pppp
wait1    IO.n                                                0010_110b_bbpp_pppp
wdreset             0_0000_0011_0000    00_0000_0111_0000    0000_0000_0011_0000
xch      M          0_1001_11mm_mmmm    01_0011_1mmm_mmmm    0110_111m_mmmm_mmmm
xor      a,I        1_0110_kkkk_kkkk    10_1110_kkkk_kkkk    0001_1110_kkkk_kkkk
xor      a,IO                                                0001_0000_01pp_pppp
xor      a,M        0_0111_10mm_mmmm    00_1111_0mmm_mmmm    0101_101m_mmmm_mmmm
xor      IO,a       0_0000_011p_pppp    00_0000_11pp_pppp    0001_0000_00pp_pppp
xor      M,a        0_0101_10mm_mmmm    00_1011_0mmm_mmmm    0101_100m_mmmm_mmmm

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: amyk on November 26, 2018, 02:15:08 am
No immediately discernable obvious systema to the opcode layout besides the fixed position of the address/data fields --- I'd be really curious to see a decap of these MCUs, because the randomness of the assignment means they're probably implemented directly with a PLA and no microcode nor field-specific decoding.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 26, 2018, 09:46:30 am
A comparison of the 13, 14, and 16 bit instruction sets.
[…]

You seem to be missing  few instructions in the 16-bit instruction set. In particular, I noticed pushw word, popw word, pushw pcN, popw pcN.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 26, 2018, 10:01:28 am
What chip has those instructions? I used the PMC234 as a reference and it does not have them.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: mikeselectricstuff on November 26, 2018, 10:09:12 am
No immediately discernable obvious systema to the opcode layout besides the fixed position of the address/data fields --- I'd be really curious to see a decap of these MCUs, because the randomness of the assignment means they're probably implemented directly with a PLA and no microcode nor field-specific decoding.
Ken Sherriff just did a teardown and decap of a flame lamp that uses a 16-pin unmarked MCU, which may or may not be a PADUK chip. Unfortunately no schematic to compare pinouts

https://electronupdate.blogspot.com/
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 26, 2018, 10:24:32 am
What chip has those instructions? I used the PMC234 as a reference and it does not have them.

I am not sure in general, but so far all the 8-core dveices that I read datasheets of have them, while the 2-core devices don't.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 26, 2018, 11:08:35 am
.CHIP PDK82S_EV made more opcodes acceptable to the assembler

Code: [Select]
0x0400  popw   word
0x0401  pushw  word
0x0060  popw   pcN
0x0070  pushw  pcN
0x003C  mul

Looking for ideas on how to get the opcodes for 13 and 16 bit ldsptl/ldspth
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 26, 2018, 11:21:20 am
pushw/popw pcN use 4 bits for the core number :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 26, 2018, 12:06:16 pm
.CHIP PDK82S_EV made more opcodes acceptable to the assembler

Code: [Select]
0x0400  popw   word
0x0401  pushw  word
0x0060  popw   pcN
0x0070  pushw  pcN
0x003C  mul

Looking for ideas on how to get the opcodes for 13 and 16 bit ldsptl/ldspth


There should also be instructions
IGOTO
ICALL
and
PMODE

The best idea I have is to look at the Symbol Files but if they encode the Opcodes as well as the mnemonics it seems to be in different places
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 26, 2018, 12:23:39 pm
Code: [Select]
0x0040  pmode   n
0x0600  igoto   word
0x0601  icall   word

Not many gaps remaining in the 16 bit instruction set
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 26, 2018, 12:45:52 pm
Code: [Select]
0x0040  pmode   n
0x0600  igoto   word
0x0601  icall   word

Not many gaps remaining in the 16 bit instruction set


True, although I would consider calling this PDK_SYM_82A instruction set.

Could you also point out what chips you used for the other instruction sets?

If I counted correctly there are only these instruction set families
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
.Assembly   INSTRUMENT   SYM_82A
.Assembly   INSTRUMENT   SYM_83A
.Assembly   INSTRUMENT   SYM_86A

I suspect that INSTRUMENT means same for ASM and ICE
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 26, 2018, 01:04:29 pm
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 26, 2018, 01:54:51 pm
I started to create simple demo projects for PADAUK IDE:

- simple blink in mini-C
- simple blink in ASM embedded in mini-C
- simple blink in pure ASM
- timer based blink using interrupt

https://github.com/free-pdk/simple-pdk-code-examples

If you have analyzed some special functions please try to create a simple demo project just describing / using this function.
This will come handy for regression testing emulation.

To research:
 - watchdog
 - edge triggered interrupts for PA/PB
 - timer source PA/PB pin change
 - stopsys / stopexe and wakeup interrupt
 - adc
 - multicore
 - ...

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DDunfield on November 26, 2018, 07:56:58 pm
In case anyone else wants to fool with it, I've made my *very Quick and Dirty*/preliminary simulator for the PMC150/PMS150 available on a google drive at the following link:

https://drive.google.com/open?id=1iNK7dmASzDRcld0SGHDq_lqcMhntBvrv (https://drive.google.com/open?id=1iNK7dmASzDRcld0SGHDq_lqcMhntBvrv)

Before you bother downloading it, take note:

Most of you won't like it - the main reason being that I tend to prototype software things with the tools that I am most familiar with and in this case I built it with a compiler I wrote back in the 80's, which builds DOS executables. That means you need a DOS compatible environment. For most modern 64-bit systems, DOSBOX works well, and is available for Windows/Linux/Mac/Android etc. (yeah, I can run PSM150 code on my phone!) - for Windows, I recommend the DOSBOX that I have posted under "DOS wigets" on my site (www.dunfield.com (http://www.dunfield.com)).

It is a very preliminary prototype. It is not optimized in any way.

It does not yet simulate any of the on-chip hardware (timer, interrupts etc). At this time this is for fooling with the instruction set only.

I've confirmed that it understands all the instructions listed in the PMC150/PMS150 manual, however I have not exhaustively tested them. I do not have the Paudak ICE or programmer, so I cannot easily verify the operation of the actual CPU (implementation is a combination of guesswork and "as documented" in the Paudak data sheet). There are most certainly bugs. I will update the simulator as these are found/reported. Please contact me as 'DDunfield' on the EEVBLOG forums.

Refer to the QDS150.TXT file included in the above archive for more information.

Dave
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 26, 2018, 10:20:39 pm
Hi,

I just created a repository on github containing new tools and source code for PDK FPPA controller:

https://github.com/free-pdk/fppa-pdk-tools

depdk : deobfuscate PDK file to binary format
dispdk : disassemble PDK file (the 14 bit instruction set disassembler is already working, only mapped processors are PMx154 variants)
emupdk: simulates PDK (PMx154 is implemented and mapped)

I spent quite some time with the flag solver for OV, AC, CF, ZF. But it is easy to reuse now for all other processor types.
Basic testing was done with most ALU operations so it's looking good.

-> adapting disassembler for 13/16 bit is a simple task
-> adapting emulator for 13 bit should be straight forward, 16 bit needs some understanding of new opcodes

I will focus on interrupt / peripheral emulation and GUI (ncurses).

So if anybody wants to assist, 13/16 bit needs implementation.


JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 27, 2018, 06:20:05 pm
Code: [Select]
0x0040  pmode   n
0x0600  igoto   word
0x0601  icall   word

Not many gaps remaining in the 16 bit instruction set


True, although I would consider calling this PDK_SYM_82A instruction set.

Could you also point out what chips you used for the other instruction sets?

If I counted correctly there are only these instruction set families
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
.Assembly   INSTRUMENT   SYM_82A
.Assembly   INSTRUMENT   SYM_83A
.Assembly   INSTRUMENT   SYM_86A

I suspect that INSTRUMENT means same for ASM and ICE

Chips settings I have used...

13 bit:  PMS150C
14 bit:  PFS154
16 bit:  PMS234  PMC882  PMC884  PDK82C12  PDK82C13  PDK82S_EV

I think the SYM_8xx designations refer to subsets of the full instruction set that run on specific hardware revs.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 27, 2018, 06:22:55 pm
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others

Looks like the same 14 bit instruction set to me. What differences did you notice?

Test program
Code: [Select]
.CHIP PFS154
//{{PADAUK_CODE_OPTION
.Code_Option LVR 2.5V
.Code_Option Security Enable // Security 7/8 words Enable
.Code_Option Comparator_Edge All_Edge
.Code_Option LCD2 Disable // At ICE, LCD always disable, PB0 PA0/3/4 are independent pins
.Code_Option Bootup_Time Fast
.Code_Option Drive Normal
//}}PADAUK_CODE_OPTION

goto FPPA0

WORD Stack_FPPA0 [2]

FPPA0:
.ADJUST_IC SYSCLK=IHRC/8, IHRC=16MHz, VDD=5V

SP = Stack_FPPA0;

@@:
wdreset
nop
goto @B

Disassembly
Code: [Select]
000  3001  goto    0x001
001  2F00  mov     a,0x00
002  0182  mov     SP,a
003  3FED  call    0x7ED
004  018B  mov     IHRCR,a
005  3FEE  call    0x7EE
006  019A  mov     BGTR,a
007  2F80  mov     a,0x80
008  019B  mov     MISC_LVR,a
009  2F3C  mov     a,0x3C
00A  0183  mov     CLKCMD,a
00B  3FFE  call    0x7FE
00C  2AFF  ceqsn   a,0xFF
00D  3054  goto    0x054
00E  3FED  call    0x7ED
00F  0B81  mov     M01,a
010  1F91  set1    PAC.6
011  2F09  mov     a,0x09
012  0B80  mov     M00,a
013  1AD0  t1sn    PA.3
014  3013  goto    0x013
015  1F90  set1    PA.6
016  0063  dzsn    a
017  3016  goto    0x016
018  1180  dzsn    M00
019  3016  goto    0x016
01A  1D90  set0    PA.6
01B  18D0  t0sn    PA.3
01C  301B  goto    0x01B
01D  2F01  mov     a,0x01
01E  1950  t0sn    PA.5
01F  2FFF  mov     a,0xFF
020  0C01  add     a,M01
021  018B  mov     IHRCR,a
022  0B81  mov     M01,a
023  1AD0  t1sn    PA.3
024  3023  goto    0x023
025  1B50  t1sn    PA.5
026  304F  goto    0x04F
027  2F04  mov     a,0x04
028  0188  mov     MISC,a
029  18D0  t0sn    PA.3
02A  3029  goto    0x029
02B  2F02  mov     a,0x02
02C  0182  mov     SP,a
02D  1304  clear   M04
02E  1305  clear   M05
02F  2F59  mov     a,0x59
030  0B82  mov     M02,a
031  2F00  mov     a,0x00
032  0B83  mov     M03,a
033  0006  ldsptl
034  0B04  xor     M04,a
035  0007  ldspth
036  0805  add     M05,a
037  1584  sl      M04
038  1685  slc     M05
039  1004  addc    M04
03A  1282  dec     M02
03B  1083  subc    M03
03C  1A40  t1sn    FLAG.1
03D  3033  goto    0x033
03E  1F90  set1    PA.6
03F  1AD0  t1sn    PA.3
040  303F  goto    0x03F
041  1584  sl      M04
042  1685  slc     M05
043  0590  swapc   PA.6
044  18D0  t0sn    PA.3
045  3044  goto    0x044
046  1950  t0sn    PA.5
047  303F  goto    0x03F
048  1D90  set0    PA.6
049  1AD0  t1sn    PA.3
04A  3049  goto    0x049
04B  18D0  t0sn    PA.3
04C  304B  goto    0x04B
04D  1B50  t1sn    PA.5
04E  302B  goto    0x02B
04F  18D0  t0sn    PA.3
050  304F  goto    0x04F
051  1B50  t1sn    PA.5
052  3011  goto    0x011
053  3053  goto    0x053
054  018B  mov     IHRCR,a
055  2F00  mov     a,0x00
056  0182  mov     SP,a
057  0070  wdreset
058  0000  nop
059  3057  goto    0x057
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on November 27, 2018, 06:51:18 pm
Updated instruction set encodings. Sorted by opcode. All gaps indicated.

16 bit
Code: [Select]
0x0000  0000_0000_0000_0000  nop
0x0001  0000_0000_0000_0001
0x0002  0000_0000_0000_0010
0x0003  0000_0000_0000_0011
0x0004  0000_0000_0000_0100
0x0005  0000_0000_0000_0101
0x0006  0000_0000_0000_0110
0x0007  0000_0000_0000_0111
0x0008  0000_0000_0000_1000
0x0009  0000_0000_0000_1001
0x000A  0000_0000_0000_1010
0x000B  0000_0000_0000_1011
0x000C  0000_0000_0000_1100
0x000D  0000_0000_0000_1101
0x000E  0000_0000_0000_1110
0x000F  0000_0000_0000_1111
0x0010  0000_0000_0001_0000  addc     a
0x0011  0000_0000_0001_0001  subc     a
0x0012  0000_0000_0001_0010  izsn     a
0x0013  0000_0000_0001_0011  dzsn     a
0x0014  0000_0000_0001_0100
0x0015  0000_0000_0001_0101
0x0016  0000_0000_0001_0110
0x0017  0000_0000_0001_0111  pcadd    a
0x0018  0000_0000_0001_1000  not      a
0x0019  0000_0000_0001_1001  neg      a
0x001A  0000_0000_0001_1010  sr       a
0x001B  0000_0000_0001_1011  sl       a
0x001C  0000_0000_0001_1100  src      a
0x001D  0000_0000_0001_1101  slc      a
0x001E  0000_0000_0001_1110  swap     a
0x001F  0000_0000_0001_1111  delay    a
0x0020  0000_0000_0010_----
0x0030  0000_0000_0011_0000  wdreset
0x0031  0000_0000_0011_0001
0x0032  0000_0000_0011_0010  pushaf
0x0033  0000_0000_0011_0011  popaf
0x0034  0000_0000_0011_0100
0x0035  0000_0000_0011_0101  reset
0x0036  0000_0000_0011_0110  stopsys
0x0037  0000_0000_0011_0111  stopexe
0x0038  0000_0000_0011_1000  engint
0x0039  0000_0000_0011_1001  disgint
0x003A  0000_0000_0011_1010  ret
0x003B  0000_0000_0011_1011  reti
0x003C  0000_0000_0011_1100  mul
0x003D  0000_0000_0011_1101
0x003E  0000_0000_0011_1110
0x003F  0000_0000_0011_1111
0x0040  0000_0000_010k_kkkk  pmode    n
0x0060  0000_0000_0110_tttt  popw     pcN
0x0070  0000_0000_0111_tttt  pushw    pcN
0x0080  0000_0000_10pp_pppp  mov      IO,a
0x00C0  0000_0000_11pp_pppp  mov      a,IO
0x0100  0000_0001_kkkk_kkkk  cneqsn   a,I
0x0200  0000_001w_wwww_www0  stt16    word
0x0201  0000_001w_wwww_www1  ldt16    word
0x0400  0000_010w_wwww_www0  popw     word
0x0401  0000_010w_wwww_www1  pushw    word
0x0600  0000_011w_wwww_www0  igoto    word
0x0601  0000_011w_wwww_www1  icall    word
0x0800  0000_100w_wwww_www0  idxm     index,a
0x0801  0000_100w_wwww_www1  idxm     a,index
0x0A00  0000_101w_wwww_www0  ldtabl   word
0x0A01  0000_101w_wwww_www1  ldtabh   word
0x0C00  0000_110-_----_----
0x0E00  0000_1110_kkkk_kkkk  delay    I
0x0F00  0000_1111_kkkk_kkkk  ret      I
0x1000  0001_0000_00pp_pppp  xor      IO,a
0x1040  0001_0000_01pp_pppp  xor      a,IO
0x1080  0001_0000_1---_----
0x1100 0001_0001_----_----
0x1200 0001_001-_----_----
0x1400 0001_010m_mmmm_mmmm  cneqsn   M,a
0x1600  0001_011m_mmmm_mmmm  cneqsn   a,M
0x1800  0001_1000_kkkk_kkkk  add      a,I
0x1900  0001_1001_kkkk_kkkk  sub      a,I
0x1A00  0001_1010_kkkk_kkkk  ceqsn    a,I
0x1B00  0001_1011_kkkk_kkkk  comp     a,I
0x1C00  0001_1100_kkkk_kkkk  and      a,I
0x1D00  0001_1101_kkkk_kkkk  or       a,I
0x1E00  0001_1110_kkkk_kkkk  xor      a,I
0x1F00  0001_1111_kkkk_kkkk  mov      a,I
0x2000  0010_000b_bbpp_pppp  t0sn     IO.n
0x2200  0010_001b_bbpp_pppp  t1sn     IO.n
0x2400  0010_010b_bbpp_pppp  set0     IO.n
0x2600  0010_011b_bbpp_pppp  set1     IO.n
0x2800  0010_100b_bbpp_pppp  tog      IO.n
0x2A00  0010_101b_bbpp_pppp  wait0    IO.n
0x2C00  0010_110b_bbpp_pppp  wait1    IO.n
0x2E00  0010_111b_bbpp_pppp  swapc    IO.n
0x3000  0011_000m_mmmm_mmmm  nmov     M,a
0x3200  0011_001m_mmmm_mmmm  nmov     a,M
0x3400  0011_010m_mmmm_mmmm  nadd     M,a
0x3600  0011_011m_mmmm_mmmm  nadd     a,M
0x3800  0011_100m_mmmm_mmmm  ceqsn    M,a
0x3A00  0011_101m_mmmm_mmmm  ceqsn    a,M
0x3C00  0011_110m_mmmm_mmmm  comp     M,a
0x3E00  0011_111m_mmmm_mmmm  comp     a,M
0x4000  0100_000m_mmmm_mmmm  add      M,a
0x4200  0100_001m_mmmm_mmmm  add      a,M
0x4400  0100_010m_mmmm_mmmm  sub      M,a
0x4600  0100_011m_mmmm_mmmm  sub      a,M
0x4800  0100_100m_mmmm_mmmm  addc     M,a
0x4A00  0100_101m_mmmm_mmmm  addc     a,M
0x4C00  0100_110m_mmmm_mmmm  subc     M,a
0x4E00  0100_111m_mmmm_mmmm  subc     a,M
0x5000  0101_000m_mmmm_mmmm  and      M,a
0x5200  0101_001m_mmmm_mmmm  and      a,M
0x5400  0101_010m_mmmm_mmmm  or       M,a
0x5600  0101_011m_mmmm_mmmm  or       a,M
0x5800  0101_100m_mmmm_mmmm  xor      M,a
0x5A00  0101_101m_mmmm_mmmm  xor      a,M
0x5C00  0101_110m_mmmm_mmmm  mov      M,a
0x5E00  0101_111m_mmmm_mmmm  mov      a,M
0x6000  0110_000m_mmmm_mmmm  addc     M
0x6200  0110_001m_mmmm_mmmm  subc     M
0x6400  0110_010m_mmmm_mmmm  izsn     M
0x6600  0110_011m_mmmm_mmmm  dzsn     M
0x6800  0110_100m_mmmm_mmmm  inc      M
0x6A00  0110_101m_mmmm_mmmm  dec      M
0x6C00  0110_110m_mmmm_mmmm  clear    M
0x6E00  0110_111m_mmmm_mmmm  xch      M
0x7000  0111_000m_mmmm_mmmm  not      M
0x7200  0111_001m_mmmm_mmmm  neg      M
0x7400  0111_010m_mmmm_mmmm  sr       M
0x7600  0111_011m_mmmm_mmmm  sl       M
0x7800  0111_100m_mmmm_mmmm  src      M
0x7A00  0111_101m_mmmm_mmmm  slc      M
0x7C00  0111_110m_mmmm_mmmm  swap     M
0x7E00  0111_111m_mmmm_mmmm  delay    M
0x8000  1000_bbbm_mmmm_mmmm  t0sn     M.n
0x9000  1001_bbbm_mmmm_mmmm  t1sn     M.n
0xA000  1010_bbbm_mmmm_mmmm  set0     M.n
0xB000  1011_bbbm_mmmm_mmmm  set1     M.n
0xC000  110a_aaaa_aaaa_aaaa  goto     label
0xE000  111a_aaaa_aaaa_aaaa  call     label


14 bit
Code: [Select]
0x0000  00_0000_0000_0000   nop
0x0001  00_0000_0000_0001
0x0002  00_0000_0000_0010
0x0003  00_0000_0000_0011
0x0004  00_0000_0000_0100
0x0005  00_0000_0000_0101
0x0006  00_0000_0000_0110   ldsptl         
0x0007  00_0000_0000_0111   ldspth         
0x0008  00_0000_0000_1---
0x0010  00_0000_0001_----
0x0020  00_0000_001-_----
0x0040  00_0000_010-_----
0x0060  00_0000_0110_0000   addc    a       
0x0061  00_0000_0110_0001   subc    a       
0x0062  00_0000_0110_0010   izsn    a       
0x0063  00_0000_0110_0011   dzsn    a       
0x0064  00_0000_0110_0100
0x0065  00_0000_0110_0101
0x0066  00_0000_0110_0110
0x0067  00_0000_0110_0111   pcadd   a       
0x0068  00_0000_0110_1000   not     a       
0x0069  00_0000_0110_1001   neg     a       
0x006a  00_0000_0110_1010   sr      a       
0x006b  00_0000_0110_1011   sl      a       
0x006c  00_0000_0110_1100   src     a       
0x006d  00_0000_0110_1101   slc     a       
0x006e  00_0000_0110_1110   swap    a       
0x006f  00_0000_0110_1111
0x0070  00_0000_0111_0000   wdreset         
0x0071  00_0000_0111_0001
0x0072  00_0000_0111_0010   pushaf         
0x0073  00_0000_0111_0011   popaf           
0x0074  00_0000_0111_0100
0x0075  00_0000_0111_0101   reset           
0x0076  00_0000_0111_0110   stopsys         
0x0077  00_0000_0111_0111   stopexe         
0x0078  00_0000_0111_1000   engint         
0x0079  00_0000_0111_1001   disgint         
0x007a  00_0000_0111_1010   ret             
0x007b  00_0000_0111_1011   reti           
0x007c  00_0000_0111_1100   mul             
0x007d  00_0000_0111_1101
0x007e  00_0000_0111_1110
0x007f  00_0000_0111_1111
0x0080  00_0000_10--_----
0x00c0  00_0000_11pp_pppp   xor     io,a   
0x0100  00_0001_00--_----
0x0140  00_0001_01--_----
0x0180  00_0001_10pp_pppp   mov     io,a   
0x01c0  00_0001_11pp_pppp   mov     a,io   
0x0200  00_0010_kkkk_kkkk   ret     k       
0x0300  00_0011_0aaa_aaa0   stt16   m       
0x0301  00_0011_0aaa_aaa1   ldt16   m       
0x0380  00_0011_1aaa_aaa0   idxm    m,a     
0x0381  00_0011_1aaa_aaa1   idxm    a,m     
0x0400  00_010b_bbpp_pppp   swapc   io.b   
0x0600  00_0110_0aaa_aaaa   comp    a,m     
0x0680  00_0110 1aaa_aaaa   comp    m,a     
0x0700  00_0111_0aaa_aaaa   nadd    a,m     
0x0780  00_0111_1aaa_aaaa   nadd    m,a     
0x0800  00_1000_0aaa_aaaa   add     m,a     
0x0880  00_1000_1aaa_aaaa   sub     m,a     
0x0900  00_1001_0aaa_aaaa   addc    m,a     
0x0980  00_1001_1aaa_aaaa   subc    m,a     
0x0a00  00_1010_0aaa_aaaa   and     m,a     
0x0a80  00_1010_1aaa_aaaa   or      m,a     
0x0b00  00_1011_0aaa_aaaa   xor     m,a     
0x0b80  00_1011_1aaa_aaaa   mov     m,a     
0x0c00  00_1100_0aaa_aaaa   add     a,m     
0x0c80  00_1100_1aaa_aaaa   sub     a,m     
0x0d00  00_1101_0aaa_aaaa   addc    a,m     
0x0d80  00_1101_1aaa_aaaa   subc    a,m     
0x0e00  00_1110_0aaa_aaaa   and     a,m     
0x0e80  00_1110_1aaa_aaaa   or      a,m     
0x0f00  00_1111_0aaa_aaaa   xor     a,m     
0x0f80  00_1111_1aaa_aaaa   mov     a,m     
0x1000  01_0000_0aaa_aaaa   addc    m       
0x1080  01_0000_1aaa_aaaa   subc    m       
0x1100  01_0001_0aaa_aaaa   izsn    m       
0x1180  01_0001_1aaa_aaaa   dzsn    m       
0x1200  01_0010_0aaa_aaaa   inc     m       
0x1280  01_0010_1aaa_aaaa   dec     m       
0x1300  01_0011_0aaa_aaaa   clear   m       
0x1380  01_0011_1aaa_aaaa   xch     m       
0x1400  01_0100_0aaa_aaaa   not     m       
0x1480  01_0100_1aaa_aaaa   neg     m       
0x1500  01_0101_0aaa_aaaa   sr      m       
0x1580  01_0101_1aaa_aaaa   sl      m       
0x1600  01_0110_0aaa_aaaa   src     m       
0x1680  01_0110_1aaa_aaaa   slc     m       
0x1700  01_0111_0aaa_aaaa   ceqsn   a,m     
0x1780  01_0111_1aaa_aaaa   cneqsn  a,m     
0x1800  01_100b_bbpp_pppp   t0sn    io.b   
0x1a00  01_101b_bbpp_pppp   t1sn    io.b   
0x1c00  01_110b_bbpp_pppp   set0    io.b   
0x1e00  01_111b_bbpp_pppp   set1    io.b   
0x2000  10_000b_bbaa_aaaa   t0sn    m.b     
0x2200  10_001b_bbaa_aaaa   t1sn    m.b     
0x2400  10_010b_bbaa_aaaa   set0    m.b     
0x2600  10_011b_bbaa_aaaa   set1    m.b     
0x2800  10_1000_dddd_dddd   add     a,k     
0x2900  10_1001_dddd_dddd   sub     a,k     
0x2a00  10_1010_dddd_dddd   ceqsn   a,k     
0x2b00  10_1011_dddd_dddd   cneqsn  a,k     
0x2c00  10_1100_dddd_dddd   and     a,k     
0x2d00  10_1101_dddd_dddd   or      a,k     
0x2e00  10_1110_dddd_dddd   xor     a,k     
0x2f00  10_1111_dddd_dddd   mov     a,k     
0x3000  11_0aaa_aaaa_aaaa   goto    k       
0x3800  11_1aaa_aaaa_aaaa   call    k       


13 bit
Code: [Select]
0x0000 0_0000_0000_0000  nop
0x0001 0_0000_0000_0001 
0x0002 0_0000_0000_0010 
0x0003 0_0000_0000_0011 
0x0004 0_0000_0000_0100 
0x0005 0_0000_0000_0101 
0x0006 0_0000_0000_0110 
0x0007 0_0000_0000_0111 
0x0008 0_0000_0000_1000 
0x0009 0_0000_0000_1001 
0x000a 0_0000_0000_1010 
0x000b 0_0000_0000_1011 
0x000c 0_0000_0000_1100 
0x000d 0_0000_0000_1101 
0x000e 0_0000_0000_1110 
0x000f 0_0000_0000_1111 
0x0010 0_0000_0001_0000  addc      a
0x0011 0_0000_0001_0001  subc      a
0x0012 0_0000_0001_0010  izsn      a
0x0013 0_0000_0001_0011  dzsn      a
0x0014 0_0000_0001_0100 
0x0015 0_0000_0001_0101 
0x0016 0_0000_0001_0110 
0x0017 0_0000_0001_0111  pcadd     a
0x0018 0_0000_0001_1000  not       a
0x0019 0_0000_0001_1001  neg       a
0x001a 0_0000_0001_1010  sr        a
0x001b 0_0000_0001_1011  sl        a
0x001c 0_0000_0001_1100  src       a
0x001d 0_0000_0001_1101  slc       a
0x001e 0_0000_0001_1110  swap      a
0x001f 0_0000_0001_1111 
0x0020 0_0000_0010_---- 
0x0030 0_0000_0011_0000  wdreset
0x0031 0_0000_0011_0001 
0x0032 0_0000_0011_0010  pushaf
0x0033 0_0000_0011_0011  popaf
0x0034 0_0000_0011_0100 
0x0035 0_0000_0011_0101  reset
0x0036 0_0000_0011_0110  stopsys
0x0037 0_0000_0011_0111  stopexe
0x0038 0_0000_0011_1000  engint
0x0039 0_0000_0011_1001  disgint
0x003a 0_0000_0011_1010  ret
0x003b 0_0000_0011_1011  reti
0x003c 0_0000_0011_1100 
0x003d 0_0000_0011_1101 
0x003e 0_0000_0011_1110 
0x003f 0_0000_0011_1111 
0x0040 0_0000_010-_---- 
0x0060 0_0000_011p_pppp  xor       io,a
0x0080 0_0000_100p_pppp  mov       io,a
0x00a0 0_0000_101p_pppp  mov       a,io
0x00c0 0_0000_110a_aaa0  stt16     m
0x00c1 0_0000_110a_aaa1  ldt16     m
0x00e0 0_0000_111a_aaa0  idxm      m,a
0x00e1 0_0000_111a_aaa1  idxm      a,m
0x0100 0_0001_dddd_dddd  ret       k
0x0200 0_0010_bbb0_aaaa  t0sn      m.b
0x0210 0_0010_bbb1_aaaa  t1sn      m.b
0x0300 0_0011_bbb0_aaaa  set0      m.b
0x0310 0_0011_bbb1_aaaa  set1      m.b
0x0400 0_0100_00aa_aaaa  add       m,a
0x0440 0_0100_01aa_aaaa  sub       m,a
0x0480 0_0100_10aa_aaaa  addc      m,a
0x04c0 0_0100_11aa_aaaa  subc      m,a
0x0500 0_0101_00aa_aaaa  and       m,a
0x0540 0_0101_01aa_aaaa  or        m,a
0x0580 0_0101_10aa_aaaa  xor       m,a
0x05c0 0_0101_11aa_aaaa  mov       m,a
0x0600 0_0110_00aa_aaaa  add       a,m
0x0640 0_0110_01aa_aaaa  sub       a,m
0x0680 0_0110_10aa_aaaa  addc      a,m
0x06c0 0_0110_11aa_aaaa  subc      a,m
0x0700 0_0111_00aa_aaaa  and       a,m
0x0740 0_0111_01aa_aaaa  or        a,m
0x0780 0_0111_10aa_aaaa  xor       a,m
0x07c0 0_0111_11aa_aaaa  mov       a,m
0x0800 0_1000_00aa_aaaa  addc      m
0x0840 0_1000_01aa_aaaa  subc      m
0x0880 0_1000_10aa_aaaa  izsn      m
0x08c0 0_1000_11aa_aaaa  dzsn      m
0x0900 0_1001_00aa_aaaa  inc       m
0x0940 0_1001_01aa_aaaa  dec       m
0x0980 0_1001_10aa_aaaa  clear     m
0x09c0 0_1001_11aa_aaaa  xch       m
0x0a00 0_1010_00aa_aaaa  not       m
0x0a40 0_1010_01aa_aaaa  neg       m
0x0a80 0_1010_10aa_aaaa  sr        m
0x0ac0 0_1010_11aa_aaaa  sl        m
0x0b00 0_1011_00aa_aaaa  src       m
0x0b40 0_1011_01aa_aaaa  slc       m
0x0b80 0_1011_10aa_aaaa  ceqsn     a,m
0x0bc0 0_1011_11aa_aaaa  cneqsn    a,m
0x0c00 0_1100_bbbp_pppp  t0sn      p.b
0x0d00 0_1101_bbbp_pppp  t1sn      p.b
0x0e00 0_1110_bbbp_pppp  set0      p.b
0x0f00 0_1111_bbbp_pppp  set1      p.b
0x1000 1_0000_dddd_dddd  add       a,k
0x1100 1_0001_dddd_dddd  sub       a,k
0x1200 1_0010_dddd_dddd  ceqsn     a,k
0x1300 1_0011_dddd_dddd  cneqsn    a,k
0x1400 1_0100_dddd_dddd  and       a,k
0x1500 1_0101_dddd_dddd  or        a,k
0x1600 1_0110_dddd_dddd  xor       a,k
0x1700 1_0111_dddd_dddd  mov       a,k
0x1800 1_10aa_aaaa_aaaa  goto      j
0x1c00 1_11aa_aaaa_aaaa  call      j


Comparison sorted by 16 bit opcode
Code: [Select]
nop                 0000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
ldsptl                                    00_0000_0000_0110
ldspth                                    00_0000_0000_0111
addc      a         0000_0000_0001_0000   00_0000_0110_0000   0_0000_0001_0000
subc      a         0000_0000_0001_0001   00_0000_0110_0001   0_0000_0001_0001
izsn      a         0000_0000_0001_0010   00_0000_0110_0010   0_0000_0001_0010
dzsn      a         0000_0000_0001_0011   00_0000_0110_0011   0_0000_0001_0011
pcadd     a         0000_0000_0001_0111   00_0000_0110_0111   0_0000_0001_0111
not       a         0000_0000_0001_1000   00_0000_0110_1000   0_0000_0001_1000
neg       a         0000_0000_0001_1001   00_0000_0110_1001   0_0000_0001_1001
sr        a         0000_0000_0001_1010   00_0000_0110_1010   0_0000_0001_1010
sl        a         0000_0000_0001_1011   00_0000_0110_1011   0_0000_0001_1011
src       a         0000_0000_0001_1100   00_0000_0110_1100   0_0000_0001_1100
slc       a         0000_0000_0001_1101   00_0000_0110_1101   0_0000_0001_1101
swap      a         0000_0000_0001_1110   00_0000_0110_1110   0_0000_0001_1110
delay     a         0000_0000_0001_1111
wdreset             0000_0000_0011_0000   00_0000_0111_0000   0_0000_0011_0000
pushaf              0000_0000_0011_0010   00_0000_0111_0010   0_0000_0011_0010
popaf               0000_0000_0011_0011   00_0000_0111_0011   0_0000_0011_0011
reset               0000_0000_0011_0101   00_0000_0111_0101   0_0000_0011_0101
stopsys             0000_0000_0011_0110   00_0000_0111_0110   0_0000_0011_0110
stopexe             0000_0000_0011_0111   00_0000_0111_0111   0_0000_0011_0111
engint              0000_0000_0011_1000   00_0000_0111_1000   0_0000_0011_1000
disgint             0000_0000_0011_1001   00_0000_0111_1001   0_0000_0011_1001
ret                 0000_0000_0011_1010   00_0000_0111_1010   0_0000_0011_1010
reti                0000_0000_0011_1011   00_0000_0111_1011   0_0000_0011_1011
mul                 0000_0000_0011_1100   00_0000_0111_1100
pmode     n         0000_0000_010k_kkkk
popw      pcN       0000_0000_0110_tttt
pushw     pcN       0000_0000_0111_tttt
mov       IO,a      0000_0000_10pp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       a,IO      0000_0000_11pp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
cneqsn    a,I       0000_0001_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
stt16     word      0000_001w_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
ldt16     word      0000_001w_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
popw      word      0000_010w_wwww_www0
pushw     word      0000_010w_wwww_www1
igoto     word      0000_011w_wwww_www0
icall     word      0000_011w_wwww_www1
idxm      index,a   0000_100w_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
idxm      a,index   0000_100w_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
ldtabl    word      0000_101w_wwww_www0
ldtabh    word      0000_101w_wwww_www1
delay     I         0000_1110_kkkk_kkkk
ret       I         0000_1111_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
xor       IO,a      0001_0000_00pp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       a,IO      0001_0000_01pp_pppp
cneqsn    M,a       0001_010m_mmmm_mmmm
cneqsn    a,M       0001_011m_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
add       a,I       0001_1000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
sub       a,I       0001_1001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
ceqsn     a,I       0001_1010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
comp      a,I       0001_1011_kkkk_kkkk
and       a,I       0001_1100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
or        a,I       0001_1101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
xor       a,I       0001_1110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
mov       a,I       0001_1111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
t0sn      IO.n      0010_000b_bbpp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t1sn      IO.n      0010_001b_bbpp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
set0      IO.n      0010_010b_bbpp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set1      IO.n      0010_011b_bbpp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
swapc     IO.n      0010_111b_bbpp_pppp   00_010b_bbpp_pppp
nmov      M,a       0011_000m_mmmm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   00_0111_1mmm_mmmm
nadd      a,M       0011_011m_mmmm_mmmm   00_0111_0mmm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
ceqsn     a,M       0011_101m_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   00_0110_1mmm_mmmm
comp      a,M       0011_111m_mmmm_mmmm   00_0110_0mmm_mmmm
add       M,a       0100_000m_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
add       a,M       0100_001m_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
sub       a,M       0100_011m_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
addc      a,M       0100_101m_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
subc      a,M       0100_111m_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
and       a,M       0101_001m_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
or        a,M       0101_011m_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
xor       M,a       0101_100m_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm
xor       a,M       0101_101m_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
mov       M,a       0101_110m_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mov       a,M       0101_111m_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
addc      M         0110_000m_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
subc      M         0110_001m_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
izsn      M         0110_010m_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
dzsn      M         0110_011m_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
inc       M         0110_100m_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
dec       M         0110_101m_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
clear     M         0110_110m_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
xch       M         0110_111m_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
not       M         0111_000m_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
neg       M         0111_001m_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
sr        M         0111_010m_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
sl        M         0111_011m_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
src       M         0111_100m_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
slc       M         0111_101m_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
swap      M         0111_110m_mmmm_mmmm
delay     M         0111_111m_mmmm_mmmm
t0sn      M.n       1000_bbbm_mmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      M.n       1001_bbbm_mmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
set0      M.n       1010_bbbm_mmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      M.n       1011_bbbm_mmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
goto      label     110a_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
call      label     111a_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa


Comparison sorted by mnemonic
Code: [Select]
add       a,I       0001_1000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
add       a,M       0100_001m_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
add       M,a       0100_000m_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
addc      a         0000_0000_0001_0000   00_0000_0110_0000   0_0000_0001_0000
addc      a,M       0100_101m_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
addc      M         0110_000m_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
and       a,I       0001_1100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
and       a,M       0101_001m_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
call      label     111a_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa
ceqsn     a,I       0001_1010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
ceqsn     a,M       0011_101m_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
clear     M         0110_110m_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
cneqsn    a,I       0000_0001_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
cneqsn    a,M       0001_011m_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
cneqsn    M,a       0001_010m_mmmm_mmmm
comp      a,I       0001_1011_kkkk_kkkk
comp      a,M       0011_111m_mmmm_mmmm   00_0110_0mmm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   00_0110_1mmm_mmmm
dec       M         0110_101m_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
delay     a         0000_0000_0001_1111
delay     I         0000_1110_kkkk_kkkk
delay     M         0111_111m_mmmm_mmmm
disgint             0000_0000_0011_1001   00_0000_0111_1001   0_0000_0011_1001
dzsn      a         0000_0000_0001_0011   00_0000_0110_0011   0_0000_0001_0011
dzsn      M         0110_011m_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
engint              0000_0000_0011_1000   00_0000_0111_1000   0_0000_0011_1000
goto      label     110a_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
icall     word      0000_011w_wwww_www1
idxm      a,index   0000_100w_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
idxm      index,a   0000_100w_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
igoto     word      0000_011w_wwww_www0
inc       M         0110_100m_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
izsn      a         0000_0000_0001_0010   00_0000_0110_0010   0_0000_0001_0010
izsn      M         0110_010m_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
ldspth                                    00_0000_0000_0111
ldsptl                                    00_0000_0000_0110
ldt16     word      0000_001w_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
ldtabh    word      0000_101w_wwww_www1
ldtabl    word      0000_101w_wwww_www0
mov       a,I       0001_1111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
mov       a,IO      0000_0000_11pp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
mov       a,M       0101_111m_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
mov       IO,a      0000_0000_10pp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       M,a       0101_110m_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mul                 0000_0000_0011_1100   00_0000_0111_1100
nadd      a,M       0011_011m_mmmm_mmmm   00_0111_0mmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   00_0111_1mmm_mmmm
neg       a         0000_0000_0001_1001   00_0000_0110_1001   0_0000_0001_1001
neg       M         0111_001m_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nmov      M,a       0011_000m_mmmm_mmmm
nop                 0000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
not       a         0000_0000_0001_1000   00_0000_0110_1000   0_0000_0001_1000
not       M         0111_000m_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
or        a,I       0001_1101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
or        a,M       0101_011m_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
pcadd     a         0000_0000_0001_0111   00_0000_0110_0111   0_0000_0001_0111
pmode     n         0000_0000_010k_kkkk
popaf               0000_0000_0011_0011   00_0000_0111_0011   0_0000_0011_0011
popw      pcN       0000_0000_0110_tttt
popw      word      0000_010w_wwww_www0
pushaf              0000_0000_0011_0010   00_0000_0111_0010   0_0000_0011_0010
pushw     pcN       0000_0000_0111_tttt
pushw     word      0000_010w_wwww_www1
reset               0000_0000_0011_0101   00_0000_0111_0101   0_0000_0011_0101
ret                 0000_0000_0011_1010   00_0000_0111_1010   0_0000_0011_1010
ret       I         0000_1111_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
reti                0000_0000_0011_1011   00_0000_0111_1011   0_0000_0011_1011
set0      IO.n      0010_010b_bbpp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set0      M.n       1010_bbbm_mmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      IO.n      0010_011b_bbpp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
set1      M.n       1011_bbbm_mmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
sl        a         0000_0000_0001_1011   00_0000_0110_1011   0_0000_0001_1011
sl        M         0111_011m_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
slc       a         0000_0000_0001_1101   00_0000_0110_1101   0_0000_0001_1101
slc       M         0111_101m_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
sr        a         0000_0000_0001_1010   00_0000_0110_1010   0_0000_0001_1010
sr        M         0111_010m_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
src       a         0000_0000_0001_1100   00_0000_0110_1100   0_0000_0001_1100
src       M         0111_100m_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
stopexe             0000_0000_0011_0111   00_0000_0111_0111   0_0000_0011_0111
stopsys             0000_0000_0011_0110   00_0000_0111_0110   0_0000_0011_0110
stt16     word      0000_001w_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
sub       a,I       0001_1001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
sub       a,M       0100_011m_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
subc      a         0000_0000_0001_0001   00_0000_0110_0001   0_0000_0001_0001
subc      a,M       0100_111m_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
subc      M         0110_001m_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
swap      a         0000_0000_0001_1110   00_0000_0110_1110   0_0000_0001_1110
swap      M         0111_110m_mmmm_mmmm
swapc     IO.n      0010_111b_bbpp_pppp   00_010b_bbpp_pppp
t0sn      IO.n      0010_000b_bbpp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t0sn      M.n       1000_bbbm_mmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      IO.n      0010_001b_bbpp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
t1sn      M.n       1001_bbbm_mmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
wdreset             0000_0000_0011_0000   00_0000_0111_0000   0_0000_0011_0000
xch       M         0110_111m_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
xor       a,I       0001_1110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
xor       a,IO      0001_0000_01pp_pppp
xor       a,M       0101_101m_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
xor       IO,a      0001_0000_00pp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       M,a       0101_100m_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 27, 2018, 07:18:11 pm
Thanks for the code. I seem to have an endianess problem somewhere.
I am using linux, but the IDE doesnt work with wine.
So I used windows to make and convert the file. Somehow bytes got swapped  :palm:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 27, 2018, 07:49:57 pm
[…]
If I counted correctly there are only these instruction set families
.Assembly   ASM_INSTR   SYM_83A
.Assembly   ASM_INSTR   SYM_84B
.Assembly   ASM_INSTR   SYM_85A
.Assembly   ASM_INSTR   SYM_86B
.Assembly   ICE_INSTR   SYM_83A
.Assembly   ICE_INSTR   SYM_86A
.Assembly   INSTRUMENT   SYM_82A
.Assembly   INSTRUMENT   SYM_83A
.Assembly   INSTRUMENT   SYM_86A

I suspect that INSTRUMENT means same for ASM and ICE

I had noticed those SYM_ whatever things in the files before, but didn't see their relation to the instruction sets. ASM_INSTR SYM_85A is found in files for devices both with (e.g. PMS130) and without (e.g. PFS154) the mul instruction. ASM_INSTR SYM_83A is found in files for devices with pushw (e.g. PMC884) without pushw (e.g. PMS232).

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: westfw on November 28, 2018, 09:04:54 am
(Wow.   I just want to throw in a compliment.  This has been REALLY IMPRESSIVE!  Great work; excellent collaboration!)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on November 28, 2018, 08:47:40 pm
Maybe the Symbol Files have to be seen in conjuction with the inc files.
SYM_85A does not include the mul instruction.
The inc file for the pfs154 doesnt have anything related to mul and the ide complains that "mul not be supported at pfs154"

The inc file for the pms130 does have to registers defined
   MULOP      IO_RW      0x08
   MULRH      IO_RO      0x09
for the multiplication.

I couldnt find the device ids in the symbol files so that must be stored somewhere else.

So I guess the symbol files are templates for the ide that then get modified for the specific ic.

Edit: if I change the SYM in the INC file, instructions missing in the other family are no longer recognized. (syntax error)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 30, 2018, 12:21:26 pm
For all the people interested in ordering PADAUK parts and tools.

I ordered some stuff from lcsc.com with standard shipping. Payment was done using Paypal, delivery cost was around 7 USD. After 15 days my order arrived without any problems (direct shipping from China to my place).


Here is a list of ICs and tools from PADAUK I use.

Please consider to use the AFFILIATE LINKS from below when you order from lcsc.com (https://lcsc.com/search?q=padauk%20tech&promote=ZTU4NGt1MWVFOGtHWHZoVDZDYkZaS2xvMGtuMUlhNDBJMHJtb2xqK3VnbWRMYy84NDFQTjVkSGZ3N3ZmdEJodlo1bUtRUlpBMXhTaFl2alpLOVhEVVd6cGQ5NlltQ1lQU3l5YWpnR3ZDZUNkb1k1Vll3TGYwK2pRa1djMlZuY2phc2lu). This will give me some credits there and I can order more PADAUK parts to investigate.

THANK YOU!

---

ICs I use:

Flash based ICs (1000 erase/write cycles possible):
PFS154-S08 (https://lcsc.com/product-detail/Others_PADAUK-Tech-PFS154-S08_C317611.html?promote=NTBjZlBvSU9aWWlET0VCVkUrUGcrU1c0TkQ4NFBPcGlGZVExb1YvbFQ1UHlsWDhUTXlEaUZwc0xoSTc4YjJoOTZnTkdzUlVZTDZPY3VpeHhTUVNNQnJqZnRqMVNhNWN6a1NiSEFXTk81S0VWWkpyT2VOYlh5MitWSzVydmMwMjZJelFG)  (14 bit opcodes)
PFS154-S14 (https://lcsc.com/product-detail/Others_PADAUK-Tech-PFS154-S14_C317612.html?promote=ZWJiY2cvQk1Qb2xBS2RxRXZiQXlTcnN2amd6NHBaVmEzTGdHSGkzOHpHQjc2ck84TDMzWlVCR1M1cGpSWjBhdmcxNHh3OWxUMGQ2RFVXaWQvOFR0bERjcmxwNFN6V3VPNzVneFM0Y3RHZnBvZzkvMksvYUdKNlVwZjJqRVd0M1RYMFNN) (14 bit opcodes)

OTP ICs (One Time Programmable):
PMS154B-S14 (https://lcsc.com/product-detail/PADAUK_PADAUK-Tech-PMS154B_C129128.html?promote=MmVkYTcyVnU0YzNSRnNVRTRFbWNLWlp0MzdZNzJBdG5zeUVxaWNCREdtQzlsTjJMRS9KeXFWZGtvd1RQTXZOcGdOTktXN0ZjaFB2alBLU0FGYkhwOTYwYU9Bc09vaEdJckJUMkgwVGtDZnc1bnFaYVVBS1Z4WFBPSmZhRXorU2YwQytw) (14 bit opcodes)
PMS150C-S08 (https://lcsc.com/product-detail/PADAUK_PADAUK-Tech-PMS150C_C129127.html?promote=Nzc2YmJ1OGlseDIvMU02L29EN3I4ZlhUSDA4UjNBbEdHOEhWUVl6MHVORFc5Y20rUUZLWlNtUGVncndQVGxWRjZONzBQOXpadVZJSXB5dlg0cTBoMmNSVHc1amFBajhwTDN1WTNPRXROa0tiZVVYTE0rTkVxMDJTdU9wWXZub25xdjZS) (13 bit opcodes)

---

My Programmer: PDK 3S-P-002 (https://lcsc.com/product-detail/_PADAUK-Tech-PDK-3S-P-002_C248471.html?promote=YWIwY2NZV0FJeU9lMGQwWG1EaUsrQXdHTXU1UDF5YnRMdXJtbkgxa1JGS2kxYWZTU1UvemdLYTQ3elhJck04ckpwUWVRdWhmMXgyVGdEZHJvOTFXejZ3WGhTUGVUTE9oenNTSzRQZHZtOXBVWkc5VEVwdDM3elpUbzM0N1ZXZXoxcTdz) !!!OLD VERSION, DOES NOT SUPPORT PFS154 Flash based IC!!!!

Alternative Programmer: PDK 5S-P-003 (https://lcsc.com/product-detail/Development-Kits-Emulators-Simulators_PADAUK-Tech-5S-P-003_C263009.html?promote=NTQ0MUpsUisxei96ZG1QWnk3dEpKTDhCNjR4dldHaEhLY2g3ZVRkK1RGTU0zNVpmdlJ2d0NhY2hPWTAzUVlxNTlHRkhXZ21oYzVENU1uUHRsS016c2V2NWN1N2JjK2lYQ2tFN3hXUmYvcmlZV0FsZ1VGMDVYcy8rTDZWblVaOWQ1cWZS)

My ICE: PDK 5S-I-S01 (https://lcsc.com/product-detail/Development-Kits-Emulators-Simulators_PADAUK-Tech-PDK-5S-I-S01_C194849.html?promote=ZjU3ZFVTT2c0Rk1MUitrTWNjV09EeHN2bnBTVXBsUDRGUCt3V2lZdnhoZWVuenhQdGNpK21FQ3FOaFdNODRyV3FiZTkyVG44b2FrN0xSTHI1WjZod2FzQmltRm1NQVZMRlV1VVRzYmpTZFpPdFBwWEZEb3k4QUVyZEx4SWxhV0pKbEN3) !!! SUPPORTS ALL SINGLE CORE VARIANTS!!!

Alternative ICE: PDK 3S-I-003 (https://lcsc.com/product-detail/Development-Kits-Emulators-Simulators_PADAUK-Tech-PDK-3S-I-003_C341193.html?promote=NTVjNHFIZ0VuYUk4eXpXZ1BPS0RaRHdlL2V4SmNseEtVVElxZXo4bElmNDJaMlFNbGpVd254ZE8vTGZJOGZhTHNRYXh6ME1McnlNNlVoVWRWTlI4b3MrbEtRRTlReVo4eU9MVHRvOUNTYm5uMlZZN3ZSbHUrYVoxTjdLOThieXFndDV4) !!!OLD PRODUCT, ONLY FOR SOME MULTICORE VARIANTS!!!

---

Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on November 30, 2018, 03:56:21 pm
Do we have any idea if the Padauk Programmer supports on-target debugging in any way?

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on November 30, 2018, 04:49:27 pm
Do we have any idea if the Padauk Programmer supports on-target debugging in any way?

Philipp

Hi,

the programmer is just for writing to the IC. Usually the IDE inserts some "INIT-CODE" for IC testing and calibrating clock. This init code steals some valuable code space. It uses bit bang protocol on 3 IO pins to communicate with WRITER.

-> WRITER can not debug anything from your user program.
-> PADAUK CPU do not have any debug features (e.g. breakpoints) built in

Your best choice is to use the ICE. Then you get breakpoints and memory inspection from the IDE directly.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 01, 2018, 12:51:12 am
Disassembler for all Padauk MCUs.

Usage: pdisasm pdk [io_symbols [mem_symbols]]

To show instruction set: pdisasm 13 | 14 | 16 | all
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 01, 2018, 10:32:01 am
Disassembler for all Padauk MCUs.

Usage: pdisasm pdk [io_symbols [mem_symbols]]

To show instruction set: pdisasm 13 | 14 | 16 | all


Great job!
I've modified it so that it compiles under linux (none of those ms dependencies any more and a Makefile), hope thats ok (+ some whitespace changes)
You can look at the attached patch files to see what I did.
just 'make' it.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 01, 2018, 12:35:31 pm
I've modified main so that it will load the io symbols automagically, because that was irritating me to no end ;)

Code: [Select]
--- original/padauk_disasm.cpp 2018-12-01 11:25:20.595205297 +0100
+++ padauk_disasm.cpp 2018-12-01 13:31:07.148535905 +0100
@@ -1,11 +1,11 @@
-
-#include "stdafx.h"
+#include <string.h>
+#include <stdlib.h>
 #include "pdk.h"
 #include "disasm.h"
 
 
-int main(int argc, char **argv)
-{
+int
+main(int argc, char **argv) {
  if (argc < 2) {
  printf("Usage: pdisasm pdk [ io_symbols [ mem_symbols] ]\n");
  return 0;
@@ -30,10 +30,17 @@
  auto d = CPadaukDisasm::New(pdk.bits);
  if (!d) { printf("Unsupported core (%i bits)\n", pdk.bits);  return -2; }
 
- if (argc > 2) d->io_symbols.ReadFile(argv[2]);
+ if (argc > 2) {
+ d->io_symbols.ReadFile(argv[2]);
+ } else {
+ char fname[17] = {};
+ sprintf(fname, "sym_io_%d.txt", pdk.bits);
+ d->io_symbols.ReadFile(fname);
+ }
+
  if (argc > 3) d->mem_symbols.ReadFile(argv[3]);
 
  d->disasm(pdk);
  }
-    return 0;
+ return 0;
 }
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 01, 2018, 12:57:14 pm
Here is the precompiled ready to run binary and support files for linux. I use Ubuntu 18.04 LTS so should be fine for any current distribution ( I hope ;)

small_possum is the same but with debug symbols stripped so its only about 45k in size ready to run.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 02, 2018, 04:40:25 pm
Today, I made a first step to inefficently compiling a small subset of C to Padauk asm code. The current version is very restricted and generates very inefficient code; it is untested.

There is no assembler / linker support, so the resulting .asm file has to be assembled in other ways.

Particularly noticeable restrictions:

* The only data types supported are the basic integer types. No pointers, arrays, struct, union, float, etc.
* Functions cannot have parameters.
* Functions can return at most 1 byte (i.e. only void, bool, char, signed char, unsigned char are allowed).
* Bitwise operations and shifts are no supported.
* Multiplicative operators are not supported.
* Functions are not reentrant.

Code in svn at https://svn.code.sf.net/p/sdcc/code/branches/pdk/sdcc, use -mpdk14 to target Padauk (despite the name, the set of instructions emitted is part of the common subset of the Padauk instruction sets).

Philipp

P.S.: The only allowed comparisons are for equality, i.e. == and !=, while <,<=, >, >= don't work. Fortunately, most attempts to use non-supported functionality result in compile-time errors.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 03, 2018, 08:44:39 am
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others

Has this been resolved? Do we know if there are encoding differences within the individual 13-Bit / 14-Bit / 16_ Bit instruction sets (apart from differences in the supported subset of instructions)?

In particular: Can we be reasonably sure that the 14-Bit instruction set at https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html reflects the actual encoding for the PFS154?

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 03, 2018, 12:53:43 pm
I have a startup file for the pfs154 that doesnt dissasemble correctly using the current sets, I suspect that 85A is still different from the others

Has this been resolved? Do we know if there are encoding differences within the individual 13-Bit / 14-Bit / 16_ Bit instruction sets (apart from differences in the supported subset of instructions)?

In particular: Can we be reasonably sure that the 14-Bit instruction set at https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html reflects the actual encoding for the PFS154?

Philipp


Just checked again. Yes.
Startup code for the PFS154 (dissassembled with opossum on linux):

Code: [Select]
PDK version: 20
PDK data size:  2048 words
Free data size: 2016 words
MCU: PFS154 [ID: 0x2AA1]
Compiler version: 0.83B17
14 bit core
0000  0070  wdreset   
0001  2F00  mov       a, 0x00
0002  0182  mov       SP, a
0003  3FED  call      0x07ED
0004  018B  mov       IHRCR, a
0005  3FEE  call      0x07EE
0006  019A  mov       BGTR, a
0007  2F20  mov       a, 0x20
0008  019B  mov       MISC_LVR, a
0009  2F34  mov       a, 0x34
000A  0183  mov       CLKCMD, a
000B  3FFE  call      0x07FE
000C  2AFF  ceqsn     a, 0xFF
000D  3054  goto      0x0054
000E  3FED  call      0x07ED
000F  0B81  mov       M1, a
0010  1F91  set1      PAC.6
0011  2F20  mov       a, 0x20
0012  0B80  mov       M0, a
0013  1AD0  t1sn      PA.3
0014  3013  goto      0x0013
0015  1F90  set1      PA.6
0016  0063  dzsn      a
0017  3016  goto      0x0016
0018  1180  dzsn      M0
0019  3016  goto      0x0016
001A  1D90  set0      PA.6
001B  18D0  t0sn      PA.3
001C  301B  goto      0x001B
001D  2F01  mov       a, 0x01
001E  1950  t0sn      PA.5
001F  2FFF  mov       a, 0xFF
0020  0C01  add       a, M1
0021  018B  mov       IHRCR, a
0022  0B81  mov       M1, a
0023  1AD0  t1sn      PA.3
0024  3023  goto      0x0023
0025  1B50  t1sn      PA.5
0026  304F  goto      0x004F
0027  2F04  mov       a, 0x04
0028  0188  mov       MISC, a
0029  18D0  t0sn      PA.3
002A  3029  goto      0x0029
002B  2F02  mov       a, 0x02
002C  0182  mov       SP, a
002D  1304  clear     M4
002E  1305  clear     M5
002F  2F5E  mov       a, 0x5E
0030  0B82  mov       M2, a
0031  2F00  mov       a, 0x00
0032  0B83  mov       M3, a
0033  0006  ldsptl   
0034  0B04  xor       M4, a
0035  0007  ldspth   
0036  0805  add       M5, a
0037  1584  sl        M4
0038  1685  slc       M5
0039  1004  addc      M4
003A  1282  dec       M2
003B  1083  subc      M3
003C  1A40  t1sn      FLAG.C
003D  3033  goto      0x0033
003E  1F90  set1      PA.6
003F  1AD0  t1sn      PA.3
0040  303F  goto      0x003F
0041  1584  sl        M4
0042  1685  slc       M5
0043  0590  swapc     PA.6
0044  18D0  t0sn      PA.3
0045  3044  goto      0x0044
0046  1950  t0sn      PA.5
0047  303F  goto      0x003F
0048  1D90  set0      PA.6
0049  1AD0  t1sn      PA.3
004A  3049  goto      0x0049
004B  18D0  t0sn      PA.3
004C  304B  goto      0x004B
004D  1B50  t1sn      PA.5
004E  302B  goto      0x002B
004F  18D0  t0sn      PA.3
0050  304F  goto      0x004F
0051  1B50  t1sn      PA.5
0052  3011  goto      0x0011
0053  3053  goto      0x0053
0054  018B  mov       IHRCR, a
0055  0000  nop       // here a nop/wdreset pattern starts so that I can recognize my code
0056  0070  wdreset   
0057  0000  nop       
0058  0070  wdreset   
0059  0000  nop       
005A  0070  wdreset   
005B  0000  nop       
005C  0070  wdreset   
005D  0000  nop       
005E  3055  goto      0x0055 
....    // all other locations are 3FFF
07EF  1FFE  set1      GPCC.7
07F0  3FFF  call      0x07FF
07F1  3FFF  call      0x07FF
07F2  3FFF  call      0x07FF
07F3  3FFF  call      0x07FF
07F4  3FFF  call      0x07FF
07F5  3FFF  call      0x07FF
07F6  3FFF  call      0x07FF
07F7  3FFF  call      0x07FF
07F8  0000  nop       
07F9  0000  nop       
07FA  3FFF  call      0x07FF
07FB  3FFF  call      0x07FF
07FC  3FFF  call      0x07FF
07FD  3FFF  call      0x07FF
07FE  3FFF  call      0x07FF
07FF  3DFD  call      0x05FD

Edit: It's actually slightly different from the one posted above, but only single instructions and coherent with the encoding.
Probably the options I chose?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 03, 2018, 01:19:38 pm
I think the only family missing is for these chips:

grep -Rlsi SYM_86B

PMS134.INC
MCU371.INC
PMS132K.INC
PMS133.INC
PFS173.INC

---

The differences I can spot are minimal: 86B also includes the NMOV instruction but lacks the (explicit?) description of LDSPTL/LDSPTH but instead has LDTABL/LDTABH.
Also the order of the instructions in the symbol file is slightly different.

The datasheet claims that the pfs173 has 89 instructions (I count 88) while the pfs154 has 82.

The actual devices are thus slightly different: the PFS154 misses the NADD and COMP instructions as per datasheet. Dont know if the IDE will accept them anyway. And LDSPTL/LDSPTH is in the Symbol file but not documented.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 03, 2018, 02:05:20 pm
And trying to dissassemble the PFS173 startup code we get this:

PDK version: 20
PDK data size:  3072 words
Free data size: 3040 words
MCU: PFS173 [ID: 0x2AA2]
Compiler version: 0.83B17
15 bit core
Unsupported core (15 bits)

So I was almost right: there is a different encoding (but not for the pfs154) :-DD
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 03, 2018, 02:15:02 pm
So the 15-Bit encoding actually exists. Interesting. I hope it gets documented, too.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 03, 2018, 03:00:07 pm
Just noticed a small error I made in the linux sources that cuts off the first three bits of the printed opcode.
Corrected source below (also includes startupcode for pfs154 and 173) and precompiled binary.

Just a reminder to myself:
the amount of addressable memory is (core size in bits - 3)
16 -> 13 -> 8192 words, Family 83A
15 -> 12 -> 4096 words, Family 86B
14 -> 11 -> 2048 words, Family 85A
13 -> 10 -> 1024 words, Family 84B
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 03, 2018, 03:16:20 pm
15 bit instruction set confirmed. I thought it existed but the chips with 4 kW memory used the 16 bit instruction set, so I stopped looking.
Working on complete decode and updated disassembler.

Code: [Select]
6000   goto  0x0000
6FFF   goto  0x0FFF
7000   call  0x0000
7FFF   call  0x0FFF

12 bit program address
Probably 8 bit memory address.
IO address TBD.

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 03, 2018, 07:17:57 pm
Today, I made a first step to inefficently compiling a small subset of C to Padauk asm code. The current version is very restricted and generates very inefficient code; it is untested.

There is no assembler / linker support, so the resulting .asm file has to be assembled in other ways.

[…]

Code in svn at https://svn.code.sf.net/p/sdcc/code/branches/pdk/sdcc, use -mpdk14 to target Padauk (despite the name, the set of instructions emitted is part of the common subset of the Padauk instruction sets).

On the second day, wrt. completeness of implementation of the C standard, this has now far surpassed Mini-C.

Noticeable remaining restrictions:

* Variables can only reside in RAM, not in code space
* Global and static variables are not initialized.
* No floating-point or bit-fields.
* Functions can return at most 2 bytes (i.e. no long or long long).
* Multiplicative operators are not supported.
* Functions are not reentrant.
* No support for variable arguments.
* No standard library.
* struct / union cannot be assigned, passed as arguments or returned.
* No compoundliterals.
* No access to I/O from C.

There is no glue to connect this to assembler / linker yet, so the only useable output is asm code.
The generated asm code is still very inefficient. I will look into improving that a bit soon.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 03, 2018, 07:27:53 pm
Has this been resolved? Do we know if there are encoding differences within the individual 13-Bit / 14-Bit / 16_ Bit instruction sets (apart from differences in the supported subset of instructions)?
In particular: Can we be reasonably sure that the 14-Bit instruction set at https://free-pdk.github.io/PADAUK_FPPA_14_bit_instruction_set.html reflects the actual encoding for the PFS154?

Philipp

I updated the instruction set pages (13,14,16 bit) with all known stuff gathered from the contributors of this forum:

https://free-pdk.github.io/

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 03, 2018, 07:43:54 pm
15 bit instruction set

Used by PMS132K, PMS133, PMS134, PFS173, MCU371

Code: [Select]
0x0000  000_0000_0000_0000  nop
0x0001  000_0000_0000_0001
0x0002  000_0000_0000_001-
0x0004  000_0000_0000_01--
0x0008  000_0000_0000_1---
0x0010  000_0000_0001_----
0x0020  000_0000_001-_----
0x0040  000_0000_010-_----
0x0050  000_0000_0101_----
0x0060  000_0000_0110_0000  addc     a
0x0061  000_0000_0110_0001  subc     a
0x0062  000_0000_0110_0010  izsn     a
0x0063  000_0000_0110_0011  dzsn     a
0x0064  000_0000_0110_0100
0x0065  000_0000_0110_0101
0x0066  000_0000_0110_0110
0x0067  000_0000_0110_0111  pcadd    a
0x0068  000_0000_0110_1000  not      a
0x0069  000_0000_0110_1001  neg      a
0x006A  000_0000_0110_1010  sr       a
0x006B  000_0000_0110_1011  sl       a
0x006C  000_0000_0110_1100  src      a
0x006D  000_0000_0110_1101  slc      a
0x006E  000_0000_0110_1110  swap     a
0x006F  000_0000_0110_1111
0x0070  000_0000_0111_0000  wdreset
0x0071  000_0000_0111_0001
0x0072  000_0000_0111_0010  pushaf
0x0073  000_0000_0111_0011  popaf
0x0074  000_0000_0111_0100
0x0075  000_0000_0111_0101  reset
0x0076  000_0000_0111_0110  stopsys
0x0077  000_0000_0111_0111  stopexe
0x0078  000_0000_0111_1000  engint
0x0079  000_0000_0111_1001  disgint
0x007A  000_0000_0111_1010  ret
0x007B  000_0000_0111_1011  reti
0x007C  000_0000_0111_1100  mul
0x007D  000_0000_0111_1101
0x007E  000_0000_0111_1110
0x007F  000_0000_0111_1110
0x0080  000_0000_1ppp_pppp  xor      a,IO
0x0100  000_0001_0ppp_pppp  mov      IO,a
0x0180  000_0001_1ppp_pppp  mov      a,IO
0x0200  000_0010_kkkk_kkkk  ret      I
0x0300  000_0011_----_----
0x0400  000_0100_----_----
0x0500  000_0101_wwww_www0  ldtabl   word
0x0501  000_0101_wwww_www1  ldtabh   word
0x0600  000_0110_wwww_www0  stt16    word
0x0601  000_0110_wwww_www1  ldt16    word
0x0700  000_0111_wwww_www0  idxm     index,a
0x0701  000_0111_wwww_www1  idxm     a,index
0x0800  000_10--_----_----
0x0C00  000_1100_mmmm_mmmm  comp     a,M
0x0D00  000_1101_mmmm_mmmm  comp     M,a
0x0E00  000_1110_mmmm_mmmm  nadd     a,M
0x0F00  000_1111_mmmm_mmmm  nadd     M,a
0x1000  001_0000_mmmm_mmmm  add      M,a
0x1100  001_0001_mmmm_mmmm  sub      M,a
0x1200  001_0010_mmmm_mmmm  addc     M,a
0x1300  001_0011_mmmm_mmmm  subc     M,a
0x1400  001_0100_mmmm_mmmm  and      M,a
0x1500  001_0101_mmmm_mmmm  or       M,a
0x1600  001_0110_mmmm_mmmm  xor      M,a
0x1700  001_0111_mmmm_mmmm  mov      M,a
0x1800  001_1000_mmmm_mmmm  add      a,M
0x1900  001_1001_mmmm_mmmm  sub      a,M
0x1A00  001_1010_mmmm_mmmm  addc     a,M
0x1B00  001_1011_mmmm_mmmm  subc     a,M
0x1C00  001_1100_mmmm_mmmm  and      a,M
0x1D00  001_1101_mmmm_mmmm  or       a,M
0x1E00  001_1110_mmmm_mmmm  xor      a,M
0x1F00  001_1111_mmmm_mmmm  mov      a,M
0x2000  010_0000_mmmm_mmmm  addc     M
0x2100  010_0001_mmmm_mmmm  subc     M
0x2200  010_0010_mmmm_mmmm  izsn     M
0x2300  010_0011_mmmm_mmmm  dzsn     M
0x2400  010_0100_mmmm_mmmm  inc      M
0x2500  010_0101_mmmm_mmmm  dec      M
0x2600  010_0110_mmmm_mmmm  clear    M
0x2700  010_0111_mmmm_mmmm  xch      M
0x2800  010_1000_mmmm_mmmm  not      M
0x2900  010_1001_mmmm_mmmm  neg      M
0x2A00  010_1010_mmmm_mmmm  sr       M
0x2B00  010_1011_mmmm_mmmm  sl       M
0x2C00  010_1100_mmmm_mmmm  src      M
0x2D00  010_1101_mmmm_mmmm  slc      M
0x2E00  010_1110_mmmm_mmmm  ceqsn    a,M
0x2F00  010_1111_mmmm_mmmm  cneqsn   a,M
0x3000  011_00bb_bppp_pppp  t0sn     IO.n
0x3400  011_01bb_bppp_pppp  t1sn     IO.n
0x3800  011_10bb_bppp_pppp  set0     IO.n
0x3C00  011_11bb_bppp_pppp  set1     IO.n
0x4000  100_00bb_bmmm_mmmm  t0sn     M.n
0x4400  100_01bb_bmmm_mmmm  t1sn     M.n
0x4800  100_10bb_bmmm_mmmm  set0     M.n
0x4C00  100_11bb_bmmm_mmmm  set1     M.n
0x5000  101_0000_kkkk_kkkk  add      a,I
0x5100  101_0001_kkkk_kkkk  sub      a,I
0x5200  101_0010_kkkk_kkkk  ceqsn    a,I
0x5300  101_0011_kkkk_kkkk  cneqsn   a,I
0x5400  101_0100_kkkk_kkkk  and      a,I
0x5500  101_0101_kkkk_kkkk  or       a,I
0x5600  101_0110_kkkk_kkkk  xor      a,I
0x5700  101_0111_kkkk_kkkk  mov      a,I
0x5800  101_10--_----_----
0x5C00  101_11bb_bppp_pppp  swapc    IO.n
0x6000  110_aaaa_aaaa_aaaa  goto     label
0x7000  111_aaaa_aaaa_aaaa  call     label

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 03, 2018, 08:00:00 pm
Edit: It's actually slightly different from the one posted above, but only single instructions and coherent with the encoding.
Probably the options I chose?

Yes, I think so. Different .ADJUST_IC options and different code size.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 03, 2018, 08:09:57 pm
Just a reminder to myself:
the amount of addressable memory is (core size in bits - 3)
16 -> 13 -> 8192 words, Family 83A
15 -> 12 -> 4096 words, Family 86B
14 -> 11 -> 2048 words, Family 85A
13 -> 10 -> 1024 words, Family 84B

Also...

16 -> 13 -> 8192 words, Family 82A  [PMC882 PDK22C13 PDK22C13A PDK22C58 PDK22C58A PDK82C12 PDK82C13 PDK82S_EV]
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 03, 2018, 08:23:58 pm
16/15/14/13 bit instruction encoding sorted by 16 bit opcode
Code: [Select]
nop                 0000_0000_0000_0000   000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
ldsptl                                                         00_0000_0000_0110
ldspth                                                         00_0000_0000_0111
addc      a         0000_0000_0001_0000   000_0000_0110_0000   00_0000_0110_0000   0_0000_0001_0000
subc      a         0000_0000_0001_0001   000_0000_0110_0001   00_0000_0110_0001   0_0000_0001_0001
izsn      a         0000_0000_0001_0010   000_0000_0110_0010   00_0000_0110_0010   0_0000_0001_0010
dzsn      a         0000_0000_0001_0011   000_0000_0110_0011   00_0000_0110_0011   0_0000_0001_0011
pcadd     a         0000_0000_0001_0111   000_0000_0110_0111   00_0000_0110_0111   0_0000_0001_0111
not       a         0000_0000_0001_1000   000_0000_0110_1000   00_0000_0110_1000   0_0000_0001_1000
neg       a         0000_0000_0001_1001   000_0000_0110_1001   00_0000_0110_1001   0_0000_0001_1001
sr        a         0000_0000_0001_1010   000_0000_0110_1010   00_0000_0110_1010   0_0000_0001_1010
sl        a         0000_0000_0001_1011   000_0000_0110_1011   00_0000_0110_1011   0_0000_0001_1011
src       a         0000_0000_0001_1100   000_0000_0110_1100   00_0000_0110_1100   0_0000_0001_1100
slc       a         0000_0000_0001_1101   000_0000_0110_1101   00_0000_0110_1101   0_0000_0001_1101
swap      a         0000_0000_0001_1110   000_0000_0110_1110   00_0000_0110_1110   0_0000_0001_1110
delay     a         0000_0000_0001_1111
wdreset             0000_0000_0011_0000   000_0000_0111_0000   00_0000_0111_0000   0_0000_0011_0000
pushaf              0000_0000_0011_0010   000_0000_0111_0010   00_0000_0111_0010   0_0000_0011_0010
popaf               0000_0000_0011_0011   000_0000_0111_0011   00_0000_0111_0011   0_0000_0011_0011
reset               0000_0000_0011_0101   000_0000_0111_0101   00_0000_0111_0101   0_0000_0011_0101
stopsys             0000_0000_0011_0110   000_0000_0111_0110   00_0000_0111_0110   0_0000_0011_0110
stopexe             0000_0000_0011_0111   000_0000_0111_0111   00_0000_0111_0111   0_0000_0011_0111
engint              0000_0000_0011_1000   000_0000_0111_1000   00_0000_0111_1000   0_0000_0011_1000
disgint             0000_0000_0011_1001   000_0000_0111_1001   00_0000_0111_1001   0_0000_0011_1001
ret                 0000_0000_0011_1010   000_0000_0111_1010   00_0000_0111_1010   0_0000_0011_1010
reti                0000_0000_0011_1011   000_0000_0111_1011   00_0000_0111_1011   0_0000_0011_1011
mul                 0000_0000_0011_1100   000_0000_0111_1100   00_0000_0111_1100
pmode     n         0000_0000_010k_kkkk
popw      pcN       0000_0000_0110_tttt
pushw     pcN       0000_0000_0111_tttt
mov       IO,a      0000_0000_10pp_pppp   000_0001_0ppp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       a,IO      0000_0000_11pp_pppp   000_0001_1ppp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
cneqsn    a,I       0000_0001_kkkk_kkkk   101_0011_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
stt16     word      0000_001w_wwww_www0   000_0110_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
ldt16     word      0000_001w_wwww_www1   000_0110_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
popw      word      0000_010w_wwww_www0
pushw     word      0000_010w_wwww_www1
igoto     word      0000_011w_wwww_www0
icall     word      0000_011w_wwww_www1
idxm      index,a   0000_100w_wwww_www0   000_0111_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
idxm      a,index   0000_100w_wwww_www1   000_0111_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
ldtabl    word      0000_101w_wwww_www0   000_0101_wwww_www0
ldtabh    word      0000_101w_wwww_www1   000_0101_wwww_www1
delay     I         0000_1110_kkkk_kkkk
ret       I         0000_1111_kkkk_kkkk   000_0010_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
xor       IO,a      0001_0000_00pp_pppp   000_0000_1ppp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       a,IO      0001_0000_01pp_pppp
cneqsn    M,a       0001_010m_mmmm_mmmm
cneqsn    a,M       0001_011m_mmmm_mmmm   010_1111_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
add       a,I       0001_1000_kkkk_kkkk   101_0000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
sub       a,I       0001_1001_kkkk_kkkk   101_0001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
ceqsn     a,I       0001_1010_kkkk_kkkk   101_0010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
comp      a,I       0001_1011_kkkk_kkkk
and       a,I       0001_1100_kkkk_kkkk   101_0100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
or        a,I       0001_1101_kkkk_kkkk   101_0101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
xor       a,I       0001_1110_kkkk_kkkk   101_0110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
mov       a,I       0001_1111_kkkk_kkkk   101_0111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
t0sn      IO.n      0010_000b_bbpp_pppp   011_00bb_bppp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t1sn      IO.n      0010_001b_bbpp_pppp   011_01bb_bppp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
set0      IO.n      0010_010b_bbpp_pppp   011_10bb_bppp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set1      IO.n      0010_011b_bbpp_pppp   011_11bb_bppp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
swapc     IO.n      0010_111b_bbpp_pppp   101_11bb_bppp_pppp   00_010b_bbpp_pppp
nmov      M,a       0011_000m_mmmm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   000_1111_mmmm_mmmm   00_0111_1mmm_mmmm
nadd      a,M       0011_011m_mmmm_mmmm   000_1110_mmmm_mmmm   00_0111_0mmm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
ceqsn     a,M       0011_101m_mmmm_mmmm   010_1110_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   000_1101_mmmm_mmmm   00_0110_1mmm_mmmm
comp      a,M       0011_111m_mmmm_mmmm   000_1100_mmmm_mmmm   00_0110_0mmm_mmmm
add       M,a       0100_000m_mmmm_mmmm   001_0000_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
add       a,M       0100_001m_mmmm_mmmm   001_1000_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   001_0001_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
sub       a,M       0100_011m_mmmm_mmmm   001_1001_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   001_0010_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
addc      a,M       0100_101m_mmmm_mmmm   001_1010_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   001_0011_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
subc      a,M       0100_111m_mmmm_mmmm   001_1011_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   001_0100_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
and       a,M       0101_001m_mmmm_mmmm   001_1100_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   001_0101_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
or        a,M       0101_011m_mmmm_mmmm   001_1101_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
xor       M,a       0101_100m_mmmm_mmmm   001_0110_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm
xor       a,M       0101_101m_mmmm_mmmm   001_1110_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
mov       M,a       0101_110m_mmmm_mmmm   001_0111_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mov       a,M       0101_111m_mmmm_mmmm   001_1111_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
addc      M         0110_000m_mmmm_mmmm   010_0000_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
subc      M         0110_001m_mmmm_mmmm   010_0001_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
izsn      M         0110_010m_mmmm_mmmm   010_0010_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
dzsn      M         0110_011m_mmmm_mmmm   010_0011_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
inc       M         0110_100m_mmmm_mmmm   010_0100_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
dec       M         0110_101m_mmmm_mmmm   010_0101_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
clear     M         0110_110m_mmmm_mmmm   010_0110_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
xch       M         0110_111m_mmmm_mmmm   010_0111_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
not       M         0111_000m_mmmm_mmmm   010_1000_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
neg       M         0111_001m_mmmm_mmmm   010_1001_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
sr        M         0111_010m_mmmm_mmmm   010_1010_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
sl        M         0111_011m_mmmm_mmmm   010_1011_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
src       M         0111_100m_mmmm_mmmm   010_1100_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
slc       M         0111_101m_mmmm_mmmm   010_1101_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
swap      M         0111_110m_mmmm_mmmm
delay     M         0111_111m_mmmm_mmmm
t0sn      M.n       1000_bbbm_mmmm_mmmm   100_00bb_bmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      M.n       1001_bbbm_mmmm_mmmm   100_01bb_bmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
set0      M.n       1010_bbbm_mmmm_mmmm   100_10bb_bmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      M.n       1011_bbbm_mmmm_mmmm   100_11bb_bmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
goto      label     110a_aaaa_aaaa_aaaa   110_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
call      label     111a_aaaa_aaaa_aaaa   111_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa


16/15/14/13 bit instruction encoding sorted by mnemonic
Code: [Select]
add       a,I       0001_1000_kkkk_kkkk   101_0000_kkkk_kkkk   10_1000_kkkk_kkkk   1_0000_kkkk_kkkk
add       a,M       0100_001m_mmmm_mmmm   001_1000_mmmm_mmmm   00_1100_0mmm_mmmm   0_0110_00mm_mmmm
add       M,a       0100_000m_mmmm_mmmm   001_0000_mmmm_mmmm   00_1000_0mmm_mmmm   0_0100_00mm_mmmm
addc      a         0000_0000_0001_0000   000_0000_0110_0000   00_0000_0110_0000   0_0000_0001_0000
addc      a,M       0100_101m_mmmm_mmmm   001_1010_mmmm_mmmm   00_1101_0mmm_mmmm   0_0110_10mm_mmmm
addc      M         0110_000m_mmmm_mmmm   010_0000_mmmm_mmmm   01_0000_0mmm_mmmm   0_1000_00mm_mmmm
addc      M,a       0100_100m_mmmm_mmmm   001_0010_mmmm_mmmm   00_1001_0mmm_mmmm   0_0100_10mm_mmmm
and       a,I       0001_1100_kkkk_kkkk   101_0100_kkkk_kkkk   10_1100_kkkk_kkkk   1_0100_kkkk_kkkk
and       a,M       0101_001m_mmmm_mmmm   001_1100_mmmm_mmmm   00_1110_0mmm_mmmm   0_0111_00mm_mmmm
and       M,a       0101_000m_mmmm_mmmm   001_0100_mmmm_mmmm   00_1010_0mmm_mmmm   0_0101_00mm_mmmm
call      label     111a_aaaa_aaaa_aaaa   111_aaaa_aaaa_aaaa   11_1aaa_aaaa_aaaa   1_11aa_aaaa_aaaa
ceqsn     a,I       0001_1010_kkkk_kkkk   101_0010_kkkk_kkkk   10_1010_kkkk_kkkk   1_0010_kkkk_kkkk
ceqsn     a,M       0011_101m_mmmm_mmmm   010_1110_mmmm_mmmm   01_0111_0mmm_mmmm   0_1011_10mm_mmmm
ceqsn     M,a       0011_100m_mmmm_mmmm
clear     M         0110_110m_mmmm_mmmm   010_0110_mmmm_mmmm   01_0011_0mmm_mmmm   0_1001_10mm_mmmm
cneqsn    a,I       0000_0001_kkkk_kkkk   101_0011_kkkk_kkkk   10_1011_kkkk_kkkk   1_0011_kkkk_kkkk
cneqsn    a,M       0001_011m_mmmm_mmmm   010_1111_mmmm_mmmm   01_0111_1mmm_mmmm   0_1011_11mm_mmmm
cneqsn    M,a       0001_010m_mmmm_mmmm
comp      a,I       0001_1011_kkkk_kkkk
comp      a,M       0011_111m_mmmm_mmmm   000_1100_mmmm_mmmm   00_0110_0mmm_mmmm
comp      M,a       0011_110m_mmmm_mmmm   000_1101_mmmm_mmmm   00_0110_1mmm_mmmm
dec       M         0110_101m_mmmm_mmmm   010_0101_mmmm_mmmm   01_0010_1mmm_mmmm   0_1001_01mm_mmmm
delay     a         0000_0000_0001_1111
delay     I         0000_1110_kkkk_kkkk
delay     M         0111_111m_mmmm_mmmm
disgint             0000_0000_0011_1001   000_0000_0111_1001   00_0000_0111_1001   0_0000_0011_1001
dzsn      a         0000_0000_0001_0011   000_0000_0110_0011   00_0000_0110_0011   0_0000_0001_0011
dzsn      M         0110_011m_mmmm_mmmm   010_0011_mmmm_mmmm   01_0001_1mmm_mmmm   0_1000_11mm_mmmm
engint              0000_0000_0011_1000   000_0000_0111_1000   00_0000_0111_1000   0_0000_0011_1000
goto      label     110a_aaaa_aaaa_aaaa   110_aaaa_aaaa_aaaa   11_0aaa_aaaa_aaaa   1_10aa_aaaa_aaaa
icall     word      0000_011w_wwww_www1
idxm      a,index   0000_100w_wwww_www1   000_0111_wwww_www1   00_0011_1www_www1   0_0000_111w_www1
idxm      index,a   0000_100w_wwww_www0   000_0111_wwww_www0   00_0011_1www_www0   0_0000_111w_www0
igoto     word      0000_011w_wwww_www0
inc       M         0110_100m_mmmm_mmmm   010_0100_mmmm_mmmm   01_0010_0mmm_mmmm   0_1001_00mm_mmmm
izsn      a         0000_0000_0001_0010   000_0000_0110_0010   00_0000_0110_0010   0_0000_0001_0010
izsn      M         0110_010m_mmmm_mmmm   010_0010_mmmm_mmmm   01_0001_0mmm_mmmm   0_1000_10mm_mmmm
ldspth                                                         00_0000_0000_0111
ldsptl                                                         00_0000_0000_0110
ldt16     word      0000_001w_wwww_www1   000_0110_wwww_www1   00_0011_0www_www1   0_0000_110w_www1
ldtabh    word      0000_101w_wwww_www1   000_0101_wwww_www1
ldtabl    word      0000_101w_wwww_www0   000_0101_wwww_www0
mov       a,I       0001_1111_kkkk_kkkk   101_0111_kkkk_kkkk   10_1111_kkkk_kkkk   1_0111_kkkk_kkkk
mov       a,IO      0000_0000_11pp_pppp   000_0001_1ppp_pppp   00_0001_11pp_pppp   0_0000_101p_pppp
mov       a,M       0101_111m_mmmm_mmmm   001_1111_mmmm_mmmm   00_1111_1mmm_mmmm   0_0111_11mm_mmmm
mov       IO,a      0000_0000_10pp_pppp   000_0001_0ppp_pppp   00_0001_10pp_pppp   0_0000_100p_pppp
mov       M,a       0101_110m_mmmm_mmmm   001_0111_mmmm_mmmm   00_1011_1mmm_mmmm   0_0101_11mm_mmmm
mul                 0000_0000_0011_1100   000_0000_0111_1100   00_0000_0111_1100
nadd      a,M       0011_011m_mmmm_mmmm   000_1110_mmmm_mmmm   00_0111_0mmm_mmmm
nadd      M,a       0011_010m_mmmm_mmmm   000_1111_mmmm_mmmm   00_0111_1mmm_mmmm
neg       a         0000_0000_0001_1001   000_0000_0110_1001   00_0000_0110_1001   0_0000_0001_1001
neg       M         0111_001m_mmmm_mmmm   010_1001_mmmm_mmmm   01_0100_1mmm_mmmm   0_1010_01mm_mmmm
nmov      a,M       0011_001m_mmmm_mmmm
nmov      M,a       0011_000m_mmmm_mmmm
nop                 0000_0000_0000_0000   000_0000_0000_0000   00_0000_0000_0000   0_0000_0000_0000
not       a         0000_0000_0001_1000   000_0000_0110_1000   00_0000_0110_1000   0_0000_0001_1000
not       M         0111_000m_mmmm_mmmm   010_1000_mmmm_mmmm   01_0100_0mmm_mmmm   0_1010_00mm_mmmm
or        a,I       0001_1101_kkkk_kkkk   101_0101_kkkk_kkkk   10_1101_kkkk_kkkk   1_0101_kkkk_kkkk
or        a,M       0101_011m_mmmm_mmmm   001_1101_mmmm_mmmm   00_1110_1mmm_mmmm   0_0111_01mm_mmmm
or        M,a       0101_010m_mmmm_mmmm   001_0101_mmmm_mmmm   00_1010_1mmm_mmmm   0_0101_01mm_mmmm
pcadd     a         0000_0000_0001_0111   000_0000_0110_0111   00_0000_0110_0111   0_0000_0001_0111
pmode     n         0000_0000_010k_kkkk
popaf               0000_0000_0011_0011   000_0000_0111_0011   00_0000_0111_0011   0_0000_0011_0011
popw      pcN       0000_0000_0110_tttt
popw      word      0000_010w_wwww_www0
pushaf              0000_0000_0011_0010   000_0000_0111_0010   00_0000_0111_0010   0_0000_0011_0010
pushw     pcN       0000_0000_0111_tttt
pushw     word      0000_010w_wwww_www1
reset               0000_0000_0011_0101   000_0000_0111_0101   00_0000_0111_0101   0_0000_0011_0101
ret                 0000_0000_0011_1010   000_0000_0111_1010   00_0000_0111_1010   0_0000_0011_1010
ret       I         0000_1111_kkkk_kkkk   000_0010_kkkk_kkkk   00_0010_kkkk_kkkk   0_0001_kkkk_kkkk
reti                0000_0000_0011_1011   000_0000_0111_1011   00_0000_0111_1011   0_0000_0011_1011
set0      IO.n      0010_010b_bbpp_pppp   011_10bb_bppp_pppp   01_110b_bbpp_pppp   0_1110_bbbp_pppp
set0      M.n       1010_bbbm_mmmm_mmmm   100_10bb_bmmm_mmmm   10_010b_bbmm_mmmm   0_0011_bbb0_mmmm
set1      IO.n      0010_011b_bbpp_pppp   011_11bb_bppp_pppp   01_111b_bbpp_pppp   0_1111_bbbp_pppp
set1      M.n       1011_bbbm_mmmm_mmmm   100_11bb_bmmm_mmmm   10_011b_bbmm_mmmm   0_0011_bbb1_mmmm
sl        a         0000_0000_0001_1011   000_0000_0110_1011   00_0000_0110_1011   0_0000_0001_1011
sl        M         0111_011m_mmmm_mmmm   010_1011_mmmm_mmmm   01_0101_1mmm_mmmm   0_1010_11mm_mmmm
slc       a         0000_0000_0001_1101   000_0000_0110_1101   00_0000_0110_1101   0_0000_0001_1101
slc       M         0111_101m_mmmm_mmmm   010_1101_mmmm_mmmm   01_0110_1mmm_mmmm   0_1011_01mm_mmmm
sr        a         0000_0000_0001_1010   000_0000_0110_1010   00_0000_0110_1010   0_0000_0001_1010
sr        M         0111_010m_mmmm_mmmm   010_1010_mmmm_mmmm   01_0101_0mmm_mmmm   0_1010_10mm_mmmm
src       a         0000_0000_0001_1100   000_0000_0110_1100   00_0000_0110_1100   0_0000_0001_1100
src       M         0111_100m_mmmm_mmmm   010_1100_mmmm_mmmm   01_0110_0mmm_mmmm   0_1011_00mm_mmmm
stopexe             0000_0000_0011_0111   000_0000_0111_0111   00_0000_0111_0111   0_0000_0011_0111
stopsys             0000_0000_0011_0110   000_0000_0111_0110   00_0000_0111_0110   0_0000_0011_0110
stt16     word      0000_001w_wwww_www0   000_0110_wwww_www0   00_0011_0www_www0   0_0000_110w_www0
sub       a,I       0001_1001_kkkk_kkkk   101_0001_kkkk_kkkk   10_1001_kkkk_kkkk   1_0001_kkkk_kkkk
sub       a,M       0100_011m_mmmm_mmmm   001_1001_mmmm_mmmm   00_1100_1mmm_mmmm   0_0110_01mm_mmmm
sub       M,a       0100_010m_mmmm_mmmm   001_0001_mmmm_mmmm   00_1000_1mmm_mmmm   0_0100_01mm_mmmm
subc      a         0000_0000_0001_0001   000_0000_0110_0001   00_0000_0110_0001   0_0000_0001_0001
subc      a,M       0100_111m_mmmm_mmmm   001_1011_mmmm_mmmm   00_1101_1mmm_mmmm   0_0110_11mm_mmmm
subc      M         0110_001m_mmmm_mmmm   010_0001_mmmm_mmmm   01_0000_1mmm_mmmm   0_1000_01mm_mmmm
subc      M,a       0100_110m_mmmm_mmmm   001_0011_mmmm_mmmm   00_1001_1mmm_mmmm   0_0100_11mm_mmmm
swap      a         0000_0000_0001_1110   000_0000_0110_1110   00_0000_0110_1110   0_0000_0001_1110
swap      M         0111_110m_mmmm_mmmm
swapc     IO.n      0010_111b_bbpp_pppp   101_11bb_bppp_pppp   00_010b_bbpp_pppp
t0sn      IO.n      0010_000b_bbpp_pppp   011_00bb_bppp_pppp   01_100b_bbpp_pppp   0_1100_bbbp_pppp
t0sn      M.n       1000_bbbm_mmmm_mmmm   100_00bb_bmmm_mmmm   10_000b_bbmm_mmmm   0_0010_bbb0_mmmm
t1sn      IO.n      0010_001b_bbpp_pppp   011_01bb_bppp_pppp   01_101b_bbpp_pppp   0_1101_bbbp_pppp
t1sn      M.n       1001_bbbm_mmmm_mmmm   100_01bb_bmmm_mmmm   10_001b_bbmm_mmmm   0_0010_bbb1_mmmm
tog       IO.n      0010_100b_bbpp_pppp
wait0     IO.n      0010_101b_bbpp_pppp
wait1     IO.n      0010_110b_bbpp_pppp
wdreset             0000_0000_0011_0000   000_0000_0111_0000   00_0000_0111_0000   0_0000_0011_0000
xch       M         0110_111m_mmmm_mmmm   010_0111_mmmm_mmmm   01_0011_1mmm_mmmm   0_1001_11mm_mmmm
xor       a,I       0001_1110_kkkk_kkkk   101_0110_kkkk_kkkk   10_1110_kkkk_kkkk   1_0110_kkkk_kkkk
xor       a,IO      0001_0000_01pp_pppp
xor       a,M       0101_101m_mmmm_mmmm   001_1110_mmmm_mmmm   00_1111_0mmm_mmmm   0_0111_10mm_mmmm
xor       IO,a      0001_0000_00pp_pppp   000_0000_1ppp_pppp   00_0000_11pp_pppp   0_0000_011p_pppp
xor       M,a       0101_100m_mmmm_mmmm   001_0110_mmmm_mmmm   00_1011_0mmm_mmmm   0_0101_10mm_mmmm

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 03, 2018, 08:30:32 pm

On the second day, wrt. completeness of implementation of the C standard, this has now far surpassed Mini-C.


Well done! Seems to be doing its job.

Code: [Select]
unsigned int a = 15;
unsigned int b = 23;
unsigned int c;

void
main( void ) {
while (c < a * b) {
c += a;
}
}

Weird: The compiler doesnt seem to realize that a*b will always be constant (even if I declare both variables as const and they land in the const segment).
Is that an optimization step?

Code: [Select]
...
_main:
; test.c: 7: while (c < a * b) {
00101$:
mov a, _a+0
mov __mulint_PARM_1+0, a
mov a, _a+1
mov __mulint_PARM_1+1, a
mov a, _b+0
mov __mulint_PARM_2+0, a
mov a, _b+1
mov __mulint_PARM_2+1, a
call __mulint
mov _main_sloc0_1_0+0, a
mov a, p
mov _main_sloc0_1_0+1, a
mov a, _c+0
sub a, _main_sloc0_1_0+0
mov a, _c+1
subc a, _main_sloc0_1_0+1
mov a, #0x00
slc a
mov _main_sloc1_1_0+0, a
mov a, _main_sloc1_1_0+0
cneqsn a, #0x00
goto 00104$
; test.c: 8: c += a;
mov a, _c+0
add a, _a+0
mov _c+0, a
mov a, _c+1
addc a, _a+1
mov _c+1, a
goto 00101$
00104$:
; test.c: 10: }
ret
...
__xinit__a:
.dw #0x000f
__xinit__b:
.dw #0x0017

Although init code seems to be missing and I get lot of this:

Code: [Select]
test.asm:60: Error: <a> machine specific addressing or addressing mode error
test.asm:61: Error: <a> machine specific addressing or addressing mode error
test.asm:62: Error: <a> machine specific addressing or addressing mode error
test.asm:63: Error: <a> machine specific addressing or addressing mode error
test.asm:64: Error: <a> machine specific addressing or addressing mode error
test.asm:65: Error: <a> machine specific addressing or addressing mode error
test.asm:66: Error: <a> machine specific addressing or addressing mode error
test.asm:67: Error: <a> machine specific addressing or addressing mode error
test.asm:69: Error: <a> machine specific addressing or addressing mode error
test.asm:70: Error: <a> machine specific addressing or addressing mode error
test.asm:71: Error: <a> machine specific addressing or addressing mode error
test.asm:72: Error: <a> machine specific addressing or addressing mode error
test.asm:74: Error: <a> machine specific addressing or addressing mode error
test.asm:75: Error: <o> .org in REL area or directive / mnemonic error
test.asm:76: Error: <a> machine specific addressing or addressing mode error
test.asm:77: Error: <o> .org in REL area or directive / mnemonic error
test.asm:78: Error: <a> machine specific addressing or addressing mode error
test.asm:79: Error: <a> machine specific addressing or addressing mode error
test.asm:80: Error: <o> .org in REL area or directive / mnemonic error
test.asm:81: Error: <q> missing or improper operators, terminators, or delimiters
test.asm:83: Error: <a> machine specific addressing or addressing mode error
test.asm:85: Error: <a> machine specific addressing or addressing mode error
test.asm:86: Error: <a> machine specific addressing or addressing mode error
test.asm:87: Error: <o> .org in REL area or directive / mnemonic error
test.asm:88: Error: <a> machine specific addressing or addressing mode error
test.asm:89: Error: <q> missing or improper operators, terminators, or delimiters
removing test.rel
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 04, 2018, 04:14:49 am
PFS173 startup code

Edit: fixed disassembler bug that caused IO addresses > 63 to be incorrect, and all bit addresses to be incorrect

Code: [Select]
PDK version: 20
PDK data size:  3072 words
Free data size: 3040 words
MCU: PFS173 [ID: 0x2AA2]
Compiler version: 0.84
15 bit core
0000  5700  mov       a, 0x00
0001  0102  mov       SP, a
0002  7BED  call      0x0BED
0003  010B  mov       IHRCR, a
0004  7BEE  call      0x0BEE
0005  0163  mov       BGTR, a
0006  5770  mov       a, 0x70
0007  0128  mov       MISC_LVR, a
0008  573C  mov       a, 0x3C
0009  0103  mov       CLKCMD, a
000A  57F9  mov       a, 0xF9
000B  010D  mov       PADIER, a
000C  57FF  mov       a, 0xFF
000D  010E  mov       PBDIER, a
000E  570F  mov       a, 0x0F
000F  010F  mov       PCDIER, a
0010  5700  mov       a, 0x00
0011  0167  mov       ROP, a
0012  7BFE  call      0x0BFE
0013  52FF  ceqsn     a, 0xFF
0014  6059  goto      0x0059
0015  7BED  call      0x0BED
0016  1701  mov       M1, a
0017  3F11  set1      PAC.6
0018  5709  mov       a, 0x09
0019  1700  mov       M0, a
001A  3590  t1sn      PA.3
001B  601A  goto      0x001A
001C  3F10  set1      PA.6
001D  0063  dzsn      a
001E  601D  goto      0x001D
001F  2300  dzsn      M0
0020  601D  goto      0x001D
0021  3B10  set0      PA.6
0022  3190  t0sn      PA.3
0023  6022  goto      0x0022
0024  5701  mov       a, 0x01
0025  3290  t0sn      PA.5
0026  57FF  mov       a, 0xFF
0027  1801  add       a, M1
0028  010B  mov       IHRCR, a
0029  1701  mov       M1, a
002A  3590  t1sn      PA.3
002B  602A  goto      0x002A
002C  3690  t1sn      PA.5
002D  6054  goto      0x0054
002E  5704  mov       a, 0x04
002F  0126  mov       MISC, a
0030  3190  t0sn      PA.3
0031  6030  goto      0x0030
0032  2604  clear     M4
0033  2605  clear     M5
0034  575A  mov       a, 0x5A
0035  1702  mov       M2, a
0036  5700  mov       a, 0x00
0037  1703  mov       M3, a
0038  0502  ldtabl    M2
0039  1604  xor       M4, a
003A  0503  ldtabh    M2
003B  1005  add       M5, a
003C  2B04  sl        M4
003D  2D05  slc       M5
003E  2004  addc      M4
003F  2502  dec       M2
0040  2103  subc      M3
0041  3480  t1sn      FLAG.C
0042  6038  goto      0x0038
0043  3F10  set1      PA.6
0044  3590  t1sn      PA.3
0045  6044  goto      0x0044
0046  2B04  sl        M4
0047  2D05  slc       M5
0048  5F10  swapc     PA.6
0049  3190  t0sn      PA.3
004A  6049  goto      0x0049
004B  3290  t0sn      PA.5
004C  6044  goto      0x0044
004D  3B10  set0      PA.6
004E  3590  t1sn      PA.3
004F  604E  goto      0x004E
0050  3190  t0sn      PA.3
0051  6050  goto      0x0050
0052  3690  t1sn      PA.5
0053  6032  goto      0x0032
0054  3190  t0sn      PA.3
0055  6054  goto      0x0054
0056  3690  t1sn      PA.5
0057  6018  goto      0x0018
0058  6058  goto      0x0058
0059  010B  mov       IHRCR, a
005A  605A  goto      0x005A
005B  7FFF  call      0x0FFF
005C  7FFF  call      0x0FFF
005D  7FFF  call      0x0FFF
005E  7FFF  call      0x0FFF
005F  7FFF  call      0x0FFF
0060  7FFF  call      0x0FFF
...
0BE0  7FFF  call      0x0FFF
0BE1  7FFF  call      0x0FFF
0BE2  7FFF  call      0x0FFF
0BE3  7FFF  call      0x0FFF
0BE4  7FFF  call      0x0FFF
0BE5  7FFF  call      0x0FFF
0BE6  7FFF  call      0x0FFF
0BE7  7FFF  call      0x0FFF
0BE8  7FFF  call      0x0FFF
0BE9  7FFF  call      0x0FFF
0BEA  7FFF  call      0x0FFF
0BEB  7FFF  call      0x0FFF
0BEC  7FFF  call      0x0FFF
0BED  7FFF  call      0x0FFF
0BEE  7FFF  call      0x0FFF
0BEF  3FFE  set1      io.126.7
0BF0  7FFF  call      0x0FFF
0BF1  7FFF  call      0x0FFF
0BF2  7FFF  call      0x0FFF
0BF3  7FFF  call      0x0FFF
0BF4  7FFF  call      0x0FFF
0BF5  7FFF  call      0x0FFF
0BF6  7FFF  call      0x0FFF
0BF7  7FFF  call      0x0FFF
0BF8  0000  nop
0BF9  0000  nop
0BFA  7FFF  call      0x0FFF
0BFB  7FFF  call      0x0FFF
0BFC  7FFF  call      0x0FFF
0BFD  7FFF  call      0x0FFF
0BFE  7FFF  call      0x0FFF
0BFF  7AFC  call      0x0AFC
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 04, 2018, 07:16:17 am
Now that the software side seems on track, how about some hardware engineering?

It should be possible to program the chips with xFFF so they stay fresh and useable.
Just for a quick peek at what the programmer does.
We should now be able to distinguish between the programming phase and the bit-banged calibration.
Maybe start with the PFS154 (dont have a programmer, I do have an arduino ;)? I have some of those and I suspect that reprogrammable chips are most interesting at this stage.

Or maybe analyse the bitstream from the Cypress chip to the FPGA on the ICE so we can understand what chip is being used?
Or even simpler: take the FPGA out and see whether the ICE even notices ;)

Anyone?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 04, 2018, 09:58:45 am
Although init code seems to be missing and I get lot of this:

Code: [Select]
test.asm:60: Error: <a> machine specific addressing or addressing mode error
[…]

You can compile to asm using -S to avoid those error messages (without -S, SDCC tries to invoke an Assembler, which currently happens to be one for STM8).

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 04, 2018, 12:51:04 pm
Ok, with that the error messages are now

Code: [Select]


Nice  :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 04, 2018, 12:54:14 pm
Now that the software side seems on track, how about some hardware engineering?

It should be possible to program the chips with xFFF so they stay fresh and useable.
Just for a quick peek at what the programmer does.
We should now be able to distinguish between the programming phase and the bit-banged calibration.

Currently I'm designing a 4 channel (optionally 8 channel) ADC with at least 10 MHz sample rate and 1 GB RAM:

https://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/ (https://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/)

Parts are ordered, I just need to layout it and order the PCB, then write the software for the DE10 Nano for it. Might need a few weeks, but then I can sample a full programming cycle with all pins in parallel. This should make it much easier to reverse engineer the exact protocol and to reproduce it. The software should be no problem, I've done this before (http://www.frank-buss.de/parallella/sampler/).
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 04, 2018, 01:38:17 pm
I ran the regression tests in sdcc/src/regression and most of them seem to run fine.
Sometimes there are "FATAL Compiler Internal Error" that are specfic to the pdk14 backend

find -iname \*\.c -exec sh -c "echo {} ; sdcc -S -mpdk14 {}" \;

Code: [Select]
./switch1.c
./rotate6.c
./rotate6.c:86: warning 94: comparison is always true due to limited range of data type
./rotate6.c:84: warning 158: overflow in implicit constant conversion
./rotate6.c:121: warning 158: overflow in implicit constant conversion
./compare3.c
./compare3.c:151: warning 94: comparison is always false due to limited range of data type
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:173: warning 94: comparison is always false due to limited range of data type
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./rotate1.c
./compare7.c
In file included from ./compare7.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./compare5.c
./compare5.c:219: warning 94: comparison is always false due to limited range of data type
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:242: warning 94: comparison is always false due to limited range of data type
./compare5.c:271: warning 94: comparison is always false due to limited range of data type
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare6.c
Backtrace:
sdcc(+0xa4bce)[0x55b8eaabbbce]
sdcc(+0x1d73a7)[0x55b8eabee3a7]
sdcc(+0x1d7946)[0x55b8eabee946]
sdcc(+0x1d9c1e)[0x55b8eabf0c1e]
sdcc(+0x1d671e)[0x55b8eabed71e]
sdcc(+0x3c35c)[0x55b8eaa5335c]
sdcc(+0x568b0)[0x55b8eaa6d8b0]
sdcc(+0x1fe9f)[0x55b8eaa36e9f]
sdcc(+0x1be86)[0x55b8eaa32e86]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7fde56ffdb97]
sdcc(+0x1d7aa)[0x55b8eaa347aa]
./compare6.c:165: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '265' : code generator internal error
Contact Author with source code
Caught signal 11: SIGSEGV
./bool2.c
./nestfor.c
In file included from ./nestfor.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./pcodeopt.c
./struct1.c
./compare8.c
In file included from ./compare8.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate3.c
./ptrarg.c
./add3.c
./add3.c:64: warning 94: comparison is always true due to limited range of data type
./rotate2.c
./call1.c
./bool1.c
./compare4.c
./compare4.c:63: warning 94: comparison is always false due to limited range of data type
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:93: warning 94: comparison is always false due to limited range of data type
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:250: warning 94: comparison is always true due to limited range of data type
./compare4.c:294: warning 158: overflow in implicit constant conversion
./compare4.c:304: warning 158: overflow in implicit constant conversion
./compare4.c:313: warning 158: overflow in implicit constant conversion
./rotate4.c
./rotate4.c:30: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '1520' : Unimplemented iCode
Contact Author with source code
./add2.c
./compare10.c
In file included from ./compare10.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./inline.c
In file included from ./inline.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate5.c
./rotate5.c:179: warning 158: overflow in implicit constant conversion
./rotate5.c:205: warning 158: overflow in implicit constant conversion
./rotate5.c:206: warning 158: overflow in implicit constant conversion
./rotate5.c:209: warning 158: overflow in implicit constant conversion
./rotate5.c:210: warning 158: overflow in implicit constant conversion
./rotate5.c:213: warning 158: overflow in implicit constant conversion
./rotate5.c:216: warning 158: overflow in implicit constant conversion
./rotate5.c:219: warning 158: overflow in implicit constant conversion
./rotate5.c:222: warning 158: overflow in implicit constant conversion
./rotate5.c:225: warning 158: overflow in implicit constant conversion
./rotate5.c:228: warning 158: overflow in implicit constant conversion
./rotate5.c:229: warning 158: overflow in implicit constant conversion
./bool3.c
./string1.c
In file included from ./string1.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./xor.c
./compare.c
./compare9.c
In file included from ./compare9.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./for.c
./for.c:37: error 226: no type specifier for '(cast)'
./add4.c
./add.c
./pointer1.c
./and1.c
./and2.c
./b.c
./ptrfunc.c
./ptrfunc.c:47: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '516' : Unimplemented call through function pointer
Contact Author with source code
./compare2.c
./mult1.c
./sub.c
./rotate7.c
./rotate7.c:206: warning 158: overflow in implicit constant conversion
./rotate7.c:212: warning 158: overflow in implicit constant conversion
./rotate7.c:218: warning 158: overflow in implicit constant conversion
./rotate7.c:224: warning 158: overflow in implicit constant conversion
./rotate7.c:230: warning 158: overflow in implicit constant conversion
./rotate7.c:236: warning 158: overflow in implicit constant conversion
./rotate7.c:242: warning 158: overflow in implicit constant conversion
./rotate7.c:248: warning 158: overflow in implicit constant conversion
./rotate7.c:254: warning 158: overflow in implicit constant conversion
./rotate7.c:260: warning 158: overflow in implicit constant conversion
./rotate7.c:266: warning 158: overflow in implicit constant conversion
./rotate7.c:272: warning 158: overflow in implicit constant conversion
./rotate7.c:278: warning 158: overflow in implicit constant conversion
./rotate7.c:284: warning 158: overflow in implicit constant conversion
./rotate7.c:290: warning 158: overflow in implicit constant conversion
./rotate7.c:297: warning 158: overflow in implicit constant conversion
./rotate7.c:303: warning 158: overflow in implicit constant conversion
./rotate7.c:309: warning 158: overflow in implicit constant conversion
./rotate7.c:315: warning 158: overflow in implicit constant conversion
./rotate7.c:321: warning 158: overflow in implicit constant conversion
./rotate7.c:327: warning 158: overflow in implicit constant conversion
./rotate7.c:333: warning 158: overflow in implicit constant conversion
./rotate7.c:339: warning 158: overflow in implicit constant conversion
./rotate7.c:345: warning 158: overflow in implicit constant conversion
./rotate7.c:351: warning 158: overflow in implicit constant conversion
./rotate7.c:357: warning 158: overflow in implicit constant conversion
./rotate7.c:363: warning 158: overflow in implicit constant conversion
./rotate7.c:369: warning 158: overflow in implicit constant conversion
./rotate7.c:375: warning 158: overflow in implicit constant conversion
./rotate7.c:381: warning 158: overflow in implicit constant conversion
./init0.c
./init0.c:43: error 9: FATAL Compiler Internal Error in file 'gen.c' line number '516' : Unimplemented call through function pointer
Contact Author with source code
./while.c
./empty.c
./arrays.c
./or1.c
./sub2.c
./sub2.c:162: warning 158: overflow in implicit constant conversion
./configword.c
In file included from ./configword.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./bank1.c
./bank1.c:20: error 9: FATAL Compiler Internal Error in file 'SDCCmem.c' line number '385' : code generator internal error
Contact Author with source code
Caught signal 11: SIGSEGV


find -iname \*\.c -exec sh -c "echo {} ; sdcc -S -mmcs51 {}" \;

Code: [Select]
./switch1.c
./rotate6.c
./rotate6.c:86: warning 94: comparison is always true due to limited range of data type
./rotate6.c:84: warning 158: overflow in implicit constant conversion
./rotate6.c:121: warning 158: overflow in implicit constant conversion
./compare3.c
./compare3.c:151: warning 94: comparison is always false due to limited range of data type
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:152: warning 126: unreachable code
./compare3.c:173: warning 94: comparison is always false due to limited range of data type
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./compare3.c:174: warning 126: unreachable code
./rotate1.c
./compare7.c
In file included from ./compare7.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./compare5.c
./compare5.c:219: warning 94: comparison is always false due to limited range of data type
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:220: warning 126: unreachable code
./compare5.c:242: warning 94: comparison is always false due to limited range of data type
./compare5.c:271: warning 94: comparison is always false due to limited range of data type
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:243: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare5.c:272: warning 126: unreachable code
./compare6.c
./bool2.c
./nestfor.c
In file included from ./nestfor.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./pcodeopt.c
./struct1.c
./compare8.c
In file included from ./compare8.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate3.c
./ptrarg.c
./add3.c
./add3.c:64: warning 94: comparison is always true due to limited range of data type
./rotate2.c
./call1.c
./bool1.c
./compare4.c
./compare4.c:63: warning 94: comparison is always false due to limited range of data type
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:64: warning 126: unreachable code
./compare4.c:93: warning 94: comparison is always false due to limited range of data type
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:94: warning 126: unreachable code
./compare4.c:250: warning 94: comparison is always true due to limited range of data type
./compare4.c:294: warning 158: overflow in implicit constant conversion
./compare4.c:304: warning 158: overflow in implicit constant conversion
./compare4.c:313: warning 158: overflow in implicit constant conversion
./rotate4.c
./add2.c
./compare10.c
In file included from ./compare10.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./inline.c
In file included from ./inline.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./rotate5.c
./rotate5.c:179: warning 158: overflow in implicit constant conversion
./rotate5.c:205: warning 158: overflow in implicit constant conversion
./rotate5.c:206: warning 158: overflow in implicit constant conversion
./rotate5.c:209: warning 158: overflow in implicit constant conversion
./rotate5.c:210: warning 158: overflow in implicit constant conversion
./rotate5.c:213: warning 158: overflow in implicit constant conversion
./rotate5.c:216: warning 158: overflow in implicit constant conversion
./rotate5.c:219: warning 158: overflow in implicit constant conversion
./rotate5.c:222: warning 158: overflow in implicit constant conversion
./rotate5.c:225: warning 158: overflow in implicit constant conversion
./rotate5.c:228: warning 158: overflow in implicit constant conversion
./rotate5.c:229: warning 158: overflow in implicit constant conversion
./bool3.c
./string1.c
In file included from ./string1.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./xor.c
./compare.c
./compare9.c
In file included from ./compare9.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./for.c
./for.c:37: error 226: no type specifier for '(cast)'
./add4.c
./add.c
./pointer1.c
./and1.c
./and2.c
./b.c
./ptrfunc.c
./compare2.c
./mult1.c
./sub.c
./rotate7.c
./rotate7.c:206: warning 158: overflow in implicit constant conversion
./rotate7.c:212: warning 158: overflow in implicit constant conversion
./rotate7.c:218: warning 158: overflow in implicit constant conversion
./rotate7.c:224: warning 158: overflow in implicit constant conversion
./rotate7.c:230: warning 158: overflow in implicit constant conversion
./rotate7.c:236: warning 158: overflow in implicit constant conversion
./rotate7.c:242: warning 158: overflow in implicit constant conversion
./rotate7.c:248: warning 158: overflow in implicit constant conversion
./rotate7.c:254: warning 158: overflow in implicit constant conversion
./rotate7.c:260: warning 158: overflow in implicit constant conversion
./rotate7.c:266: warning 158: overflow in implicit constant conversion
./rotate7.c:272: warning 158: overflow in implicit constant conversion
./rotate7.c:278: warning 158: overflow in implicit constant conversion
./rotate7.c:284: warning 158: overflow in implicit constant conversion
./rotate7.c:290: warning 158: overflow in implicit constant conversion
./rotate7.c:297: warning 158: overflow in implicit constant conversion
./rotate7.c:303: warning 158: overflow in implicit constant conversion
./rotate7.c:309: warning 158: overflow in implicit constant conversion
./rotate7.c:315: warning 158: overflow in implicit constant conversion
./rotate7.c:321: warning 158: overflow in implicit constant conversion
./rotate7.c:327: warning 158: overflow in implicit constant conversion
./rotate7.c:333: warning 158: overflow in implicit constant conversion
./rotate7.c:339: warning 158: overflow in implicit constant conversion
./rotate7.c:345: warning 158: overflow in implicit constant conversion
./rotate7.c:351: warning 158: overflow in implicit constant conversion
./rotate7.c:357: warning 158: overflow in implicit constant conversion
./rotate7.c:363: warning 158: overflow in implicit constant conversion
./rotate7.c:369: warning 158: overflow in implicit constant conversion
./rotate7.c:375: warning 158: overflow in implicit constant conversion
./rotate7.c:381: warning 158: overflow in implicit constant conversion
./init0.c
./while.c
./empty.c
./arrays.c
./or1.c
./sub2.c
./sub2.c:162: warning 158: overflow in implicit constant conversion
./configword.c
In file included from ./configword.c:2:
./picregs.h:6:25: fatal error: pic14regs.h: No such file or directory
compilation terminated.
./picregs.h:1: warning 190: ISO C forbids an empty source file
./bank1.c
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 04, 2018, 03:08:49 pm
Might need a few weeks, but then I can sample a full programming cycle with all pins in parallel.

Yeah, I was rather hoping someone would be in for something quick & dirty   :-DD
(Just so you get me right I think its great and well worth it in the long run, but to keep things moving something more light weight might be what we need right now)

My theory (as pointed out by others as well and assuming the chip is reasonably akin to something like the old pics is that:

The first voltage spike + shoulder selects a programming mode of some sort.
Then you would send a short command/address and maybe some data.

Code: [Select]
         |\
         |  \
         |   \______   _______
         |          | |       |
         |          |_|       | .........

         |- select -||-----command / data-----   
             mode

My hope is that no very long duration is needed for signal analysis but just the very few first cycles.
That would be enough to start getting an arduino to do the same and see what happens  :popcorn:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 04, 2018, 04:26:09 pm
A good starting point to see what I mean might be this datasheet for old PIC16C7XX OTPs
(although the padauks will probably behave differently I guess its reasonable to assume for now that their approach is similar)

http://ww1.microchip.com/downloads/en/DeviceDoc/30298d.pdf (http://ww1.microchip.com/downloads/en/DeviceDoc/30298d.pdf)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 04, 2018, 08:03:34 pm
The remark "Please notice that bit 0 should be kept 0 due to program counter is 16 bits" in the datasheets seems odd to me. Any idea, what this could be about? Would anything break if I place the stack at an odd address? Do push / pop / call / ret require the stack pointer to be aligned?

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 04, 2018, 08:42:37 pm
The remark "Please notice that bit 0 should be kept 0 due to program counter is 16 bits" in the datasheets seems odd to me. Any idea, what this could be about? Would anything break if I place the stack at an odd address? Do push / pop / call / ret require the stack pointer to be aligned?

Philipp


Well it says "should be" not "must be". Hard to tell without an actual device or the ICE.

Depends on how they implemented the actual logic.
If it just takes the MSBs and toggles the last bit, then placing it an odd address will give you the byte in front of it.
Could make sense if you dont want to add the one. Probably makes sense because it saves space on the die (you'd have to do some arithmetic to get the result right otherwise)

consider this: you place sp at 0x3f then sp+1 is 0x40
You need to add an 7 bit adder for that (if I counted that right) thats significantly more computationally intensive (ie more die space) than toggle bit 0. Can all be done, by utilising the ALU for example but then speed is an issue, so I guess they dont.

looking at the datasheets again they might actually do a single cycle 16-bit access ie. ignore the lowest bit entirely
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 04, 2018, 11:44:36 pm
I interpret this to mean that the RAM is word accessible only on word boundaries. Bit 0 of SP must be 0 to ensure word alignment. This implies that push/pop af will use a word of stack instead of a byte.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ali_asadzadeh on December 05, 2018, 05:54:09 am
I think if you could revers the programmer too, it would be like heaven! ;) ;)

Guys Thanks for the great work and collaboration. :) :-+ :-+ :-+
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 07:01:41 am
I interpret this to mean that the RAM is word accessible only on word boundaries. Bit 0 of SP must be 0 to ensure word alignment. This implies that push/pop af will use a word of stack instead of a byte.

pushaf/popaf always use a word hence the +2

Result:        [sp] ← {flag, ACC};
sp ← sp + 2 ;

I guess they optimized this for call/ret which need 16/15/14/13 bit and not just a byte.
And other instructions then just use the same mechanism that is already in place.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 05, 2018, 08:20:13 am
Another question on push af  would be which one of a and f goes into the lower address.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 09:04:03 am
Another question on push af  would be which one of a and f goes into the lower address.

Philipp


Doesnt really matter does it?

If you implement pushaf and popaf symetrically for an emulator there will be no difference.
A isn't used as return value (thats the whole point of pushing it).
Unless youre trying to expicitly modify A or the flags on the stack there is absolutely no difference. They are designed to be atomic operations.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 05, 2018, 09:12:54 am
Another question on push af  would be which one of a and f goes into the lower address.

Philipp


Doesnt really matter does it?

If you implement pushaf and popaf symetrically for an emulator there will be no difference.
A isn't used as return value (thats the whole point of pushing it).
Unless youre trying to expicitly modify A or the flags on the stack there is absolutely no difference. They are designed to be atomic operations.

It matters: Pushing data on the stack has its uses. E.g. for a call via a function pointer:

Code: [Select]
pushw #retlabel
pushw funcptr
ret
retlabel:

To emulate one pushw (which is not available on most devices) 8 instructions are generated by SDCC (p is a pseudoregister in RAM):

Code: [Select]
ld a, sp
ld p, a
push af
ld a, op0
idxm p, a
inc p
ld a, op1
idxm p, a

That could obviously be brought down to 6 or 7 (depending on which byte a goes in on push af).

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 05, 2018, 10:06:57 am
Updated disassembler with 15 bit instruction set support.

Linux and Windows binaries included.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 10:16:51 am

That could obviously be brought down to 6 or 7 (depending on which byte a goes in on push af).

Philipp

I dont quite understand why there is pushaf at all (I assume ld = mov)


Code: [Select]
mov a, sp;                  a = sp
mov p, a;                 p = a
push af    // a is already overwritten by sp so why save it? shouldn't this be the first instruction?
mov a, op0;               a = op0
idxm p, a;                  [p] = a
inc p;                          p += 1
mov a, op1;               a = op1
idxm p, a;                  [p] = a

I would imagine that something like this would be appropriate:

Code: [Select]
pushaf
mov a, sp
mov p, a
mov a, op0
idxm p, a
inc a
mov a, op1
idxm p, a
add sp, 2

Still dont see why the order in which a and flags are pushed would change this
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 10:19:55 am
You could also write something shorter like this. Still if you implement this symmetrically for pop there is no problem whatsoever even if the real hardware would behave differently.

edit: check the sp calculations on this chip sp grows up not down. Also what happens when an interrupt occurs and sp is increased by one?

Code: [Select]
pushaf
mov a, op0
idxm sp, a
inc sp
mov a, op1
idxm sp, a
inc sp



Code: [Select]
dec sp
idxm a, sp
mov op1, a
dec sp
idxm a, sp
mov op0, a
popaf
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 05, 2018, 10:21:16 am
Yes, I meant mov, not ld.

The push af is curently just used to cheaply increase sp by 2. But If I knew which byte a goes into, it could be used to at the same time write one of the bytes I want on the stack.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 10:32:49 am
Yes, I meant mov, not ld.

The push af is curently just used to cheaply increase sp by 2. But If I knew which byte a goes into, it could be used to at the same time write one of the bytes I want on the stack.

Philipp


But then you dont need the pushaf/popaf at all and youre down to six instructions anyway ;)

Code: [Select]
mov a, op0
idxm sp, a
inc sp
mov a, op1
idxm sp, a
inc sp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 05, 2018, 10:36:07 am
But then you dont need the pushaf/popaf at all and youre down to six instructions anyway ;)

Code: [Select]
mov a, op0
idxm sp, a
inc sp
mov a, op1
idxm sp, a
inc sp

sp is in IO space, so there is no inc sp, and no idxm sp, a.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 10:44:44 am
ok now i get you would like to do something like this:

Code: [Select]
mov a, sp
mov p, a
mov a, op0
pushaf
inc p
mov a, op1
idxm p, a
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 10:51:19 am
you could of course also do

Code: [Select]
mov a, op0
pushaf
mov a, op1
pushaf
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 11:02:42 am
I looked at the PMC884 datasheet and you really cannot infer the positions on the stack.

        word          data0  ;                        //  declare  data0 in RAM
        word          data1  ;                        //  declare  data1 in RAM
        ...
mov       a, 0x55 ;
mov       ld@data0,  a  ;            //  move  0x55  to  data0 (LSB)
mov       a, 0xaa ;
mov       hd@data0, a  ;          //  move  0xaa  to  data0 (MSB)
pushw   data0  ;                      //  move  data (0xaa, 0x55) to stack memory (word)
popw     data1  ;                      //  move  (0xaa,  0x55)  in stack memory to data1 (word)
mov       a,  ld@data1  ;            //  ACC=0x55
mov       a,  hd@data1  ;            // ACC=0xaa
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 12:14:54 pm
Updated disassembler with 15 bit instruction set support.

Linux and Windows binaries included.


There seems to be a small problem with the io.txt file for the 15-bit core: some of the ios are no longer named (PFS173 startup code). PFS154 and test pdks previously included work fine.

Code: [Select]
001D  3F10  set1      .6
001E  0063  dzsn      a
001F  601E  goto      0x001E
0020  2300  dzsn      M0
0021  601E  goto      0x001E
0022  3B10  set0      .6
0023  3190  t0sn      .3
0024  6023  goto      0x0023
0025  5701  mov       a, 0x01
0026  3290  t0sn      .5
0027  57FF  mov       a, 0xFF
0028  1801  add       a, M1
0029  010B  mov       IHRCR, a
002A  1701  mov       M1, a
002B  3590  t1sn      .3
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 05, 2018, 12:19:41 pm
I looked at the PMC884 datasheet and you really cannot infer the positions on the stack.

        word          data0  ;                        //  declare  data0 in RAM
        word          data1  ;                        //  declare  data1 in RAM
        ...

From the startup code and the description of idxm one can infer that the Padauks are little endian, so the byte order for pusw in the 16-Bit instruction set should be the same. But push af is a different matter. Doing push af twice won't push a 16-Bit value onto the stack. It pushes two 16-bit vales, and the two a value bytes are apart, so I can't use that to push a 16-bit value.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 12:33:30 pm

From the startup code and the description of idxm one can infer that the Padauks are little endian, so the byte order for pusw in the 16-Bit instruction set should be the same. But push af is a different matter. Doing push af twice won't push a 16-Bit value onto the stack. It pushes two 16-bit vales, and the two a value bytes are apart, so I can't use that to push a 16-bit value.

No. idxm only moves a single byte from an index that is word aligned. So 16-bit address, 8-bit data (A isnt 16-bits), two idxm's for one 16-bit operand.
I thought op0 is the low byte and op1 the high byte of op.

So still two pushaf's will push the low and high byte but not consecutive in memory which doesnt matter that much because most people wont be doing deeply nested loops or recursion on these things. Also its guranteed to work no matter what the actual design is.

So this should work:

Code: [Select]
word op;
....
mov a, ld@op //low byte of op
pushaf
mov a, hd@op //high byte of op
pushaf
...
popaf
mov hd@op, a
popaf
mov ld@op, a
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 05:38:04 pm
quick question about the ice:

is there a device driver disk or something?
The downloadable IDE doesnt install a driver somewhere does it?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 05, 2018, 06:07:46 pm
Hi,

the ICE and the WRITER use USB-HID to communicate. USB-HID is not the fastest option... but it does not need any driver on Windows/Linux/Mac/...

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 06:12:42 pm
Ok, then I need to figure out how to get the firmware onto the naked dev boards I got today.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 06:28:37 pm
Also raises the interesting question what the P5SP firmwares are.
The firmware for the Cypresschip (*HID I presume) has about the right size for the chip, but the P5SP* files are ten times as large and wouldnt fit.

Maybe the socketed chip is a microcontroller after all and not an FPGA  :popcorn:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 05, 2018, 07:01:40 pm
Ok so I have found the bytes that need to be programmed at the start of the eeprom on the ICE close to the Cypress Chip:

C2 97 07 02 70 01 80 04 // this should be the ICE VID: 0797 PID: 7002 Revision/DID: 8001

C2 B4 04 04 10 01 A0 04 // This is the bulkloop firmware example from Cypress

C2 97 07 01 70 01 00 04 // ? with the controller loading the program from the EEPROM

C0 97 07 01 70 01 00 04 // ? EEPROM only holds VID/PID

Also something firmware ish is contained in FPPA_IDE.exe between 0x22af9c and 0x22ce77 (<- uncertain about the end and whether there might actually be two different firmwares here, also weird mix of .bin and .iic formats)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 05, 2018, 11:46:55 pm
There seems to be a small problem with the io.txt file for the 15-bit core: some of the ios are no longer named (PFS173 startup code). PFS154 and test pdks previously included work fine.

CR/LF line termination was not handled properly on the Linux version. Fixed.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: amyk on December 06, 2018, 01:12:09 am
A good starting point to see what I mean might be this datasheet for old PIC16C7XX OTPs
(although the padauks will probably behave differently I guess its reasonable to assume for now that their approach is similar)

http://ww1.microchip.com/downloads/en/DeviceDoc/30298d.pdf (http://ww1.microchip.com/downloads/en/DeviceDoc/30298d.pdf)
I think they're more complex than that --- the PIC only uses the high voltage to enter programming mode and then it's just data/clock. In the video you can see more voltage levels than that.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 06, 2018, 07:56:45 am
I think they're more complex than that --- the PIC only uses the high voltage to enter programming mode and then it's just data/clock. In the video you can see more voltage levels than that.

On the PICs its not just the high voltage:
"The  Program/Verify  mode  is  entered  by  holding  pins RB6 and RB7 low, while raising MCLR pin from VSS to the appropriate VIHH (high voltage). VDD is then raised from  VSS to  the  appropriate  VDD level.  Once  in  this mode, the user program memory and the configuration memory  can  be  accessed  and  programmed  in  serial fashion. "

The Padauks are different, but I dont think that we need the full waveform to be captured.
Just the maybe 30 - 40 cycles after each rise of VDD. The mode select is probably a combination of analog voltage levels and commands.
Also its much easier to trigger on a rising edge so the timinig issues that David was having shouldnt be that much of a problem.

There arent that many voltage levels either (I assume that VPP is supplied at pin PA5 and freely adjustable within the range below).

0x63421c 70 69 Please remove all IC, and check VDD,\nVPP(PA5), PA0 / 3 / 4 / 7 is 0 V
0x634264 30 29 Please check VPP (PA5) = 4.6V
0x634284 31 30 Please check VPP (PA5) = 11.3V
0x6342a4 24 23 Please check VDD = 5.5V
0x6342bc 24 23 Please check VDD = 7.5V
0x6342d4 24 23 Please check VDD = 3.3V

But unfortunately I dont have a programmer.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 06, 2018, 08:25:24 am
The Padauks are different, but I dont think that we need the full waveform to be captured.
Just the maybe 30 - 40 cycles after each rise of VDD. The mode select is probably a combination of analog voltage levels and commands.
Also its much easier to trigger on a rising edge so the timinig issues that David was having shouldnt be that much of a problem.

There are different voltages on more pins than just VDD. But my board is routed now, will get the parts today, then I can print out the board to test for footprint errors and will get the final PCB in less than 2 weeks. Might be very useful for other things as well. I can connect two of these boards to a DE10 Nano. Then I have 8 analog (-10 V to +10 V) 8 bit channels with 50 MHz sample rate each, 1 GB sample memory, a FPGA and Linux on the board to pre-process the data if necessary, and gigabit ethernet to stream it in real time to a PC (at least 10 MHz samplerate with 8 channels should be possible in this mode).

(https://i.imgur.com/iXd0cpC.jpg)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 06, 2018, 08:45:49 am
There are different voltages on more pins than just VDD.

Do they have the same level as VDD?

Some pins just have short pulses for blank checking.

If I interpret the strings FPPA_IDE.exe correctly only VDD, VPP(PA5) and PA0 / 3 / 4 / 7 (plus GND obviously) are used.
The smallest chip I could find (PMS150C-U06) only has VDD, PA5, GND and 4/3 as well as 6.
So 3 (clock) and 4 (data) and thats it. (which also support Davids findings in the video for the PMC150C SO8)
And if remember correctly PA6 is used for that bit banging calibration thing.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 06, 2018, 09:34:27 am
Right, the voltage levels might be identical on VDD and the data pins. At least it was about 6.5 V for some data lines when I tested it:

https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg1986377/#msg1986377 (https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg1986377/#msg1986377)

Maybe looking at the programmer circuit board might help with this, too, and the programmer firmware.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 06, 2018, 09:45:06 am
I still think the areas with 6.5V VDD are for verification purposes, there should also be parts close to 2V,
however from the current PMS150C datasheet:
Supply  Voltage 2.0V ~ 5.5V (Maximum Rating: 5.5V) *If VDD over maximum rating, it may lead to a permanent damage of IC.

I quote again from the PIC datasheet:
Programming Algorithm Requires Variable VDD
The  PIC16C7XX  uses  an  intelligent  algorithm.  The algorithm  calls  for  program  verification  at  VDDMIN  as well  as  VDDMAX.  Verification  at  VDDMIN
  ensures  good “erase  margin”.  Verification  at  VDDMAX ensures  good “program margin.”  The actual programming must be done with VDD in the VDDP
 range (4.75 - 5.25V). VDDP=VDD range required during programming. VDDMIN = minimum operating VDD spec for the part. VDDMAX = maximum operating VDD
 spec for the part. Programmers must verify the PIC16C7XX at its specified VDDMAX and VDDMIN levels. Since  Microchip may introduce  future  versions  of  the  PIC16C7XX  with  a broader V
DD range, it is best that these levels are user selectable (defaults are ok).
Note:
Any    programmer    not    meeting    these requirements  may  only  be  classified  as “prototype” or “development” programmer, but not a “production” quality programmer.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 06, 2018, 10:32:56 pm
Hi,

I wrote a little program to find out how LDSPTL/LDSPTH are truly working.

The program uses LDSPTL/LDSPTH to dump the IC content and send it out via a soft spi. Then I used a STM32 and created a small capture program for the SPI which sends it to my computer via USB-Serial-Port.

First I checked flags by loading 0x00 to flags register, then execute the opcode, then output the content of flag register over spi, afterwards I loaded 0xFF to flags register and tried again.
Result: LDSPTL/LDSPTH do not alter any flags

Then I made a loop to dump the content of a PMS154B by setting SP to mem:0 and then incrementing the 16 bit value in mem:0 and mem:1.
Result: I got a complete dump of the code memory.
Upper bits of LDSPTH are reading 0 -> dump reads exactly same as content of PDK file (0x3FFF reads as 0x3FFF)
When the address in SP (can hold 16 bits) exceeds the code memory, the address just wraps around and starts reading from 0 again (NO CRASH)


Bonus: It also became visible what WRITER did to the last 32 reserved bytes in memory  :)

PDK-DATA last 32 bytes:

0000fe0: ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f
0000ff0: 00 00 00 00 ff 3f ff 3f ff 3f ff 3f ff 3f 51 11


Dump from PMC154B last 32 bytes:

0000fe0: ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f 5a 02 ff 3f
0000ff0: 2d 34 a5 3e ff 3f ff 3f ff 3f ff 3f 48 02 51 11


GREAT FUN! (just spent 3 cent :-DD)

JS

UPDATE:
More notes about "last 8 Words", security bit, ... here:
https://github.com/free-pdk/fppa-pdk-documentation/blob/master/Reserved_Area_Last_8_Words_Of_Codemem.txt

UPDATE:
Special code found and guessing what it can be here:
https://github.com/free-pdk/fppa-pdk-documentation/blob/master/SpecialCodeFoundInPMS154B.txt
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 17, 2018, 11:27:07 pm
Hi,

I finally got the time to use a logic analyzer (ZeroPlus Logic Cube LAP-C322000) to capture the writing of a program on a PFS154.

I had to "modify" the logic analyzer first: was a LAP-C16032 ($100, 32kBit, can soft mod to 128 kBit) => swap SRAM => is now a LAP-C162000 / LAP-C322000 (4MBit) ( https://hackaday.com/2010/03/30/zeroplus-logic-cube-modification/ )  ::)

The logic analyzer allows -30V / +30V on logic pins, so capturing the expected 0V - 12V from WRITER was no problem.
Later, after deciphering the logic of the flashing protocol it will be easy to measure and reapply the real voltages for programing.
On oscilloscope it looks like PA5 receives the programing voltage of up to 12V during writing and VDD receives a slightly higher voltage >= 6.5V (maybe for reading the IC).


So first I created a PDK from my "SimpleBlink" demo and used WRITER to "CONVERT" it to a different "PACKAGE" which lets you disable the PIN CHECK (WRITER will check for all pins to have no short) which is not required for programing.
(The PDK without the pin check is attached to this post)

Then I used WRITER to write it to a PFS154 using a "PADAUK P-003". The logic analyzer was connected to JP3 on bottom side of programmer (A0 = pin 1 of JP3) and logic analyzer GND was connected to a ground pin on programmer PCB.

You can see some screen shots of the capture below (focus on first data block, zoomed in, zoomed in more).
I grouped CLK and DATA into a BUS (SPI) so the software tried to decode some bits... unfortunately it seems a non standard 8 bit transmissions is used.

It looks like PADAUK ICs enter programing mode if PA5_ICVPP is present before VDD is applied. 


Since the ZeroPlus software requires a logic analyzer to be present I exported the captured data to a simple text file of 117 MB, compressed to 1MB 7-Zip (requires recent version of 7-Zip since LZMA2 is used to make it so small, hidden in a normal ZIP since forum does not allow .7z files).
The file contains all details about the capture (2MHz seems to be enough, I tried with 100MHz but did not see any pulses < 100 units)

As always,

Have fun!

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 18, 2018, 07:07:44 pm
You can see some screen shots of the capture below (focus on first data block, zoomed in, zoomed in more).
I grouped CLK and DATA into a BUS (SPI) so the software tried to decode some bits... unfortunately it seems a non standard 8 bit transmissions is used.

I guess the problem is that the clock is rather random (ie software generated, decision path dependent)
If I count the bits by hand I get
10100101   A5
10100101   A5
10100101   A5
10100110   A6
00011010   1A
10100001   A1

for the last picture.
Maybe thats A5: enter programming mode (could also be increase address), A6: write value (followed by value, is 1A the value for the configuration bits?), A1: program value followed by pause (self timing programming?)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 19, 2018, 04:43:03 pm
Hi,

I analyzed a bit more of the capture and could observe the following:

- first PA.5 is set to high (not sure which voltage is applied since logic analyzer does not provide this info, will find out later)

- 100µs later VDD is set to high (not sure which voltage is applied since logic analyzer does not provide this info, will find out later)

- 500µs later PA.3 (CLK) and PA.6 (DAT) are used to send 48 bit of data:  1010010110100101101001011001cccccccc10101010001 (A5A5A5A*CMD-BYTE*AA1) Note: AA1 might be from OTP-ID 2AA1 ?

- depending on command
 * no response expected:
   - 100µs later VDD is set to low
   - 250µs later PA.5 is set to low

 * response expected:
   - maybe DAT/CLK changes direction (driven by IC now)? --> any idea how to find out who is sending IC or WRITER?
   - response length depending of command
   - 100µs later VDD is set to low
   - 250µs later PA.5 is set to low

****

Following in this order been sent:

0x61 / no response (maybe writer stops after getting no response or does not even wait for response)
0x61 / response: 00111110111101111111111110000111111100000000000000011100011111110001000000000001111 (3F7BFFC3F8000E3F8800F)

0x31 / response: 0000 (very slow clocking)

0x66 / no response (execution time is very long before VDD/PA.5 going low)

0x70 / additional send data: 000000000010001111111111111111111111111111111111111111110011111110000 0 0 0 0 0 0 0 0 (last bits slow clocking) (4x 14bit data: 0x0008, 0x3FFF, 0x3FFF, 0x3FFF , 0x3F8 0 0..)

0x61 / no response (maybe writer stops after getting no response or does not even wait for response)

0x71 / additional send data: ( multiple times:  (4 x 14 bit data, ADR, slow clocks to process) )

0x61 / no response (maybe writer stops after getting no response or does not even wait for response)
0x61 / no response (maybe writer stops after getting no response or does not even wait for response)
0x61 / response: ...
0x61 / no response (execution time is very very very long VDD/PA.5 going low, seems DAT pulses without CLK from IC extend waiting period)

0x70 / additional send data: ( multiple times:  (4 x 14 bit data, ADR?, slow clocks to process) )
0x70 / additional send data: ( multiple times:  (4 x 14 bit data, ADR?, slow clocks to process) )

0x61 / response: ...

0x60 / response: multiple times: (14 bit data)

0x61 / no response (maybe writer stops after getting no response or does not even wait for response)

0x60 / no response (maybe writer stops after getting no response or does not even wait for response)

0x70 / additional send data: ( multiple times:  (4 x 14 bit data, ADR, slow clocks to process) )

****

- now IC is booted normally (PA.5 stays low, VDD is set to high)

- at this point it looks like the "calibration code" is executed
  # PA.5 is set high
  # PA.4 + PA.7 output high some clocks later
  lot of PA.4/PA.3 communication is done ...

- after some time VDD is set to low (IC shutdown)

****

- calibration is run again

****

0x71 / additional send data: ( multiple times:  (4 x 14 bit data, ARD?, slow clocks to process) )

0x61 / response: ...

0x60 / no response (maybe writer stops after getting no response or does not even wait for response)

0x71 / additional send data: ( multiple times:  (4 x 14 bit data, ADR?, slow clocks to process) )

****

ALL DONE



Looks like:
 0x60/0x61 might be GET_STATUS or READ
 0x70/0x71 might be WRITE
 0x31 might be ERASE
 0x66 might be CHECKBLANK


Time to write a parser for this  :)

Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: lucas.hartmann on December 19, 2018, 04:52:27 pm
You can hook if a few analog comparators to diffetentiate between the required voltage levels. Something like a flash ADC structure, but with far less bits.

A single CA339 + 4 trimpots would give you five voltage levels, and take 4 bits on the logic analyzer.

Enviado de meu SM-N910C usando o Tapatalk

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 19, 2018, 05:22:57 pm
You can hook if a few analog comparators to diffetentiate between the required voltage levels. Something like a flash ADC structure, but with far less bits.

A single CA339 + 4 trimpots would give you five voltage levels, and take 4 bits on the logic analyzer.

Enviado de meu SM-N910C usando o Tapatalk

Hi,

Thanks for the idea, looks like ZeroPlus is doing the same in their commercial offering: https://www.thedebugstore.com/dso-lap-c-zeroplus.html (https://www.thedebugstore.com/dso-lap-c-zeroplus.html)

Fortunately the different voltages applied are not so complicated. Just VPP (PA.5) and VDD are set to different level when each programing step starts. A simple measurement with a scope is no problem. Since we can count the trigger pulses in logic analyzer (VPP low / high transitions) it is easy to setup the scope to ignore X trigger and we arrive at the desired programing step to measure / monitor the voltage.


JS


EDIT: Since I like the idea of using some bits of the logic analyzer to capture analog voltage so much, I will use a cheap STM32F072 board to do exactly this... 2 parallel ADC channels, output 2x8 bit, should only take an hour to implement :-)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 19, 2018, 08:14:20 pm
EDIT: Since I like the idea of using some bits of the logic analyzer to capture analog voltage so much, I will use a cheap STM32F072 board to do exactly this... 2 parallel ADC channels, output 2x8 bit, should only take an hour to implement :-)

A Padauk or Puolop would provide the ADC channels cheaper.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 21, 2018, 03:15:58 pm

A Padauk or Puolop would provide the ADC channels cheaper.

Philipp

This would be an excellent choice in the future. I also did not see the 100% identical "Puolop" brand before  8)

Right now I do not have the PFS173 with ADC und use the STM32F072 I have at hand (also not very expensive).


Capture analog values for logic analyzer using STM32F072:

Hardware:
I use STM32F072 on this little board (USD 2.80): https://item.taobao.com/item.htm?id=539758673887 (https://item.taobao.com/item.htm?id=539758673887)
(schematics: http://www.vcc-gnd.com/jikeliangpinstm32f072c8t6xuexibanziliao (http://www.vcc-gnd.com/jikeliangpinstm32f072c8t6xuexibanziliao) )

Mini ST-Link/V2 compatible device for uploading / debugging (USD 1.40): https://item.taobao.com/item.htm?id=560869168693 (https://item.taobao.com/item.htm?id=560869168693)

Software:

1. Use CubeMX software from ST and load the file "A2LASTM32.ioc"
    The project is configured to use 2 ADC channels in 8bit mode on PA0 and PA1 and use the complete GPIOB as 16 bit output (PB0-PB15).
    ADC is configured for continuous scan using DMA to write into a circular double buffer
    DMA will trigger interrupts + callbacks whenever first or second part of double buffer is complete

2. and click "Generate Code"
   (you can change code generator to your preferred IDE)

2. Open the generated code with your preferred IDE

3. Add the following code in the specified sections in "main.c" of the generated code:

    DMA callbacks combine the 2 ADC values into a 16 bit value and set GPIOB output (USER CODE 0, see below)

    ADC is calibrated and started in main (USER CODE 2, see below)

Code: [Select]
...

/* USER CODE BEGIN 0 */

//double buffer(2) * 32 bit  //  32 bit = (2 * 16 bit) // each adc value always takes 16 bit
static uint32_t adcDMABuffer[2];

//first part of double buffer complete
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* AdcHandle) {
  //combine and output 2 adc values (8bit : 8bit) on GPIOB
  GPIOB->ODR = (adcDMABuffer[0] | (adcDMABuffer[0]>>8)) & 0xFFFF;
}

//second part of double buffer complete
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle) {
  //combine and output 2 adc values (8bit : 8bit) on GPIOB
  GPIOB->ODR = (adcDMABuffer[1] | (adcDMABuffer[1]>>8)) & 0xFFFF;
}

/* USER CODE END 0 */


...


/* USER CODE BEGIN 2 */

HAL_ADCEx_Calibration_Start(&hadc);
HAL_ADC_Start_DMA(&hadc, (uint32_t*)adcDMABuffer, 2*2 );

/* USER CODE END 2 */

...

4. Compile it

5. Upload it using ST-Link/V2 (your IDE supports this for sure)



Was a nice experience. I just used the CubeMX configurator with the mouse and typed 7 lines of code (excluding comments).

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 22, 2018, 03:02:22 pm
Hi,

I was trying to find out some info about the "BGTR" register which is defined in PFS154.INC and used by init code of PFS154 when I came across this:

"SONiX 8-Bit Micro-Controller"

I think I just found the initial IC designer which seem to have created the CPU core in 2004 or earlier (several years before PADAUK adapted it):

==> http://www.sonix.com.tw/list-en-1006 (http://www.sonix.com.tw/list-en-1006)

They also have flash versions:

==> http://www.sonix.com.tw/list-en-1001 (http://www.sonix.com.tw/list-en-1001)

More external files:

http://www.alldatasheet.com/view.jsp?Searchword=SN8P2722 (http://www.alldatasheet.com/view.jsp?Searchword=SN8P2722)
http://pdf1.alldatasheet.com/datasheet-pdf/view/110082/SONIX/SN8P2501A.html (http://pdf1.alldatasheet.com/datasheet-pdf/view/110082/SONIX/SN8P2501A.html)
...


The PADAUK IC versions seem to have small changes but we can learn a LOT from SONIX datasheets:

e.g.: P1.1/RST/VPP ... VPP: OTP 12.3V power input pin in programming mode

==> And a section mentioning "BandGap" near IHRC and ILRC (just like in PFS154.INC file)

So
IHRCR = Internal High speed R/C Register
ILRCR = Internal Low speed R/C Register
BGTR might be Band Gap Tuning Register


JS



Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 22, 2018, 05:08:37 pm
Hi,

I was trying to find out some info about the "BGTR" register which is defined in PFS154.INC and used by init code of PFS154 when I came across this:

"SONiX 8-Bit Micro-Controller"

I think I just found the initial IC designer which seem to have created the CPU core in 2004 or earlier (several years before PADAUK adapted it):
[…]

That looks somewhat similar to, but still different from the Padauk devices. In particular, Padauk (and Puolop) have a stack in RAM. SONiX has a tiny fixed-size stack in separate memory (similar to low-end PIC devices). That makes Padauk / Puolop a better target for a C compiler.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on December 22, 2018, 05:11:04 pm
[…] I also did not see the 100% identical "Puolop" brand before  8)

Most of the range looks identical, down to the dates in the datasheet changelogs. But Padauk has some flash and 8-core devices, while Puolop hasn't. And there seem to be some Puolop 1-core OTP devices that do not have a Padauk equivalent.

Philipp
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 22, 2018, 10:27:30 pm
Hi,

I was trying to find out some info about the "BGTR" register which is defined in PFS154.INC and used by init code of PFS154 when I came across this:

"SONiX 8-Bit Micro-Controller"

I think I just found the initial IC designer which seem to have created the CPU core in 2004 or earlier (several years before PADAUK adapted it):
[…]

That looks somewhat similar to, but still different from the Padauk devices. In particular, Padauk (and Puolop) have a stack in RAM. SONiX has a tiny fixed-size stack in separate memory (similar to low-end PIC devices). That makes Padauk / Puolop a better target for a C compiler.

Philipp

Only somewhat similar? They share almost the same instruction set as the 16 bit PADAUK devices. There is a disassembler on github: https://github.com/vpelletier/dissn8  ... have a look yourself.

So I wonder why PADAUK binary PDK file is encrypted... want to hide the fact that main """inspiration""" came from SN8 core?

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 23, 2018, 08:58:25 pm
Also found this site...

==> BE CAREFUL, NOT SURE IF THE TOOL IS LEGIT <==

http://www.mcusky.com/uasm/product_u51.asp (http://www.mcusky.com/uasm/product_u51.asp)


But they list PADAUK CPU and have a asm listing with valid 16 bit opcode bytes. (Looks like somebody in China was faster than us).

Somebody has setup handy to try (virtual machine, network restricted, ...)?


JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 24, 2018, 04:24:35 am
I added some eyes to a metal owl with a PMS150C:

https://www.youtube.com/watch?v=2q7OdzhhOmU (https://www.youtube.com/watch?v=2q7OdzhhOmU)

When the LED is dimmed, it needs about 300 uA, and when on about 2 mA. So the CR2032 batttery I used should last maybe at least a week.

The project file is attached. The PMS150C has no OTP ldtabl instruction, so I used a concept known from PICs: a lookup table with lots of "ret x" instructions, then calculating the address into this table, pushing it on stack and with a "ret" I jump into the table, returning the value I want. Needs some cycles, but not much space. Is there a better method? Getting the syntax right for the array etc. was not easy with the suboptimal documentation.

Interestingly with the ICE (in circuit emulator) it doesn't work, only when flashing the real chip. The ICE needs the switch-case part of the program. But I already contacted Padauk and they are looking into it.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 24, 2018, 12:14:40 pm
Hi,

I think what you should use is the "PCADD" instructions. Your table lookup could look like this:

Code: [Select]
void LookUp_A(void)
{
    ADD A,1
    PCADD A
    RET 0x0F
    RET 0x1F
    RET 0x7F
    RET 0x00
}

...

    A = i;
    LookUp_A();
    tm2b = A;
...

One other important thing: PWM is NOT turned OFF when you write 0x00 to "tm2b".
The formula for duty cycle is: Duty of Output = [( K + 1 ) ÷ 256] × 100%  (you see the +1, oscilloscope also shows a small spike all the time)
So in order to save power you should turn off PWM instead.


JS

UPDATE:

I modified your program a bit to disable PWM output when there is "0" in the table. This should save some power.

Code: [Select]
void LookUp_A(void)
{
    //caller needs to make sure A is in range of 0-3
    ADD A,1
    PCADD A
    RET 0x0F
    RET 0x1F
    RET 0x7F
    RET 0x00
}

void FPPA0(void):stack=4
{
  .ADJUST_IC  SYSCLK=IHRC/32, IHRC=16MHz, VDD=3V, Bandgap=Off

  $ TM2S = 8BIT, /1, /1;             // 8-bit PWM, pre-scalar = 1, scalar = 1 (tm2s = 0b0_00_00000)

  while (1) {
    BYTE i = 0;
    while (1)
    {
      A = i;
      LookUp_A();
      if( 0==A )
        $ TM2C = STOP;
      else
      {
        TM2B = A;
        $ TM2C = SYSCLK, PA3, PWM;   // setup timer2 as pwm out: system clock (512kHz), output=PA3, PWM mode (tm2c = 0b0001_10_1_0)
      }
      i++;
      if (i == 4) break;
      .delay 40000;
    }
    .delay 1000000;
  }
}

To really save power the DELAYs should be done using a TIMER and STOPEXE mode. Then for sure your battery will last 3 months instead of 1 week.

UPDATE2:

I did several modifications to get a much better power efficiency:
- use ILRC/16 instead of IHRC
- disable IHRC
- use STOPEXE during the long 2 second sleep

Code: [Select]
void LookUp_A(void)                                  //caller needs to make sure A is in range of 0-3
{
  ADD A,1
  PCADD A
  RET 0x0F
  RET 0x1F
  RET 0x7F
  RET 0x00
}

void DeepSleep_2s(void)
{
  WORD sleep = 0;
  STT16 sleep

  INTRQ.T16 = 0;

  $ T16M = ILRC, /64, BIT11;                         //T16 clock source = ILRC (typ. 62 kHz on PMC150), / 64 => approx 1 kHz timer, 11BIT = 2048 => approx 2 seconds

  while( !INTRQ.T16 )                                //STOPEXE could be interrupted by multiple sources, we wait for T16 overflow here
    STOPEXE;

  $ T16M = STOP;
}

void FPPA0(void) : stack=2
{
  .ADJUST_IC  SYSCLK=ILRC (IHRC/16), IHRC=16MHz, VDD=3V, Bandgap=Off

 #if _SYS (AT_ICE)
  $ CLKMD = ILRC/4, En_ILRC;                         // ICE does not support ILRC/16, so we use /4 instead
 #else
  $ CLKMD = ILRC/16, En_ILRC;                        // use ILRC/16 as system clock (3.875kHz), turn off IHRC to save more power
 #endif

  $ TM2S = 8BIT, /1, /1;                             // 8-bit PWM, pre-scalar = 1, scalar = 1 (tm2s = 0b0_00_00000)

  while (1)
  {
    BYTE i = 0;
    while (1)
    {
      A = i;
      LookUp_A();
      if( 0==A )
        $ TM2C = STOP;
      else
      {
        TM2B = A;
        $ TM2C = ILRC, PA3, PWM;             // setup timer2 as pwm out: clock ilrc (62kHz), output=PA3, PWM mode
      }
      i++;
      if (i == 4) break;
      .delay 300;
 #if _SYS (AT_ICE)
      .delay 900;                                    // wait extra time since ICE clock is faster
 #endif
    }
    DeepSleep_2s();
  }
}
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: lucas.hartmann on December 24, 2018, 12:32:11 pm
You really need ADD A, 1?

Not sure about padauk, but other microcontroller always have PC pointing to the next instruction, so PCADD zero behaves like NOP.

Enviado de meu SM-N910C usando o Tapatalk

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 24, 2018, 12:34:38 pm
You really need ADD A, 1?

Not sure about padauk, but other microcontroller always have PC pointing to the next instruction, so PCADD zero behaves like NOP.

Enviado de meu SM-N910C usando o Tapatalk

Yes really need the +1 for PCADD. Otherwise my program was jumping into nowhere, crashing (I think it adds 256 in the case of A=0, will need to investigate)

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 24, 2018, 05:08:54 pm
Thanks, good ideas. It is no problem for my program, but the pcadd wouldn't work with larger tables. But I could test for different 256 byte ranges, there is not much ROM anyway. PWM 0 with the short spike actually looks quite nice for the owl eyes in the dark, you can still see it slightly glowing.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 25, 2018, 05:15:54 am
I think the programmer is a bit rudimentary with all these jumpers, or maybe I'm doing something wrong? I managed to program the PMS150C parts with SOT-23-6 package, but it was a bit complicated.

I got an SOT-23-6 to DIP 14 adapter from Padauk, see attached images top.jpg and bottom.jpg. The pinout is odd:

signal -SOT-23-6 pin -DIP 14 pin
PA419
GND211
PA636
PA547
VDD54
PA368

When I tried to program it, it didn't work, because when I create a project for the PMS150C, the package in the PDK file is S08. In the program writer user manual (http://www.padauk.com.tw//upload/WRITERmanual/PDK5S-P-003-UM_EN_V006_20181030.pdf) on page 21 it looks like you can configure for each pin individually the signal function, like PA6 or VDD. But this didn't work.

So I did the procedure defined in chapter 5 for creating a "connecting board". On page 16 in the user manual you can see the pinout of JP7. The user manual is not very clear, but looks like each pin of JP7 is connected to the ZIF socket on top, except for 4 pins of the socket: The 8 bottom pins are connected to the socket, then there are 4 unconnected pins on the socket, and then the top 28 pins of JP7 are connected again to the socket.

I defined my own "connecting board", as defined  in chapter 5 with JP7. The way you do this is to connect the 8 lower pins to your specific pinout. I did this, connecting the signals PA3, PA4, PA5, PA6, VDD, and GND from the bottom 8 pins to my DIP 14 layout on the top side with jumper wires. You can see this in the image jp7.jpg. PA7 and PA0 doesn't need to be connected, which means a minimal programmer might need at most 6 pins, but maybe less. Then I added the pin definitions in the PRE file in the IDE, as explained on page 19 of the writer user manual:

Code: [Select]
.writer package 14, 4, 32, 8, 9, 7, 6, 32, 11, 0x0000, 0x0000, 0

I had some problems with the open/short tests, but using 0x0000 for mask1 and mask2 worked without problems, which disables all tests on all pins.

After looking again at the adapter layout, the pinout looks exactly like the pinout of the PFS154-S14 chip. Maybe this would have saved me some time with the jumper wires, because I would have needed to define just the right writer package instruction, and could then use one of the pre-defined jumpers for S14 packages. Anyone who did this for the SOT-23-6 parts?

Why I think the programmer is rudimentary: It looks like the with the jumpers JP1 to JP7, the fixed 8 programmer signals are routed to the ZIF socket pins and you have to manually short the pins on the jumpers. For some jumpers like JP2, you get this jumper block, which connects all pins in parallel and the routing is done by the PCB layout, but depending on the package, you have to set individual jumpers, like with JP5. If you have the right connector board, or if your pinout is one of the pre-defined pinouts to use the existing jumpers, it is no problem for production. Just plugin the right jumper, and you can program your chips. But would be much better if it could be configured all in software, without the need to manually change jumpers.

There are already a bunch of 4051 analog multiplexers on the programmer board, but I guess they are used only for the open/short test and maybe chip identification, not to route the programming signals. Probably this would be a problem anyway, if it needs higher power, like when routing VDD and GND. But shouldn't break the bank to add two individual transistors for each pin for switching VDD and GND if necessary, at least up to SOP16. But there are some low resistance multiplexers ICs available as well, which would reduce this to like 4 ICs instead of 32 transistors. Just as an idea, if someone is planning to build an easy to use, universal Padauk chip programmer.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 01:46:15 pm
Hi,

I finally got the time to use a logic analyzer (ZeroPlus Logic Cube LAP-C322000) to capture the writing of a program on a PFS154.
...

Hello. I have downloaded the PDK and decrypted it, and got the following:
Code: [Select]
00000000: 70 00 00 2f 82 01 ed 3f 8b 01 ee 3f 9a 01 80 2f  p../...?...?.../
00000010: 9b 01 1c 2f 83 01 fe 3f ff 2a 54 30 ed 3f 81 0b  .../...?.*T0.?..
00000020: 91 1f 05 2f 80 0b d0 1a 13 30 90 1f 63 00 16 30  .../.....0..c..0
00000030: 80 11 16 30 90 1d d0 18 1b 30 01 2f 50 19 ff 2f  ...0.....0./P../
00000040: 01 0c 8b 01 81 0b d0 1a 23 30 50 1b 4f 30 04 2f  ........#0P.O0./
00000050: 88 01 d0 18 29 30 02 2f 82 01 04 13 05 13 6e 2f  ....)0./......n/
00000060: 82 0b 00 2f 83 0b 06 00 04 0b 07 00 05 08 84 15  .../............
00000070: 85 16 04 10 82 12 83 10 40 1a 33 30 90 1f d0 1a  ........@.30....
00000080: 3f 30 84 15 85 16 90 05 d0 18 44 30 50 19 3f 30  ?0........D0P.?0
00000090: 90 1d d0 1a 49 30 d0 18 4b 30 50 1b 2b 30 d0 18  ....I0..K0P.+0..
000000a0: 4f 30 50 1b 11 30 53 30 8b 01 d1 1e d0 1e 03 2f  O0P..0S0......./
000000b0: c1 0b 8a 2f c0 0b 56 2f 63 00 5c 30 c0 11 5c 30  .../..V/c.\0..\0
000000c0: c1 11 5c 30 d0 1c 03 2f c1 0b 8a 2f c0 0b 56 2f  ..\0.../.../..V/
000000d0: 63 00 68 30 c0 11 68 30 c1 11 68 30 56 30 ff 3f  c.h0..h0..h0V0.?
000000e0: ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f  .?.?.?.?.?.?.?.?
000000f0: ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f  .?.?.?.?.?.?.?.?


I have also downloaded the text file and written a quick and dirty Python script (attached) for parsing PA6_ICPDA and PA3_ICPCK as SPI data and clock, respectively.

The output is:
Code: [Select]
      1009: 1010010110100101101001011010011000001010101000010
     55103: 1010010110100101101001011010011000011010101000010
     65685: 001111110111101111111111110000111111100000000000000001100011111110001000000000000111
     92201: 1010010110100101101001011010001100011010101000010
    112855: 0
    122857: 00
    132871: 0
    158597: 1010010110100101101001011010011001111010101000010
    737022: 1010010110100101101001011010011100001010101000010
    757693: 000000000001001111111111111111111111111111111111111111110011111110000000000000
    784240: 1010010110100101101001011010011000001010101000010
    820818: 1010010110100101101001011010011100001010101000010
    841488: 111111111111110000000000010011111111111111111111111111110011111110000000000000
    868054: 1010010110100101101001011010011000001010101000010
    904632: 1010010110100101101001011010011000001010101000010
    949230: 1010010110100101101001011010011000001010101000010
    969891: 00111111000001111111111111100011111100001011111111111110001111110001001111111111111100111111000110111111111111110011111100100111111111111111001111110010101111111111111100111111001100111111111111110011111100111011111111111111001111110100011111111111111100111111010010111111111111110011111101010011111111111111001111110101111111111111111100111111011001111111111111110011111101101000010100000011001111110111000001001111010100111111011110111111111111000011111110000000000000001000001111111000100000000000100100111111100101111111111111100011111110011111111111111110001111111010011111111111111100111111101011111111111111110011111110110111111111111111001111111011111111111111111100111111110000111111111111110011111111001111111111111111001111111101001111111111111100111111110111111111111111110011111111100011111111111111001111111110111111111111111100111111111100111111111111110011111111111111111111111111
   1004046: 1010010110100101101001011010011000011010101000010
   1589373: 1010010110100101101001011010011100011010101000010
   1620117: 000000011100001011110000000000000110000010111111111011010000000000000000000000000001100010111111111110111000000110011010101111100000000000000000100000000000000001100110111011110001110000000110000011111111111111100000000001000000000000101010111111111100000101010011111111101101001011100000010000000001100000000000011111100100011011110000010100101110000000011010110100000000000010000000000000110000000100110111111001000000000001100011110000000101100000000010100000000000010001100000001100000001011001110110010000011000110100000000000011000000000000110000000110111011110000000101100101010000101111111111110000000011100000000000001100000000010000011000101100101110000001011010110100000000000100000000000000110000001000110110110101000011000001001111101111000001000000000100100000000000000001100010000110001101000011000000101001101111000000100000000101000000000000000001100000100100110000010001001100000101101111011011100000000101100000000000001011100000101011110000000000101110000011000000000001100000000110000000000000001011000001000000000000011100100000000101010101100001000000000110100000000000010110100001010100000000010001001010000010010000100000110000000111000000000000011010010000001100000011001101111110010000011010110100000000000111100000000000110000001111110101011000010001011010000101000101100100000000001000000000000000011000110100001100000100010001100101010000110000001111110000001000100000000000011101100100000110101101000011000001001001011000110100000000001001000000000000110000010010110110110101000011000000101011011000110100000000001001100000000000110000010011110110110101000011000000010001110000010100110000001010000000000000000001100010110111101101000101111011010000101111000000110000001010100000000000001011110000011011111000101000101111000000101111010101100000001011000000000000000000011000111100000101110001000111000000110000010111000000001011100000000000010001110000011100000101110001110011010000101111000000110000001100000000000000001011110000011011111000101000101111000000101111010101100000001100100000000000000000011000111100000110100001000111000000110000011010000000001101000000000000010001110000011100000110100011000001010110111111111111110000001101100000000000
   1669266: 1010010110100101101001011010011100001010101000010
   1689953: 111111111111110000101000000100001001111010011111111111100011111101100000000000000000000001000000000000010011111111111111111111111111110011111110000000000000011000010100001111110101010011111111111111111111111111110011111111000000000000111111111111111111111111111100001011111111110001111111010011111111100000000000
   1746862: 1010010110100101101001011010011000001010101000010
   1767523: 00111111000001111111111111100011111100001111111111111110001111110001011111111111111100111111000111111111111111110011111100100111111111111111001111110010101111111111111100111111001101111111111111110011111100111011111111111111001111110100011111111111111100111111010010111111111111110011111101010111111111111111001111110101101111111111111100111111011001111111111111110011111101101000010100000011001111110111000001001111010100111111011110111111111111000011111110000000000000001000001111111000100000000000100100111111100101111111111111100011111110011111111111111110001111111010011111111111111100111111101011111111111111110011111110110111111111111111001111111011111111111111111100111111110000110000101000010011111111001111111010101001001111111101011111111111111100111111110111111111111111110011111111100011111111111111001111111110111111111111111100111111111100000101111111110011111111111110001111111011
   1801641: 1010010110100101101001011010011000011010101000010
   1832399: 0000000000000000000011100000000000000000110111100000000000000000000100000011000001000000000000011111111111011010000000000010000000110001011000000000001011111111110111010000000000110000001100110100000000000011110111110000000100000000010000000011001101100000000001001101111000111000000000000101000000110000011000000000010110111111111111000000000001100101010111111110000000000110101000001010100100000000011101111111110110100000000001111001011100000011000000001000001111110010001100000000100010011110000010100000000010010001011100000001000000001001101101011010000000000000101001100000001001100000000010101011111100100001000000001011000000001100011100000000101111100000001011010000000011000010001100000000000000001100101000000010110100000000110100111011001000010000000011011011000110100001000000001110001000000011011100000000111011011110000000110000000011110011001010100001000000001111110111111111111000000001000000011000000000110000000100001000001100010110000000010001000101110000001000000001000110110101101000000000000100100010000001000110000000010010101101101010000100000001001101100000100111110000000100111101111000001001000000010100000000110001000100000001010010110001101000000000000101010010000001010010000000010101110111100000010100000001011000000011000001010000000101101010011000001000000000010111001001100000101000000001011111011110110111010000000110000001011100000101000000011000110111100000000000000001100100010111000001100000000110011000000000001100000000011010000101100000100000000001101010000000000011100000000110110001000000001010000000011011101010110000100000000001110000101101000010100000000111001010000000001001000000011101001001010000010100000001110110100001000001110000000111100011010010000001000000011110111000000110011100000001111100111111001000010000000111111011010110100001000000100000011000000111111100000010000010101011000010010000001000010010110100001011000000100001100010110010000100000010001000110001101000010000001000101010000010001000000000100011001100101010000100000010001110100000011111110000001001000011101100100001000000100100101101011010000100000010010100100000100100110000001001011011000110100001000000100110011000001001011100000010011010110110101000010000001001110010000001010111000000100111101100011010000100000010100001100000100111110000001010001011011010100001000000101001001000000010001100000010100110100000101001110000001010100000001100010111000000101010101111011010001100000010101100111101101000000000001010111101111000000111000000101100000101111000001100000010110011011111000101000000001011010001011110000000000000101101110111101010110000000010111000000000110001100000001011101110000010111000000000101111001000111000000000000010111111100000101110010000001100000010001110000011000000110000111000001011100100000011000100111001101000010000001100011101111000000111000000110010000101111000001100000011001011011111000101000000001100110001011110000000000000110011110111101010110000000011010000000000110001100000001101001110000011010000000000110101001000111000000000000011010111100000110100010000001101100010001110000011000000110110111000001101000100000011011101100000101011010000001101111111111111111111
   1890615: 1010010110100101101001011010011000011010101000010
   1935310: 1010010110100101101001011010011000001010101000010
   2004366: 1010010110100101101001011010011100011010101000010
   2035112: 000000011100001011110000000000000110000010111111111011010000000000000000000000000001100010111111111110111000000110011010101111100000000000000000100000000000000001100110111011110001110000000110000011111111111111100000000001000000000000101010111111111100000101010011111111101101001011100000010000000001100000000000011111100100011011110000010100101110000000011010110100000000000010000000000000110000000100110111111001000000000001100011110000000101100000000010100000000000010001100000001100000001011001110110010000011000110100000000000011000000000000110000000110111011110000000101100101010000101111111111110000000011100000000000001100000000010000011000101100101110000001011010110100000000000100000000000000110000001000110110110101000011000001001111101111000001000000000100100000000000000001100010000110001101000011000000101001101111000000100000000101000000000000000001100000100100110000010001001100000101101111011011100000000101100000000000001011100000101011110000000000101110000011000000000001100000000110000000000000001011000001000000000000011100100000000101010101100001000000000110100000000000010110100001010100000000010001001010000010010000100000110000000111000000000000011010010000001100000011001101111110010000011010110100000000000111100000000000110000001111110101011000010001011010000101000101100100000000001000000000000000011000110100001100000100010001100101010000110000001111110000001000100000000000011101100100000110101101000011000001001001011000110100000000001001000000000000110000010010110110110101000011000000101011011000110100000000001001100000000000110000010011110110110101000011000000010001110000010100110000001010000000000000000001100010110111101101000101111011010000101111000000110000001010100000000000001011110000011011111000101000101111000000101111010101100000001011000000000000000000011000111100000101110001000111000000110000010111000000001011100000000000010001110000011100000101110001110011010000101111000000110000001100000000000000001011110000011011111000101000101111000000101111010101100000001100100000000000000000011000111100000110100001000111000000110000011010000000001101000000000000010001110000011100000110100011000001010110111111111111110000001101100000000000
   2110976: 0
   2223667: 00
   2230308: 00
   2237010: 0
   2277626: 1101001010001110
   2301113: 0
   2304898: 11010010100011100
   2333060: 0
   2445751: 00
   2452389: 00
   2459091: 0
   2489632: 1101001010001110
   2523220: 0
   2527007: 11010010100011100
   2584511: 1010010110100101101001011010011100001010101000010
   2605196: 111111111111110000101000000100001001111010011111111111100011111101100000000000000000000001000000000000010011111111111111111111111111110011111110000000000000011000010100001111110101010011111111111111111111111111110011111111000000000000111111111111111111111111111100001010000010110001111111010011111111100000000000
   2634228: 1010010110100101101001011010011000001010101000010
   2664969: 00111111000001111111111111100011111100001011111111111110001111110001001111111111111100111111000110111111111111110011111100100111111111111111001111110010101111111111111100111111001100111111111111110011111100111011111111111111001111110100011111111111111100111111010010111111111111110011111101010011111111111111001111110101101111111111111100111111011001111111111111110011111101101000010100000011001111110111000001001111010100111111011110111111111111000011111110000000000000001000001111111000100000000000100100111111100101111111111111100011111110011011111111111110001111111010011111111111111100111111101011111111111111110011111110110111111111111111001111111011111111111111111100111111110000110000101000010011111111001111111010101001001111111101011111111111111100111111110111111111111111110011111111100011111111111111001111111110111111111111111100111111111100000101000001010011111111111110001111111011
   2699086: 1010010110100101101001011010011000001010101000010
   2743782: 1010010110100101101001011010011100001010101000010
   2774546: 111111111111110000101000000100001001111010011111111111100011111101100000000000000000000001000000000000010011111111111111111111111111110011111110000000000000011000010100001111110101010011111111111111111111111111110011111111000000000000111111111111111111111111111100001010000010110001111111010011111111100000000000


The transmission at 1620117 (which matches 1:1 that at 2035112) with 22 bit frames between 4-word blocks:
Code: [Select]
Exec.bin: 00000001110000 10111100000000 00000110000010 11111111101101                        00000110001011 11111111101110 00000110011010 10111110000000                        00000110011011 10111100011100 00000110000011 11111111111110                        10101011111111 11000001010100 11111111101101 00101110000001                        01111110010001 10111100000101 00101110000000 01101011010000                        11000000010011 01111110010000 00000001100011 11000000010110                        01000110000000 11000000010110 01110110010000 01100011010000                        11000000011011 10111100000001 01100101010000 10111111111111                        00110000000001 00000110001011 00101110000001 01101011010000                        11000000100011 01101101010000 11000001001111 10111100000100                        00000110001000 01100011010000 11000000101001 10111100000010                        00000110000010 01001100000100 01001100000101 10111101101110                        00101110000010 10111100000000 00101110000011 00000000000110                        00101100000100 00000000000111 00100000000101 01010110000100                        01011010000101 01000000000100 01001010000010 01000010000011                        01101001000000 11000000110011 01111110010000 01101011010000                        11000000111111 01010110000100 01011010000101 00010110010000                        01100011010000 11000001000100 01100101010000 11000000111111                        01110110010000 01101011010000 11000001001001 01100011010000                        11000001001011 01101101010000 11000000101011 01100011010000                        11000001001111 01101101010000 11000000010001 11000001010011                        00000110001011 01111011010001 01111011010000 10111100000011                        00101111000001 10111110001010 00101111000000 10111101010110                        00000001100011 11000001011100 01000111000000 11000001011100                        01000111000001 11000001011100 01110011010000 10111100000011                        00101111000001 10111110001010 00101111000000 10111101010110                        00000001100011 11000001101000 01000111000000 11000001101000                        01000111000001 11000001101000 11000001010110 11111111111111                       
 1620117: 00000001110000 10111100000000 00000110000010 11111111101101 0000000000000000000000 00000110001011 11111111101110 00000110011010 10111110000000 0000000000100000000000 00000110011011 10111100011100 00000110000011 11111111111110 0000000001000000000000 10101011111111 11000001010100 11111111101101 00101110000001 0000000001100000000000 01111110010001 10111100000101 00101110000000 01101011010000 0000000010000000000000 11000000010011 01111110010000 00000001100011 11000000010110 0000000010100000000000 01000110000000 11000000010110 01110110010000 01100011010000 0000000011000000000000 11000000011011 10111100000001 01100101010000 10111111111111 0000000011100000000000 00110000000001 00000110001011 00101110000001 01101011010000 0000000100000000000000 11000000100011 01101101010000 11000001001111 10111100000100 0000000100100000000000 00000110001000 01100011010000 11000000101001 10111100000010 0000000101000000000000 00000110000010 01001100000100 01001100000101 10111101101110 0000000101100000000000 00101110000010 10111100000000 00101110000011 00000000000110 0000000110000000000000 00101100000100 00000000000111 00100000000101 01010110000100 0000000110100000000000 01011010000101 01000000000100 01001010000010 01000010000011 0000000111000000000000 01101001000000 11000000110011 01111110010000 01101011010000 0000000111100000000000 11000000111111 01010110000100 01011010000101 00010110010000 0000001000000000000000 01100011010000 11000001000100 01100101010000 11000000111111 0000001000100000000000 01110110010000 01101011010000 11000001001001 01100011010000 0000001001000000000000 11000001001011 01101101010000 11000000101011 01100011010000 0000001001100000000000 11000001001111 01101101010000 11000000010001 11000001010011 0000001010000000000000 00000110001011 01111011010001 01111011010000 10111100000011 0000001010100000000000 00101111000001 10111110001010 00101111000000 10111101010110 0000001011000000000000 00000001100011 11000001011100 01000111000000 11000001011100 0000001011100000000000 01000111000001 11000001011100 01110011010000 10111100000011 0000001100000000000000 00101111000001 10111110001010 00101111000000 10111101010110 0000001100100000000000 00000001100011 11000001101000 01000111000000 11000001101000 0000001101000000000000 01000111000001 11000001101000 11000001010110 11111111111111 0000001101100000000000

It looks like it's loading 4 words, then sending the address to where it must be flashed to.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 02:10:31 pm
Hello @socram,

this is fantastic work :-)

Meanwhile I added two 8 bit channel which capture analog voltages as well.

I measured and normalized the analog conversion so the decimal decoded 8 bit value is voltage in 100mv step (e.g. 30 = 3.0V , 65 = 6.5V , ... )

I also found out that you can download and use the logic analyzer software without a real hardware in "DEMO-Mode"
Download: LAP-C V3.14.06 2018-11-19 : http://bd.zeroplus.com.tw/www/lac_s31406_all.zip (http://bd.zeroplus.com.tw/www/lac_s31406_all.zip)
==> Select "LAP-C32000" as demo device.

Now I can share the captures directly (much smaller size) and you still can export them to text ("File->Export->Waveform...").


I also did some more captures (I just pressed all buttons in Writer GUI which started an operation):

- PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_Program (erase,write,calibrate)

- PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_Verify

- PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_BlankCheck (was not blank, was programmed properly with SimpleBlink PDK before)

- PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_ReadSearch

NOTE:
Since the analog channel used a bit of the analyzer memory some captures are in chunks (pages). So when you see _P1, _P2, ... means they need to be stitched together (not sure where exactly need to stitch, maybe the 1% pre trigger is applied to the following pages as well and some values might be doubled)

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 02:38:40 pm
I have improved a bit the Python script and now the logs are much clear. Instead of expecting a fixed time between transmissions, it uses the VDD signal to detect power cycling:
Code: [Select]
      1009       : 1010010110100101101001011010011000001010101000010
     55103   READ: 1010010110100101101001011010011000011010101000010 001111110111101111111111110000111111100000000000000001100011111110001000000000000111
     92201       : 1010010110100101101001011010001100011010101000010 0000
    158597       : 1010010110100101101001011010011001111010101000010
    737022       : 1010010110100101101001011010011100001010101000010 000000000001001111111111111111111111111111111111111111110011111110000000000000
    784240       : 1010010110100101101001011010011000001010101000010
    820818       : 1010010110100101101001011010011100001010101000010 111111111111110000000000010011111111111111111111111111110011111110000000000000
    868054       : 1010010110100101101001011010011000001010101000010
    904632       : 1010010110100101101001011010011000001010101000010
    949230       : 1010010110100101101001011010011000001010101000010 00111111000001111111111111100011111100001011111111111110001111110001001111111111111100111111000110111111111111110011111100100111111111111111001111110010101111111111111100111111001100111111111111110011111100111011111111111111001111110100011111111111111100111111010010111111111111110011111101010011111111111111001111110101111111111111111100111111011001111111111111110011111101101000010100000011001111110111000001001111010100111111011110111111111111000011111110000000000000001000001111111000100000000000100100111111100101111111111111100011111110011111111111111110001111111010011111111111111100111111101011111111111111110011111110110111111111111111001111111011111111111111111100111111110000111111111111110011111111001111111111111111001111111101001111111111111100111111110111111111111111110011111111100011111111111111001111111110111111111111111100111111111100111111111111110011111111111111111111111111
   1004046   READ: 1010010110100101101001011010011000011010101000010
   1589373  WRITE: 1010010110100101101001011010011100011010101000010 000000011100001011110000000000000110000010111111111011010000000000000000000000000001100010111111111110111000000110011010101111100000000000000000100000000000000001100110111011110001110000000110000011111111111111100000000001000000000000101010111111111100000101010011111111101101001011100000010000000001100000000000011111100100011011110000010100101110000000011010110100000000000010000000000000110000000100110111111001000000000001100011110000000101100000000010100000000000010001100000001100000001011001110110010000011000110100000000000011000000000000110000000110111011110000000101100101010000101111111111110000000011100000000000001100000000010000011000101100101110000001011010110100000000000100000000000000110000001000110110110101000011000001001111101111000001000000000100100000000000000001100010000110001101000011000000101001101111000000100000000101000000000000000001100000100100110000010001001100000101101111011011100000000101100000000000001011100000101011110000000000101110000011000000000001100000000110000000000000001011000001000000000000011100100000000101010101100001000000000110100000000000010110100001010100000000010001001010000010010000100000110000000111000000000000011010010000001100000011001101111110010000011010110100000000000111100000000000110000001111110101011000010001011010000101000101100100000000001000000000000000011000110100001100000100010001100101010000110000001111110000001000100000000000011101100100000110101101000011000001001001011000110100000000001001000000000000110000010010110110110101000011000000101011011000110100000000001001100000000000110000010011110110110101000011000000010001110000010100110000001010000000000000000001100010110111101101000101111011010000101111000000110000001010100000000000001011110000011011111000101000101111000000101111010101100000001011000000000000000000011000111100000101110001000111000000110000010111000000001011100000000000010001110000011100000101110001110011010000101111000000110000001100000000000000001011110000011011111000101000101111000000101111010101100000001100100000000000000000011000111100000110100001000111000000110000011010000000001101000000000000010001110000011100000110100011000001010110111111111111110000001101100000000000
   1669266       : 1010010110100101101001011010011100001010101000010 111111111111110000101000000100001001111010011111111111100011111101100000000000000000000001000000000000010011111111111111111111111111110011111110000000000000011000010100001111110101010011111111111111111111111111110011111111000000000000111111111111111111111111111100001011111111110001111111010011111111100000000000
   1746862       : 1010010110100101101001011010011000001010101000010 00111111000001111111111111100011111100001111111111111110001111110001011111111111111100111111000111111111111111110011111100100111111111111111001111110010101111111111111100111111001101111111111111110011111100111011111111111111001111110100011111111111111100111111010010111111111111110011111101010111111111111111001111110101101111111111111100111111011001111111111111110011111101101000010100000011001111110111000001001111010100111111011110111111111111000011111110000000000000001000001111111000100000000000100100111111100101111111111111100011111110011111111111111110001111111010011111111111111100111111101011111111111111110011111110110111111111111111001111111011111111111111111100111111110000110000101000010011111111001111111010101001001111111101011111111111111100111111110111111111111111110011111111100011111111111111001111111110111111111111111100111111111100000101111111110011111111111110001111111011
   1801641   READ: 1010010110100101101001011010011000011010101000010 0000000000000000000011100000000000000000110111100000000000000000000100000011000001000000000000011111111111011010000000000010000000110001011000000000001011111111110111010000000000110000001100110100000000000011110111110000000100000000010000000011001101100000000001001101111000111000000000000101000000110000011000000000010110111111111111000000000001100101010111111110000000000110101000001010100100000000011101111111110110100000000001111001011100000011000000001000001111110010001100000000100010011110000010100000000010010001011100000001000000001001101101011010000000000000101001100000001001100000000010101011111100100001000000001011000000001100011100000000101111100000001011010000000011000010001100000000000000001100101000000010110100000000110100111011001000010000000011011011000110100001000000001110001000000011011100000000111011011110000000110000000011110011001010100001000000001111110111111111111000000001000000011000000000110000000100001000001100010110000000010001000101110000001000000001000110110101101000000000000100100010000001000110000000010010101101101010000100000001001101100000100111110000000100111101111000001001000000010100000000110001000100000001010010110001101000000000000101010010000001010010000000010101110111100000010100000001011000000011000001010000000101101010011000001000000000010111001001100000101000000001011111011110110111010000000110000001011100000101000000011000110111100000000000000001100100010111000001100000000110011000000000001100000000011010000101100000100000000001101010000000000011100000000110110001000000001010000000011011101010110000100000000001110000101101000010100000000111001010000000001001000000011101001001010000010100000001110110100001000001110000000111100011010010000001000000011110111000000110011100000001111100111111001000010000000111111011010110100001000000100000011000000111111100000010000010101011000010010000001000010010110100001011000000100001100010110010000100000010001000110001101000010000001000101010000010001000000000100011001100101010000100000010001110100000011111110000001001000011101100100001000000100100101101011010000100000010010100100000100100110000001001011011000110100001000000100110011000001001011100000010011010110110101000010000001001110010000001010111000000100111101100011010000100000010100001100000100111110000001010001011011010100001000000101001001000000010001100000010100110100000101001110000001010100000001100010111000000101010101111011010001100000010101100111101101000000000001010111101111000000111000000101100000101111000001100000010110011011111000101000000001011010001011110000000000000101101110111101010110000000010111000000000110001100000001011101110000010111000000000101111001000111000000000000010111111100000101110010000001100000010001110000011000000110000111000001011100100000011000100111001101000010000001100011101111000000111000000110010000101111000001100000011001011011111000101000000001100110001011110000000000000110011110111101010110000000011010000000000110001100000001101001110000011010000000000110101001000111000000000000011010111100000110100010000001101100010001110000011000000110110111000001101000100000011011101100000101011010000001101111111111111111111
   1890615   READ: 1010010110100101101001011010011000011010101000010
   1935310       : 1010010110100101101001011010011000001010101000010
   2004366  WRITE: 1010010110100101101001011010011100011010101000010 000000011100001011110000000000000110000010111111111011010000000000000000000000000001100010111111111110111000000110011010101111100000000000000000100000000000000001100110111011110001110000000110000011111111111111100000000001000000000000101010111111111100000101010011111111101101001011100000010000000001100000000000011111100100011011110000010100101110000000011010110100000000000010000000000000110000000100110111111001000000000001100011110000000101100000000010100000000000010001100000001100000001011001110110010000011000110100000000000011000000000000110000000110111011110000000101100101010000101111111111110000000011100000000000001100000000010000011000101100101110000001011010110100000000000100000000000000110000001000110110110101000011000001001111101111000001000000000100100000000000000001100010000110001101000011000000101001101111000000100000000101000000000000000001100000100100110000010001001100000101101111011011100000000101100000000000001011100000101011110000000000101110000011000000000001100000000110000000000000001011000001000000000000011100100000000101010101100001000000000110100000000000010110100001010100000000010001001010000010010000100000110000000111000000000000011010010000001100000011001101111110010000011010110100000000000111100000000000110000001111110101011000010001011010000101000101100100000000001000000000000000011000110100001100000100010001100101010000110000001111110000001000100000000000011101100100000110101101000011000001001001011000110100000000001001000000000000110000010010110110110101000011000000101011011000110100000000001001100000000000110000010011110110110101000011000000010001110000010100110000001010000000000000000001100010110111101101000101111011010000101111000000110000001010100000000000001011110000011011111000101000101111000000101111010101100000001011000000000000000000011000111100000101110001000111000000110000010111000000001011100000000000010001110000011100000101110001110011010000101111000000110000001100000000000000001011110000011011111000101000101111000000101111010101100000001100100000000000000000011000111100000110100001000111000000110000011010000000001101000000000000010001110000011100000110100011000001010110111111111111110000001101100000000000
   2110976       : 0000001101001010001110011010010100011100
   2333060       : 0000001101001010001110011010010100011100
   2584511       : 1010010110100101101001011010011100001010101000010 111111111111110000101000000100001001111010011111111111100011111101100000000000000000000001000000000000010011111111111111111111111111110011111110000000000000011000010100001111110101010011111111111111111111111111110011111111000000000000111111111111111111111111111100001010000010110001111111010011111111100000000000
   2634228       : 1010010110100101101001011010011000001010101000010 00111111000001111111111111100011111100001011111111111110001111110001001111111111111100111111000110111111111111110011111100100111111111111111001111110010101111111111111100111111001100111111111111110011111100111011111111111111001111110100011111111111111100111111010010111111111111110011111101010011111111111111001111110101101111111111111100111111011001111111111111110011111101101000010100000011001111110111000001001111010100111111011110111111111111000011111110000000000000001000001111111000100000000000100100111111100101111111111111100011111110011011111111111110001111111010011111111111111100111111101011111111111111110011111110110111111111111111001111111011111111111111111100111111110000110000101000010011111111001111111010101001001111111101011111111111111100111111110111111111111111110011111111100011111111111111001111111110111111111111111100111111111100000101000001010011111111111110001111111011
   2699086       : 1010010110100101101001011010011000001010101000010
   2743782       : 1010010110100101101001011010011100001010101000010 111111111111110000101000000100001001111010011111111111100011111101100000000000000000000001000000000000010011111111111111111111111111110011111110000000000000011000010100001111110101010011111111111111111111111111110011111111000000000000111111111111111111111111111100001010000010110001111111010011111111100000000000

1589373 is now the program sequence (which also appears at 2004366 - they are still 1:1 identical, not sure why is it downloading the code twice).

I am downloading the software to export to TXT and run them through the script to find simmilarities, but it's still downloading (and will probably take a few hours - is this 2001?)

I wonder what's with 2110976 and 2333060, as they are not following the format of the rest - maybe it's something running on the microcontroller?

EDIT: It looks like 1801641 could be either read or verify:
Code: [Select]
COMMAND:
1010010110100101101001011010011000011010101000010

ADDRESS       DATA           ?
0000000000000 00000001110000 0
0000000000001 10111100000000 0
0000000000010 00000110000010 0
0000000000011 11111111101101 0
0000000000100 00000110001011 0
0000000000101 11111111101110 1
0000000000110 00000110011010 0
0000000000111 10111110000000 1
0000000001000 00000110011011 0
0000000001001 10111100011100 0
0000000001010 00000110000011 0
0000000001011 01111111111110 0
0000000001100 10101011111111 0
0000000001101 01000001010100 1
0000000001110 11111111101101 0
0000000001111 00101110000001 1
0000000010000 01111110010001 1
0000000010001 00111100000101 0
0000000010010 00101110000000 1
0000000010011 01101011010000 0
0000000010100 11000000010011 0
0000000010101 01111110010000 1
0000000010110 00000001100011 1
0000000010111 11000000010110 1
0000000011000 01000110000000 0
0000000011001 01000000010110 1
0000000011010 01110110010000 1
0000000011011 01100011010000 1
0000000011100 01000000011011 1
0000000011101 10111100000001 1
0000000011110 01100101010000 1
0000000011111 10111111111111 0
0000000100000 00110000000001 1
0000000100001 00000110001011 0
0000000100010 00101110000001 0
0000000100011 01101011010000 0
0000000100100 01000000100011 0
0000000100101 01101101010000 1
0000000100110 11000001001111 1
0000000100111 10111100000100 1
0000000101000 00000110001000 1
0000000101001 01100011010000 0
0000000101010 01000000101001 0
0000000101011 10111100000010 1
0000000101100 00000110000010 1
0000000101101 01001100000100 0
0000000101110 01001100000101 0
0000000101111 10111101101110 1
0000000110000 00101110000010 1
0000000110001 10111100000000 0
0000000110010 00101110000011 0
0000000110011 00000000000110 0
0000000110100 00101100000100 0
0000000110101 00000000000111 0
0000000110110 00100000000101 0
0000000110111 01010110000100 0
0000000111000 01011010000101 0
0000000111001 01000000000100 1
0000000111010 01001010000010 1
0000000111011 01000010000011 1
0000000111100 01101001000000 1
0000000111101 11000000110011 1
0000000111110 01111110010000 1
0000000111111 01101011010000 1
0000001000000 11000000111111 1
0000001000001 01010110000100 1
0000001000010 01011010000101 1
0000001000011 00010110010000 1
0000001000100 01100011010000 1
0000001000101 01000001000100 0
0000001000110 01100101010000 1
0000001000111 01000000111111 1
0000001001000 01110110010000 1
0000001001001 01101011010000 1
0000001001010 01000001001001 1
0000001001011 01100011010000 1
0000001001100 11000001001011 1
0000001001101 01101101010000 1
0000001001110 01000000101011 1
0000001001111 01100011010000 1
0000001010000 11000001001111 1
0000001010001 01101101010000 1
0000001010010 01000000010001 1
0000001010011 01000001010011 1
0000001010100 00000110001011 1
0000001010101 01111011010001 1
0000001010110 01111011010000 0
0000001010111 10111100000011 1
0000001011000 00101111000001 1
0000001011001 10111110001010 0
0000001011010 00101111000000 0
0000001011011 10111101010110 0
0000001011100 00000001100011 0
0000001011101 11000001011100 0
0000001011110 01000111000000 0
0000001011111 11000001011100 1
0000001100000 01000111000001 1
0000001100001 11000001011100 1
0000001100010 01110011010000 1
0000001100011 10111100000011 1
0000001100100 00101111000001 1
0000001100101 10111110001010 0
0000001100110 00101111000000 0
0000001100111 10111101010110 0
0000001101000 00000001100011 0
0000001101001 11000001101000 0
0000001101010 01000111000000 0
0000001101011 11000001101000 1
0000001101100 01000111000001 1
0000001101101 11000001101000 1
0000001101110 11000001010110 1
0000001101111 11111111111111 1


I am not sure what the last bit could be, but the "data" is 1:1 the binary code that had just been programmed previously in the flash.

EDIT2: If that is indeed READ, then 55103 would be also reading 1FFE 0003 0003 from address 0x7EF
Code: [Select]
COMMAND:
1010010110100101101001011010011000011010101000010

ADDRESS       DATA           ?
0011111101111 01111111111110 0
0011111110000 00000000000011 0
0011111110001 00000000000011 1
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 04:45:57 pm
I wonder what's with 2110976 and 2333060, as they are not following the format of the rest - maybe it's something running on the microcontroller?

This is calibration discussed earlier in this thread with full disassembly.

I am not sure what the last bit could be, but the "data" is 1:1 the binary code that had just been programmed previously in the flash.

In case of READ/VERIFY/... the direction of CLK and DAT need to change:
begin (sending command): WRITER output: CLK/DAT, IC = input
after command (receive data): WRITER disables output of CLK/DAT and switches to input, IC = output

During this transition it looks like a "CLK" is generated which is in fact ignored by both sides (both sides are switching input/output of CLK/DAT). Saw this during writing.

If there is no switch of modes in the read command it also might be a PARITY bit?

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 05:30:35 pm
I am not sure. I had also thought of the parity bit, but it doesn't seem to make sense (for example, because it stays as 1 when one bit in the address or data is flipped). I had also tried sampling on the falling edge but again, it didn't make any sense.

Other files:

PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_BlankCheck.txt

Code: [Select]
      1207: FLASH_READ_1
            No data (dummy read)

     27385: FLASH_READ_2
            No data (dummy read)

     72043: FLASH_READ_2

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 3FFF 0
            07E2 3FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 1FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 1FFF 1
            07EB 1FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0025 0
            07F1 0025 1
            07F2 3FFF 0
            07F3 1FFF 0
            07F4 3FFF 1
            07F5 1FFF 1
            07F6 3FFF 1
            07F7 1FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

    126900: FLASH_READ_2
            No data (dummy read)



PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_Program_P1.txt

Code: [Select]
      1209: FLASH_READ_B
            No data (dummy read)

     55304: FLASH_READ_B

            ADDR DATA ?
            -----------
            07EF 1FFE 0
            07F0 0021 0
            07F1 0021 1

    102483: ??? (1010010110100101101001011010001100001010101000010)

    178976: ??? (1010010110100101101001011010011001111010101000010)

    747185: FLASH_WRITE

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 0022 3FFF 3FFF 3FFF


    794400: FLASH_READ_A
            No data (dummy read)

    830958: ??? (1010010110100101101001011010011100001010101000010)

    878196: FLASH_READ_B
            No data (dummy read)

    914794: FLASH_READ_A
            No data (dummy read)

    959391: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 3FFF 0
            07E2 3FFF 1
            07E3 3FFF 1
            07E4 3FFF 1
            07E5 3FFF 1
            07E6 3FFF 1
            07E7 3FFF 1
            07E8 3FFF 1
            07E9 3FFF 1
            07EA 3FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0022 0
            07F1 0022 1
            07F2 3FFF 0
            07F3 1FFF 0
            07F4 3FFF 1
            07F5 1FFF 1
            07F6 1FFF 1
            07F7 1FFF 1
            07F8 3FFF 1
            07F9 1FFF 1
            07FA 1FFF 1
            07FB 1FFF 1
            07FC 3FFF 1
            07FD 1FFF 1
            07FE 3FFF 1
            07FF 3FFF 1

   1014210: FLASH_READ_B
            No data (dummy read)


PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck_Bus_AVDD_Verify

Code: [Select]
      1209: FLASH_READ_B
            No data (dummy read)

     27386: FLASH_READ_B
            No data (dummy read)

     72043: FLASH_READ_A

            ADDR DATA ?
            -----------
            07E0 1FFF 0
            07E1 1FFF 0
            07E2 3FFF 1
            07E3 3FFF 1
            07E4 3FFF 1
            07E5 3FFF 1
            07E6 1FFF 1
            07E7 3FFF 1
            07E8 1FFF 1
            07E9 3FFF 1
            07EA 1FFF 1
            07EB 3FFF 1
            07EC 1FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 001F 0
            07F1 001F 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 3FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

    136979: FLASH_READ_A
            No data (dummy read)

    695006: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 1FFF 0
            07E2 1FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 1FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 1FFF 1
            07EB 1FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 001F 0
            07F1 001F 1
            07F2 3FFF 0
            07F3 1FFF 0
            07F4 3FFF 1
            07F5 1FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

    749723: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 1FFF 0
            07E2 1FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 3FFF 1
            07E7 3FFF 1
            07E8 3FFF 1
            07E9 3FFF 1
            07EA 3FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 001F 0
            07F1 001F 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 1FFF 1
            07F5 3FFF 1
            07F6 1FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

    804580: FLASH_READ_A

            ADDR DATA ?
            -----------
            0000 0070 0
            0001 2F00 0
            0002 0182 0
            0003 3FED 0
            0004 018B 0
            0005 3FEE 1
            0006 019A 0
            0007 2F80 1
            0008 019B 0
            0009 2F1C 0
            000A 0183 0
            000B 3FFE 0
            000C 0AFF 0
            000D 3054 1
            000E 1FED 0
            000F 0B81 1
            0010 1F91 1
            0011 2F05 0
            0012 0B80 1
            0013 1AD0 0
            0014 3013 0
            0015 1F90 1
            0016 0063 1
            0017 3016 1
            0018 1180 0
            0019 3016 1
            001A 1D90 1
            001B 18D0 1
            001C 301B 1
            001D 2F01 1
            001E 1950 1
            001F 2FFF 0
            0020 0C01 1
            0021 018B 0
            0022 0B81 0
            0023 1AD0 0
            0024 3023 0
            0025 1B50 1
            0026 304F 1
            0027 2F04 1
            0028 0188 1
            0029 18D0 0
            002A 3029 0
            002B 0F02 1
            002C 0182 1
            002D 1304 0
            002E 1305 0
            002F 0F6E 1
            0030 0B82 1
            0031 0F00 0
            0032 0B83 0
            0033 0006 0
            0034 0B04 0
            0035 0007 0
            0036 0805 0
            0037 1584 0
            0038 1685 0
            0039 1004 1
            003A 1282 1
            003B 1083 1
            003C 1A40 1
            003D 3033 1
            003E 1F90 1
            003F 1AD0 1
            0040 303F 1
            0041 1584 1
            0042 1685 1
            0043 0590 1
            0044 18D0 1
            0045 3044 0
            0046 1950 1
            0047 303F 1
            0048 1D90 1
            0049 1AD0 1
            004A 3049 1
            004B 18D0 1
            004C 104B 1
            004D 1B50 1
            004E 302B 1
            004F 18D0 1
            0050 104F 1
            0051 1B50 1
            0052 3011 1
            0053 3053 1
            0054 018B 1
            0055 1ED1 1
            0056 1ED0 0
            0057 2F03 1
            0058 0BC1 1
            0059 2F8A 0
            005A 0BC0 0
            005B 2F56 0
            005C 0063 0
            005D 305C 0
            005E 11C0 0
            005F 305C 1
            0060 11C1 1
            0061 305C 1
            0062 1CD0 1
            0063 2F03 1
            0064 0BC1 1
            0065 2F8A 0
            0066 0BC0 0
            0067 2F56 0
            0068 0063 0
            0069 1068 0
            006A 11C0 0
            006B 3068 1
            006C 11C1 1
            006D 3068 1
            006E 1056 1
            006F 1FFF 1
            0070 3FFF 1
            0071 1FFF 1
            0072 3FFF 1
            0073 1FFF 1
            0074 3FFF 1
            0075 1FFF 1
            0076 3FFF 1
            0077 1FFF 1
            0078 3FFF 1
            0079 1FFF 1
            007A 3FFF 1
            007B 1FFF 1
            007C 3FFF 1
            007D 1FFF 1
            007E 3FFF 1
            007F 3FFF 1
            0080 1FFF 1
            0081 3FFF 1
            0082 1FFF 1
            0083 3FFF 1
            0084 1FFF 1
            0085 3FFF 1
            0086 1FFF 1
            0087 3FFF 1
            0088 1FFF 1
            0089 3FFF 1
            008A 3FFF 1
            008B 3FFF 1
            008C 1FFF 1
            008D 3FFF 1
            008E 3FFF 1
            008F 3FFF 1
            0090 1FFF 1
            0091 3FFF 1
            0092 3FFF 1
            0093 3FFF 1
            0094 1FFF 1
            0095 3FFF 1
            0096 3FFF 1
            0097 3FFF 1
            0098 3FFF 1
            0099 3FFF 1
            009A 3FFF 1
            009B 3FFF 1
            009C 3FFF 1
            009D 3FFF 1
            009E 3FFF 1
            009F 3FFF 1
            00A0 3FFF 1
            00A1 3FFF 1
            00A2 3FFF 1
            00A3 3FFF 1
            00A4 3FFF 1
            00A5 3FFF 1
            00A6 3FFF 1
            00A7 3FFF 1
            00A8 3FFF 1
            00A9 3FFF 1
            00AA 3FFF 1
            00AB 3FFF 1
            00AC 3FFF 1
            00AD 3FFF 1
            00AE 3FFF 1
            00AF 1FFF 1
            00B0 3FFF 1
            00B1 1FFF 1
            00B2 1FFF 1
            00B3 1FFF 1
            00B4 3FFF 1
            00B5 1FFF 1
            00B6 1FFF 1
            00B7 1FFF 1
            00B8 3FFF 1
            00B9 1FFF 1
            00BA 1FFF 1
            00BB 1FFF 1
            00BC 3FFF 1
            00BD 1FFF 1
            00BE 1FFF 1
            00BF 3FFF 1
            00C0 1FFF 1
            00C1 1FFF 1
            00C2 1FFF 1
            00C3 3FFF 1
            00C4 1FFF 1
            00C5 3FFF 1
            00C6 1FFF 1
            00C7 3FFF 1
            00C8 1FFF 1
            00C9 3FFF 1
            00CA 3FFF 1
            00CB 3FFF 1
            00CC 1FFF 1
            00CD 3FFF 1
            00CE 3FFF 1
            00CF 3FFF 1
            00D0 1FFF 1
            00D1 3FFF 1
            00D2 3FFF 1
            00D3 3FFF 1
            00D4 1FFF 1
            00D5 3FFF 1
            00D6 3FFF 1
            00D7 3FFF 1
            00D8 1FFF 1
            00D9 3FFF 1
            00DA 3FFF 1
            00DB 3FFF 1
            00DC 3FFF 1
            00DD 3FFF 1
            00DE 3FFF 1
            00DF 3FFF 1
            00E0 3FFF 1
            00E1 3FFF 1
            00E2 3FFF 1
            00E3 3FFF 1
            00E4 3FFF 1
            00E5 3FFF 1
            00E6 3FFF 1
            00E7 3FFF 1
            00E8 3FFF 1
            00E9 3FFF 1
            00EA 3FFF 1
            00EB 3FFF 1
            00EC 3FFF 1
            00ED 3FFF 1
            00EE 3FFF 1
            00EF 3FFF 1
            00F0 3FFF 1
            00F1 1FFF 1
            00F2 1FFF 1
            00F3 1FFF 1
            00F4 3FFF 1
            00F5 1FFF 1
            00F6 1FFF 1
            00F7 1FFF 1
            00F8 3FFF 1
            00F9 1FFF 1
            00FA 1FFF 1
            00FB 1FFF 1
            00FC 3FFF 1
            00FD 1FFF 1
            00FE 1FFF 1
            00FF 1FFF 1
            0100 1FFF 1
            0101 1FFF 1
            0102 1FFF 1
            0103 1FFF 1
            0104 1FFF 1
            0105 3FFF 1
            0106 1FFF 1
            0107 3FFF 1
            0108 3FFF 1
            0109 3FFF 1
            010A 3FFF 1
            010B 3FFF 1
            010C 1FFF 1
            010D 3FFF 1
            010E 3FFF 1
            010F 3FFF 1
            0110 1FFF 1
            0111 3FFF 1
            0112 3FFF 1
            0113 3FFF 1
            0114 1FFF 1
            0115 3FFF 1
            0116 3FFF 1
            0117 3FFF 1
            0118 1FFF 1
            0119 3FFF 1
            011A 3FFF 1
            011B 3FFF 1
            011C 3FFF 1
            011D 3FFF 1
            011E 3FFF 1
            011F 3FFF 1
            0120 3FFF 1
            0121 3FFF 1
            0122 3FFF 1
            0123 3FFF 1
            0124 3FFF 1
            0125 3FFF 1
            0126 3FFF 1
            0127 3FFF 1
            0128 3FFF 1
            0129 3FFF 1
            012A 3FFF 1
            012B 3FFF 1
            012C 3FFF 1
            012D 3FFF 1
            012E 3FFF 1
            012F 3FFF 1
            0130 3FFF 1
            0131 3FFF 1
            0132 3FFF 1
            0133 3FFF 1
            0134 3FFF 1
            0135 1FFF 1
            0136 1FFF 1
            0137 1FFF 1
            0138 3FFF 1
            0139 1FFF 1
            013A 1FFF 1
            013B 1FFF 1
            013C 3FFF 1
            013D 1FFF 1
            013E 1FFF 1
            013F 1FFF 1
            0140 3FFF 1
            0141 1FFF 1
            0142 1FFF 1
            0143 1FFF 1
            0144 1FFF 1
            0145 1FFF 1
            0146 1FFF 1
            0147 1FFF 1
            0148 3FFF 1
            0149 3FFF 1
            014A 3FFF 1
            014B 3FFF 1
            014C 3FFF 1
            014D 3FFF 1
            014E 3FFF 1
            014F 3FFF 1
            0150 1FFF 1
            0151 3FFF 1
            0152 3FFF 1
            0153 3FFF 1
            0154 1FFF 1
            0155 3FFF 1
            0156 3FFF 1
            0157 3FFF 1
            0158 1FFF 1
            0159 3FFF 1
            015A 3FFF 1
            015B 3FFF 1
            015C 1FFF 1
            015D 3FFF 1
            015E 3FFF 1
            015F 3FFF 1
            0160 3FFF 1
            0161 3FFF 1
            0162 3FFF 1
            0163 3FFF 1
            0164 3FFF 1
            0165 3FFF 1
            0166 3FFF 1
            0167 3FFF 1
            0168 3FFF 1
            0169 3FFF 1
            016A 3FFF 1
            016B 3FFF 1
            016C 3FFF 1
            016D 3FFF 1
            016E 3FFF 1
            016F 3FFF 1
            0170 3FFF 1
            0171 3FFF 1
            0172 3FFF 1
            0173 3FFF 1
            0174 3FFF 1
            0175 3FFF 1
            0176 3FFF 1
            0177 1FFF 1
            0178 3FFF 1
            0179 1FFF 1
            017A 1FFF 1
            017B 1FFF 1
            017C 3FFF 1
            017D 1FFF 1
            017E 1FFF 1
            017F 1FFF 1
            0180 3FFF 1
            0181 1FFF 1
            0182 3FFF 1
            0183 1FFF 1
            0184 3FFF 1
            0185 1FFF 1
            0186 1FFF 1
            0187 1FFF 1
            0188 3FFF 1
            0189 3FFF 1
            018A 3FFF 1
            018B 3FFF 1
            018C 3FFF 1
            018D 3FFF 1
            018E 3FFF 1
            018F 3FFF 1
            0190 1FFF 1
            0191 3FFF 1
            0192 3FFF 1
            0193 3FFF 1
            0194 1FFF 1
            0195 3FFF 1
            0196 3FFF 1
            0197 3FFF 1
            0198 1FFF 1
            0199 3FFF 1
            019A 3FFF 1
            019B 3FFF 1
            019C 1FFF 1
            019D 3FFF 1
            019E 3FFF 1
            019F 3FFF 1
            01A0 1FFF 1
            01A1 3FFF 1
            01A2 3FFF 1
            01A3 3FFF 1
            01A4 3FFF 1
            01A5 3FFF 1
            01A6 3FFF 1
            01A7 3FFF 1
            01A8 3FFF 1
            01A9 3FFF 1
            01AA 3FFF 1
            01AB 3FFF 1
            01AC 3FFF 1
            01AD 3FFF 1
            01AE 3FFF 1
            01AF 3FFF 1
            01B0 3FFF 1
            01B1 3FFF 1
            01B2 3FFF 1
            01B3 3FFF 1
            01B4 3FFF 1
            01B5 3FFF 1
            01B6 3FFF 1
            01B7 3FFF 1
            01B8 3FFF 1
            01B9 1FFF 1
            01BA 1FFF 1
            01BB 1FFF 1
            01BC 3FFF 1
            01BD 1FFF 1
            01BE 1FFF 1
            01BF 1FFF 1
            01C0 3FFF 1
            01C1 1FFF 1
            01C2 3FFF 1
            01C3 1FFF 1
            01C4 3FFF 1
            01C5 1FFF 1
            01C6 3FFF 1
            01C7 1FFF 1
            01C8 3FFF 1
            01C9 1FFF 1
            01CA 3FFF 1
            01CB 3FFF 1
            01CC 3FFF 1
            01CD 3FFF 1
            01CE 3FFF 1
            01CF 3FFF 1
            01D0 3FFF 1
            01D1 3FFF 1
            01D2 3FFF 1
            01D3 3FFF 1
            01D4 1FFF 1
            01D5 3FFF 1
            01D6 3FFF 1
            01D7 3FFF 1
            01D8 1FFF 1
            01D9 3FFF 1
            01DA 3FFF 1
            01DB 3FFF 1
            01DC 1FFF 1
            01DD 3FFF 1
            01DE 3FFF 1
            01DF 3FFF 1
            01E0 1FFF 1
            01E1 3FFF 1
            01E2 3FFF 1
            01E3 3FFF 1
            01E4 3FFF 1
            01E5 3FFF 1
            01E6 3FFF 1
            01E7 3FFF 1
            01E8 3FFF 1
            01E9 3FFF 1
            01EA 3FFF 1
            01EB 3FFF 1
            01EC 3FFF 1
            01ED 3FFF 1
            01EE 3FFF 1
            01EF 3FFF 1
            01F0 3FFF 1
            01F1 3FFF 1
            01F2 3FFF 1
            01F3 3FFF 1
            01F4 3FFF 1
            01F5 3FFF 1
            01F6 3FFF 1
            01F7 3FFF 1
            01F8 3FFF 1
            01F9 3FFF 1
            01FA 3FFF 1
            01FB 3FFF 1
            01FC 3FFF 1
            01FD 1FFF 1
            01FE 1FFF 1
            01FF 1FFF 1
            0200 3FFF 1
            0201 1FFF 1
            0202 3FFF 1
            0203 1FFF 1
            0204 3FFF 1
            0205 1FFF 1
            0206 3FFF 1
            0207 1FFF 1
            0208 3FFF 1
            0209 1FFF 1
            020A 1FFF 1
            020B 1FFF 1
            020C 3FFF 1
            020D 3FFF 1
            020E 3FFF 1
            020F 3FFF 1
            0210 3FFF 1
            0211 3FFF 1
            0212 3FFF 1
            0213 3FFF 1
            0214 3FFF 1
            0215 3FFF 1
            0216 3FFF 1
            0217 3FFF 1
            0218 1FFF 1
            0219 3FFF 1
            021A 3FFF 1
            021B 3FFF 1
            021C 1FFF 1
            021D 3FFF 1
            021E 3FFF 1
            021F 3FFF 1
            0220 1FFF 1
            0221 3FFF 1
            0222 3FFF 1
            0223 3FFF 1
            0224 1FFF 1
            0225 3FFF 1
            0226 3FFF 1
            0227 3FFF 1
            0228 3FFF 1
            0229 3FFF 1
            022A 3FFF 1
            022B 3FFF 1
            022C 3FFF 1
            022D 3FFF 1
            022E 3FFF 1
            022F 3FFF 1
            0230 3FFF 1
            0231 3FFF 1
            0232 3FFF 1
            0233 3FFF 1
            0234 3FFF 1
            0235 3FFF 1
            0236 3FFF 1
            0237 3FFF 1
            0238 3FFF 1
            0239 3FFF 1
            023A 3FFF 1
            023B 3FFF 1
            023C 3FFF 1
            023D 3FFF 1
            023E 3FFF 1
            023F 1FFF 1
            0240 3FFF 1
            0241 3FFF 1
            0242 3FFF 1
            0243 1FFF 1
            0244 3FFF 1
            0245 1FFF 1
            0246 3FFF 1
            0247 1FFF 1
            0248 3FFF 1
            0249 1FFF 1
            024A 1FFF 1
            024B 1FFF 1
            024C 3FFF 1
            024D 1FFF 1
            024E 1FFF 1
            024F 1FFF 1
            0250 3FFF 1
            0251 3FFF 1
            0252 3FFF 1
            0253 3FFF 1
            0254 3FFF 1
            0255 3FFF 1
            0256 3FFF 1
            0257 3FFF 1
            0258 1FFF 1
            0259 3FFF 1
            025A 3FFF 1
            025B 3FFF 1
            025C 1FFF 1
            025D 3FFF 1
            025E 3FFF 1
            025F 3FFF 1
            0260 1FFF 1
            0261 3FFF 1
            0262 3FFF 1
            0263 3FFF 1
            0264 1FFF 1
            0265 3FFF 1
            0266 3FFF 1
            0267 3FFF 1
            0268 1FFF 1
            0269 3FFF 1
            026A 3FFF 1
            026B 3FFF 1
            026C 3FFF 1
            026D 3FFF 1
            026E 3FFF 1
            026F 3FFF 1
            0270 3FFF 1
            0271 3FFF 1
            0272 3FFF 1
            0273 3FFF 1
            0274 3FFF 1
            0275 3FFF 1
            0276 3FFF 1
            0277 3FFF 1
            0278 3FFF 1
            0279 3FFF 1
            027A 3FFF 1
            027B 3FFF 1
            027C 3FFF 1
            027D 3FFF 1
            027E 3FFF 1
            027F 3FFF 1
            0280 3FFF 1
            0281 3FFF 1
            0282 3FFF 1
            0283 3FFF 1
            0284 3FFF 1
            0285 1FFF 1
            0286 3FFF 1
            0287 1FFF 1
            0288 3FFF 1
            0289 1FFF 1
            028A 1FFF 1
            028B 1FFF 1
            028C 3FFF 1
            028D 1FFF 1
            028E 1FFF 1
            028F 1FFF 1
            0290 3FFF 1
            0291 1FFF 1
            0292 1FFF 1
            0293 3FFF 1
            0294 3FFF 1
            0295 3FFF 1
            0296 3FFF 1
            0297 3FFF 1
            0298 3FFF 1
            0299 3FFF 1
            029A 3FFF 1
            029B 3FFF 1
            029C 1FFF 1
            029D 3FFF 1
            029E 3FFF 1
            029F 3FFF 1
            02A0 1FFF 1
            02A1 3FFF 1
            02A2 3FFF 1
            02A3 3FFF 1
            02A4 1FFF 1
            02A5 3FFF 1
            02A6 3FFF 1
            02A7 3FFF 1
            02A8 1FFF 1
            02A9 3FFF 1
            02AA 3FFF 1
            02AB 3FFF 1
            02AC 3FFF 1
            02AD 3FFF 1
            02AE 3FFF 1
            02AF 3FFF 1
            02B0 3FFF 1
            02B1 3FFF 1
            02B2 3FFF 1
            02B3 3FFF 1
            02B4 3FFF 1
            02B5 3FFF 1
            02B6 3FFF 1
            02B7 3FFF 1
            02B8 3FFF 1
            02B9 3FFF 1
            02BA 3FFF 1
            02BB 3FFF 1
            02BC 3FFF 1
            02BD 3FFF 1
            02BE 3FFF 1
            02BF 3FFF 1
            02C0 3FFF 1
            02C1 3FFF 1
            02C2 3FFF 1
            02C3 3FFF 1
            02C4 3FFF 1
            02C5 3FFF 1
            02C6 3FFF 1
            02C7 1FFF 1
            02C8 3FFF 1
            02C9 1FFF 1
            02CA 1FFF 1
            02CB 1FFF 1
            02CC 3FFF 1
            02CD 1FFF 1
            02CE 1FFF 1
            02CF 1FFF 1
            02D0 3FFF 1
            02D1 1FFF 1
            02D2 1FFF 1
            02D3 1FFF 1
            02D4 3FFF 1
            02D5 3FFF 1
            02D6 3FFF 1
            02D7 3FFF 1
            02D8 3FFF 1
            02D9 3FFF 1
            02DA 3FFF 1
            02DB 3FFF 1
            02DC 3FFF 1
            02DD 3FFF 1
            02DE 3FFF 1
            02DF 3FFF 1
            02E0 1FFF 1
            02E1 3FFF 1
            02E2 3FFF 1
            02E3 3FFF 1
            02E4 1FFF 1
            02E5 3FFF 1
            02E6 3FFF 1
            02E7 3FFF 1
            02E8 1FFF 1
            02E9 3FFF 1
            02EA 3FFF 1
            02EB 3FFF 1
            02EC 1FFF 1
            02ED 3FFF 1
            02EE 3FFF 1
            02EF 3FFF 1
            02F0 3FFF 1
            02F1 3FFF 1
            02F2 3FFF 1
            02F3 3FFF 1
            02F4 3FFF 1
            02F5 3FFF 1
            02F6 3FFF 1
            02F7 3FFF 1
            02F8 3FFF 1
            02F9 3FFF 1
            02FA 3FFF 1
            02FB 3FFF 1
            02FC 3FFF 1
            02FD 3FFF 1
            02FE 3FFF 1
            02FF 3FFF 1
            0300 3FFF 1
            0301 3FFF 1
            0302 3FFF 1
            0303 3FFF 1
            0304 3FFF 1
            0305 3FFF 1
            0306 3FFF 1
            0307 3FFF 1
            0308 3FFF 1
            0309 1FFF 1
            030A 1FFF 1
            030B 1FFF 1
            030C 3FFF 1
            030D 1FFF 1
            030E 1FFF 1
            030F 1FFF 1
            0310 3FFF 1
            0311 1FFF 1
            0312 1FFF 1
            0313 1FFF 1
            0314 3FFF 1
            0315 1FFF 1
            0316 1FFF 1
            0317 1FFF 1
            0318 3FFF 1
            0319 3FFF 1
            031A 3FFF 1
            031B 3FFF 1
            031C 3FFF 1
            031D 3FFF 1
            031E 3FFF 1
            031F 3FFF 1
            0320 1FFF 1
            0321 3FFF 1
            0322 3FFF 1
            0323 3FFF 1
            0324 1FFF 1
            0325 3FFF 1
            0326 3FFF 1
            0327 3FFF 1
            0328 1FFF 1
            0329 3FFF 1
            032A 3FFF 1
            032B 3FFF 1
            032C 1FFF 1
            032D 3FFF 1
            032E 3FFF 1
            032F 3FFF 1
            0330 1FFF 1
            0331 3FFF 1
            0332 3FFF 1
            0333 3FFF 1
            0334 3FFF 1
            0335 3FFF 1
            0336 3FFF 1


EDIT: Improved dumps with automatic decoding script.

So far:

I have no idea what's the difference between the two flash reads, but they at least use exactly the same output format, and they both seem to be used interchangeably.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 06:50:41 pm
There seems to be two Flash read commands and two Flash write commands - why? I have absolutely no idea.

Parsing again the first shared .txt file, one gets now:

PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck.txt

Code: [Select]
      1009: FLASH_READ_B
            No data (dummy read)

     55103: FLASH_READ_A

            ADDR DATA ?
            -----------
            07EF 1FFE 0
            07F0 0003 0
            07F1 0003 1

     92201: ??? (1010010110100101101001011010001100011010101000010)

    158597: ??? (1010010110100101101001011010011001111010101000010)

    737022: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 0004 3FFF 3FFF 3FFF


    784240: FLASH_READ_B
            No data (dummy read)

    820818: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 3FFF 0004 3FFF 3FFF


    868054: FLASH_READ_B
            No data (dummy read)

    904632: FLASH_READ_B
            No data (dummy read)

    949230: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 1FFF 0
            07E2 1FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 1FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 1FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0004 0
            07F1 0004 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1FFF 1
            07F9 3FFF 1
            07FA 1FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 1FFF 1
            07FF 3FFF 1

   1004046: FLASH_READ_A
            No data (dummy read)

   1589373: FLASH_WRITE_A

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            0000 0070 2F00 0182 3FED
            0004 018B 3FEE 019A 2F80
            0008 019B 2F1C 0183 3FFE
            000C 2AFF 3054 3FED 0B81
            0010 1F91 2F05 0B80 1AD0
            0014 3013 1F90 0063 3016
            0018 1180 3016 1D90 18D0
            001C 301B 2F01 1950 2FFF
            0020 0C01 018B 0B81 1AD0
            0024 3023 1B50 304F 2F04
            0028 0188 18D0 3029 2F02
            002C 0182 1304 1305 2F6E
            0030 0B82 2F00 0B83 0006
            0034 0B04 0007 0805 1584
            0038 1685 1004 1282 1083
            003C 1A40 3033 1F90 1AD0
            0040 303F 1584 1685 0590
            0044 18D0 3044 1950 303F
            0048 1D90 1AD0 3049 18D0
            004C 304B 1B50 302B 18D0
            0050 304F 1B50 3011 3053
            0054 018B 1ED1 1ED0 2F03
            0058 0BC1 2F8A 0BC0 2F56
            005C 0063 305C 11C0 305C
            0060 11C1 305C 1CD0 2F03
            0064 0BC1 2F8A 0BC0 2F56
            0068 0063 3068 11C0 3068
            006C 11C1 3068 3056 3FFF


   1669266: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07EC 3FFF 0281 027A 1FFE
            07F0 0004 0004 3FFF 3FFF
            07F8 1850 3F54 3FFF 3FFF
            07FC 3FFF 3FFF 02FF 31FD


   1746862: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 3FFF 0
            07E2 3FFF 1
            07E3 3FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 3FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 3FFF 1
            07EB 1FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0004 0
            07F1 0004 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 02FF 1
            07FF 31FD 1

   1801641: FLASH_READ_A

            ADDR DATA ?
            -----------
            0000 0070 0
            0001 2F00 0
            0002 0182 0
            0003 3FED 0
            0004 018B 0
            0005 3FEE 1
            0006 019A 0
            0007 2F80 1
            0008 019B 0
            0009 2F1C 0
            000A 0183 0
            000B 1FFE 0
            000C 2AFF 0
            000D 1054 1
            000E 3FED 0
            000F 0B81 1
            0010 1F91 1
            0011 0F05 0
            0012 0B80 1
            0013 1AD0 0
            0014 3013 0
            0015 1F90 1
            0016 0063 1
            0017 3016 1
            0018 1180 0
            0019 1016 1
            001A 1D90 1
            001B 18D0 1
            001C 101B 1
            001D 2F01 1
            001E 1950 1
            001F 2FFF 0
            0020 0C01 1
            0021 018B 0
            0022 0B81 0
            0023 1AD0 0
            0024 1023 0
            0025 1B50 1
            0026 304F 1
            0027 2F04 1
            0028 0188 1
            0029 18D0 0
            002A 1029 0
            002B 2F02 1
            002C 0182 1
            002D 1304 0
            002E 1305 0
            002F 2F6E 1
            0030 0B82 1
            0031 2F00 0
            0032 0B83 0
            0033 0006 0
            0034 0B04 0
            0035 0007 0
            0036 0805 0
            0037 1584 0
            0038 1685 0
            0039 1004 1
            003A 1282 1
            003B 1083 1
            003C 1A40 1
            003D 3033 1
            003E 1F90 1
            003F 1AD0 1
            0040 303F 1
            0041 1584 1
            0042 1685 1
            0043 0590 1
            0044 18D0 1
            0045 1044 0
            0046 1950 1
            0047 103F 1
            0048 1D90 1
            0049 1AD0 1
            004A 1049 1
            004B 18D0 1
            004C 304B 1
            004D 1B50 1
            004E 102B 1
            004F 18D0 1
            0050 304F 1
            0051 1B50 1
            0052 1011 1
            0053 1053 1
            0054 018B 1
            0055 1ED1 1
            0056 1ED0 0
            0057 2F03 1
            0058 0BC1 1
            0059 2F8A 0
            005A 0BC0 0
            005B 2F56 0
            005C 0063 0
            005D 305C 0
            005E 11C0 0
            005F 305C 1
            0060 11C1 1
            0061 305C 1
            0062 1CD0 1
            0063 2F03 1
            0064 0BC1 1
            0065 2F8A 0
            0066 0BC0 0
            0067 2F56 0
            0068 0063 0
            0069 3068 0
            006A 11C0 0
            006B 3068 1
            006C 11C1 1
            006D 3068 1
            006E 3056 1
            006F 3FFF 1

   1890615: FLASH_READ_A
            No data (dummy read)

   1935310: FLASH_READ_B
            No data (dummy read)

   2004366: FLASH_WRITE_A

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            0000 0070 2F00 0182 3FED
            0004 018B 3FEE 019A 2F80
            0008 019B 2F1C 0183 3FFE
            000C 2AFF 3054 3FED 0B81
            0010 1F91 2F05 0B80 1AD0
            0014 3013 1F90 0063 3016
            0018 1180 3016 1D90 18D0
            001C 301B 2F01 1950 2FFF
            0020 0C01 018B 0B81 1AD0
            0024 3023 1B50 304F 2F04
            0028 0188 18D0 3029 2F02
            002C 0182 1304 1305 2F6E
            0030 0B82 2F00 0B83 0006
            0034 0B04 0007 0805 1584
            0038 1685 1004 1282 1083
            003C 1A40 3033 1F90 1AD0
            0040 303F 1584 1685 0590
            0044 18D0 3044 1950 303F
            0048 1D90 1AD0 3049 18D0
            004C 304B 1B50 302B 18D0
            0050 304F 1B50 3011 3053
            0054 018B 1ED1 1ED0 2F03
            0058 0BC1 2F8A 0BC0 2F56
            005C 0063 305C 11C0 305C
            0060 11C1 305C 1CD0 2F03
            0064 0BC1 2F8A 0BC0 2F56
            0068 0063 3068 11C0 3068
            006C 11C1 3068 3056 3FFF


   2110976: 0000001101001010001110011010010100011100
   2333060: 0000001101001010001110011010010100011100
   2584511: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07EC 3FFF 0281 027A 1FFE
            07F0 0004 0004 3FFF 3FFF
            07F8 1850 3F54 3FFF 3FFF
            07FC 3FFF 3FFF 0282 31FD


   2634228: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 1FFF 0
            07E2 1FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 1FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 1FFF 1
            07EB 1FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0004 0
            07F1 0004 1
            07F2 3FFF 0
            07F3 1FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

   2699086: FLASH_READ_B
            No data (dummy read)

   2743782: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07EC 3FFF 0281 027A 1FFE
            07F0 0004 0004 3FFF 3FFF
            07F8 1850 3F54 3FFF 3FFF
            07FC 3FFF 3FFF 0282 31FD


Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 07:07:58 pm
There seems to be two Flash read commands and two Flash write commands - why? I have absolutely no idea.

    1010010110100101101001011010011100011010101000010: FLASH write A
    1010010110100101101001011010011100001010101000010: FLASH write B
    1010010110100101101001011010011000011010101000010: FLASH read A
    1010010110100101101001011010011000001010101000010: FLASH read B

This are the same commands I mentioned several posts ago.

    101001011010010110100101101001110001101010100001 (0): A5A5A5A *71* AA1   
    101001011010010110100101101001110000101010100001 (0): A5A5A5A *70* AA1
    101001011010010110100101101001100001101010100001 (0): A5A5A5A *61* AA1
    101001011010010110100101101001100000101010100001 (0): A5A5A5A *60* AA1

last bit (0) is clock when switching bus direction or delay before write?

==> https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg2052700/#msg2052700 (https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg2052700/#msg2052700)

I also wrote about the ERASE command 31 and maybe a CHECK command 66  (your 2 unknown commands).


The new captures contain the analog voltages of VDD and VPP. I wonder if different voltages are applied when the same commands are executed...?

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 07:39:35 pm
First there is:
Code: [Select]
     55103: FLASH_READ_A

            ADDR DATA ?
            -----------
            07EF 1FFE 0
            07F0 0003 0
            07F1 0003 1

After that, the two mysterious commands are sent.
Code: [Select]
     92201: 1010010110100101101001011010001100011010101000010 0000
    158597: 1010010110100101101001011010011001111010101000010

Then, it does two writes:
Code: [Select]
    737022: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 0004 3FFF 3FFF 3FFF

    820818: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 3FFF 0004 3FFF 3FFF

It finally does one read to verify it. As we can see, the two writes have been AND'ed, so it means FLASH_WRITE_B doesn't implicitely clear the FLASH and it had to be one of the mysterious that had been run before:
Code: [Select]
    949230: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 1FFF 0
            07E2 1FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 1FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 1FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0004 0
            07F1 0004 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1FFF 1
            07F9 3FFF 1
            07FA 1FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 1FFF 1
            07FF 3FFF 1

Either 0x60 or 0x31 have erased thus the last page (at least) of the memory, but I still don't see which would. Sending 0000 to erase last/all pages don't make much sense - I doubt there's only one page of flash and 0 means thus all.

0x60 being "clear everything" would make more sense (and thus would explain the long delay after executing that command while the device is being cleared), but I don't understand what 0x31 would do then.

EDIT: Also have a look at 0x7ED, still contains data after issuing those commands.

EDIT2: I don't know how to use the ZEROPLUS tool, so I don't really know how to see the VPP voltages.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 08:31:18 pm
EDIT2: I don't know how to use the ZEROPLUS tool, so I don't really know how to see the VPP voltages.

I grouped the 2 channels into a bus each (VDD_AN and PA5_ICVPP_AN, bottom of Zero Plus) which decodes to decimal values (right click on the hex values and select "Numeric Base->Decimal").

In case you want to do it manually:
C0...C7 = 8 bit of analog value VDD_AN (in 100mV, ==> 30 decimal = 3.0V, 45 decimal = 4.5V, ...)
D0...D7 = 8 bit of analog value PA5_ICVPP_AN


example line from text export:


         PA0_UNUSED   | Bus1           *VDD*SCLK*DATA PA4  PA5 PA7  GND   | VDD_AN              *C0...*C7  | PA5_ICVPP_AN  *D0...*D7   

91330            0    | Data=0X1F             1   0   0   0   1   0   0   | 0X2B                  11010100 | 0X38           00011100


VDD_AN = 11010100 = 0x2B = 43 ==> 4.3V
PA5_ICVPP_AN = 00011100 = 0x38 = 56 ==> 5.6V

 :)

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 08:40:30 pm
Then, it does two writes:
Code: [Select]
    737022: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 0004 3FFF 3FFF 3FFF

    820818: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 3FFF 0004 3FFF 3FFF

This looks pretty normal. To understand this you must know how a OTP / flash write is usually working.

Blank IC / After Erase => all memory cells are holding a '1' bit value
Programing = change some of the '1' bits to '0' bits. You only can change '1' to '0' not the other way around. If you want to write something new you must erase the chip first (is possible) which makes *ALL* memory cells to a '1'.

So
- writing '11111111' somewhere does in reality: NOTHING (all stays same, you can do this as many times as you want)
- writing '0' somewhere changes this bit to '0'. If you later write a '1' it will do NOTHING (the 0 will stay).


==> Since the IC seems to require to write 4 WORDS at once a simple solution just to write 1 WORD or even only some bits from it is to write the unused WORDS with all '1'.
- writing "ABCD 3FFF 3FFF 3FFF" only will change the first word
- writing "3FFF EFGH 3FFF 3FFF" only will change the second word

==> It looks like WRITER just wants to write 2 WORDS in 2 single operations.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 09:52:30 pm
Then, it does two writes:
Code: [Select]
    737022: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 0004 3FFF 3FFF 3FFF

    820818: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 3FFF 0004 3FFF 3FFF

This looks pretty normal. To understand this you must know how a OTP / flash write is usually working.

Blank IC / After Erase => all memory cells are holding a '1' bit value
Programing = change some of the '1' bits to '0' bits. You only can change '1' to '0' not the other way around. If you want to write something new you must erase the chip first (is possible) which makes *ALL* memory cells to a '1'.

So
- writing '11111111' somewhere does in reality: NOTHING (all stays same, you can do this as many times as you want)
- writing '0' somewhere changes this bit to '0'. If you later write a '1' it will do NOTHING (the 0 will stay).


==> Since the IC seems to require to write 4 WORDS at once a simple solution just to write 1 WORD or even only some bits from it is to write the unused WORDS with all '1'.
- writing "ABCD 3FFF 3FFF 3FFF" only will change the first word
- writing "3FFF EFGH 3FFF 3FFF" only will change the second word

==> It looks like WRITER just wants to write 2 WORDS in 2 single operations.

JS
My point was that before the mysterious commands, 07F0 held 0003 and 07F1 held 0003. After them, they seem to held FFFF, which are subsequently changed into 0004 by those two writes.

However, you can see on 949230: FLASH_READ_B, that 07ED holds 0281. This means that "66" followed by four 0 bits, or "31" doesn't actually wipe all the flash, but if it actually actually wipes anything, it only clears a few bytes.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 10:37:24 pm
EDIT2: I don't know how to use the ZEROPLUS tool, so I don't really know how to see the VPP voltages.

I grouped the 2 channels into a bus each (VDD_AN and PA5_ICVPP_AN, bottom of Zero Plus) which decodes to decimal values (right click on the hex values and select "Numeric Base->Decimal").

In case you want to do it manually:
C0...C7 = 8 bit of analog value VDD_AN (in 100mV, ==> 30 decimal = 3.0V, 45 decimal = 4.5V, ...)
D0...D7 = 8 bit of analog value PA5_ICVPP_AN


example line from text export:


         PA0_UNUSED   | Bus1           *VDD*SCLK*DATA PA4  PA5 PA7  GND   | VDD_AN              *C0...*C7  | PA5_ICVPP_AN  *D0...*D7   

91330            0    | Data=0X1F             1   0   0   0   1   0   0   | 0X2B                  11010100 | 0X38           00011100


VDD_AN = 11010100 = 0x2B = 43 ==> 4.3V
PA5_ICVPP_AN = 00011100 = 0x38 = 56 ==> 5.6V

 :)

JS

Thanks. It seems that all commands are sent to the microcontroller with VDD 2.6V and VPP 5.6V.

After sending the command with those voltages:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 10:45:15 pm
My point was that before the mysterious commands, 07F0 held 0003 and 07F1 held 0003. After them, they seem to held FFFF, which are subsequently changed into 0004 by those two writes.

However, you can see on 949230: FLASH_READ_B, that 07ED holds 0281. This means that "66" followed by four 0 bits, or "31" doesn't actually wipe all the flash, but if it actually actually wipes anything, it only clears a few bytes.

Ok, got it now.

I think I know what it is... In WRITER I found a string telling the user that the flash chip is "overused" (when erased >1000 times).

So best guess is that they write the use count there. To be sure the value is always written correctly (not failed when power is lost during writing) they do it in 2 writes updating the 2 value.

 :)

Using "PADAUK-P-003-PFS154_SimpleBlink_NoPinCheck.txt" as example:

   55103: FLASH_READ_A

            ADDR DATA ?
            -----------
            07EF 1FFE 0
            07F0 0003 0
            07F1 0003 1

==> use count = 3

92201: ??? (1010010110100101101001011010001100011010101000010)
158597: ??? (1010010110100101101001011010011001111010101000010)
one of those is ERASE

    737022: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 0004 3FFF 3FFF 3FFF

    820818: FLASH_WRITE_B

            ADDR -W1- -W2- -W3- -W4-
            ------------------------
            07F0 3FFF 0004 3FFF 3FFF

949230: FLASH_READ_B

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 1FFF 0
            07E2 1FFF 1
            07E3 1FFF 1
            07E4 3FFF 1
            07E5 1FFF 1
            07E6 1FFF 1
            07E7 1FFF 1
            07E8 3FFF 1
            07E9 1FFF 1
            07EA 1FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0004 0
            07F1 0004 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1FFF 1
            07F9 3FFF 1
            07FA 1FFF 1
            07FB 3FFF 1
            07FC 1FFF 1
            07FD 3FFF 1
            07FE 1FFF 1
            07FF 3FFF 1

==> now use count is 4

BTW: This 0x1FFF read backs are for sure not correct. I know for sure that 0x3FFF is at most places there (in a previous posting I used LDSPTL/LDSPTH and soft SPI to read back the content of a real IC).

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 10:56:36 pm
Hi,

  92201: ? ? ? (1010010110100101101001011010 00110001 1010101000010) => 0x31
158597: ? ? ? (1010010110100101101001011010 01100111 1010101000010) => 0x67

I still think command 31 is ERASE. Then WRITER waits internally some time doing nothing (assuming erase takes time) and then WRITER sends 0x67 (GET_STATUS or WAIT_FOR_ERASE_FINISH or ...) to find out if the erase finished for sure.


JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 25, 2018, 11:14:06 pm
My point was that before the mysterious commands, 07F0 held 0003 and 07F1 held 0003. After them, they seem to held FFFF, which are subsequently changed into 0004 by those two writes.
However, you can see on 949230: FLASH_READ_B, that 07ED holds 0281. This means that "66" followed by four 0 bits, or "31" doesn't actually wipe all the flash, but if it actually actually wipes anything, it only clears a few bytes.

I think those values (0x7ED, 0x7EE) might be FIXED for IC identification??. So they just can not get erased.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 25, 2018, 11:59:15 pm
BTW: This 0x1FFF read backs are for sure not correct. I know for sure that 0x3FFF is at most places there (in a previous posting I used LDSPTL/LDSPTH and soft SPI to read back the content of a real IC).
I am not sure, but it could be possible that data from writer to IC is sampled on the rising edge, but on the falling edge for the IC? maybe that's why I'm getting those weird, useless trailing bits and why they are sometimes read as 1FFF instead of 3FFF.
I think those values (0x7ED, 0x7EE) might be FIXED for IC identification??. So they just can not get erased.
That actually makes sense.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 26, 2018, 01:40:49 am
So apparently yes, the data from writer to IC gets sampled on rising edge, but from IC to writer gets sampled on the falling edge.

If we parse "Verify" on the falling edge we get:
Code: [Select]
    804582: FLASH_READ_A_N2

            ADDR DATA ?
            -----------
            0000 0060 0
            0001 1F00 0
            0002 0300 0
            0003 3FFA 0
            0004 0306 0
            0005 3FFC 1
            0006 0330 0
            0007 1F80 1
            0008 03B2 0
            0009 0E38 0
            000A 0302 0
            000B 3FFC 0
            000C 07FF 0
            000D 20E0 1
            000E 3FD8 0
            000F 1783 1
            0010 1F23 1
            0011 1E0B 0
            0012 1781 1
            0013 3C80 0
            0014 2023 0
            0015 1F01 1
            0016 00C3 1
            0017 300C 1
            0018 0180 0
            0019 2037 1
            001A 1F90 1
            001B 11D0 1
            001C 301B 1
            001D 2E03 1
            001E 19C0 1
            001F 2FFE 0
            0020 0C03 1
            0021 038F 0
            0022 0381 0
            0023 13F0 0
            0024 3022 0
            0025 3FC0 1
            0026 300F 1
            0027 2F0D 1
            0028 0118 1
            0029 3890 0
            002A 303B 0
            002B 2E00 1
            002C 0386 1
            002D 360C 0
            002E 230C 0
            002F 1EDF 1
            0030 1785 1
            0031 1F00 0
            0032 1F06 0
            0033 000C 0
            0034 1708 0
            0035 000E 0
            0036 100A 0
            0037 2B08 0
            0038 2D0A 0
            0039 2000 1
            003A 2405 1
            003B 2103 1
            003C 3481 1
            003D 2027 1
            003E 3F21 1
            003F 3DA1 1
            0040 207F 1
            0041 3B0D 1
            0042 250B 1
            0043 0B21 1
            0044 38A1 1
            0045 2008 0
            0046 3231 1
            0047 203F 1
            0048 3921 1
            0049 3C81 1
            004A 2001 1
            004B 31E1 1
            004C 2007 1
            004D 3F81 1
            004E 2047 1
            004F 3881 1
            0050 201F 1
            0051 3F81 1
            0052 2023 1
            0053 20B7 1
            0054 0197 1
            0055 1FE3 1
            0056 1EC0 0
            0057 3E03 1
            0058 0F83 1
            0059 2F82 0
            005A 03C0 0
            005B 2E16 0
            005C 0063 0
            005D 301C 0
            005E 03C0 0
            005F 30D8 1
            0060 11C3 1
            0061 30D8 1
            0062 3C90 1
            0063 2F03 1
            0064 1BC3 1
            0065 2F8E 0
            0066 0FC0 0
            0067 2E76 0
            0068 0062 0
            0069 3078 0
            006A 2380 0
            006B 30F8 1
            006C 2381 1
            006D 30F9 1
            006E 303F 1
            006F 3FFF 1
            0070 3FFF 1
            0071 3FFF 1
            0072 3FFF 1
            0073 3FFF 1
            0074 3FFF 1
            0075 3FFF 1
            0076 3FFF 1
            0077 3FFF 1
            0078 3FFF 1
            0079 3FFF 1
            007A 3FFF 1
            007B 3FFF 1
            007C 3FFF 1
            007D 3FFF 1
            007E 3FFF 1
            007F 3FFF 1
            0080 3FFF 1
            0081 3FFF 1
            0082 3FFF 1
            0083 3FFF 1
            0084 3FFF 1
            0085 3FFF 1
            0086 3FFF 1
            0087 3FFF 1
            0088 3FFF 1
            0089 3FFF 1
            008A 3FFF 1
            008B 3FFF 1
            008C 3FFF 1
            008D 3FFF 1
            008E 3FFF 1
            008F 3FFF 1
            0090 3FFF 1
            0091 3FFF 1
            0092 3FFF 1
            0093 3FFF 1
            0094 3FFF 1
            0095 3FFF 1
            0096 3FFF 1
            0097 3FFF 1
            0098 3FFF 1
            0099 3FFF 1
            009A 3FFF 1
            009B 3FFF 1
            009C 3FFF 1
            009D 3FFF 1
            009E 3FFF 1
            009F 3FFF 1
            00A0 3FFF 1
            00A1 3FFF 1
            00A2 3FFF 1
            00A3 3FFF 1
            00A4 3FFF 1
            00A5 3FFF 1
            00A6 3FFF 1
            00A7 3FFF 1
            00A8 3FFF 1
            00A9 3FFF 1
            00AA 3FFF 1
            00AB 3FFF 1
            00AC 3FFF 1
            00AD 3FFF 1
            00AE 3FFF 1
            00AF 3FFF 1
            00B0 3FFF 1
            00B1 3FFF 1
            00B2 3FFF 1
            00B3 3FFF 1
            00B4 3FFF 1
            00B5 3FFF 1
            00B6 3FFF 1
            00B7 3FFF 1
            00B8 3FFF 1
            00B9 3FFF 1
            00BA 3FFF 1
            00BB 3FFF 1
            00BC 3FFF 1
            00BD 3FFF 1
            00BE 3FFF 1
            00BF 3FFF 1
            00C0 3FFF 1
            00C1 3FFF 1
            00C2 3FFF 1
            00C3 3FFF 1
            00C4 3FFF 1
            00C5 3FFF 1
            00C6 3FFF 1
            00C7 3FFF 1
            00C8 3FFF 1
            00C9 3FFF 1
            00CA 3FFF 1
            00CB 3FFF 1
            00CC 3FFF 1
            00CD 3FFF 1
            00CE 3FFF 1
            00CF 3FFF 1
            00D0 3FFF 1
            00D1 3FFF 1
            00D2 3FFF 1
            00D3 3FFF 1
            00D4 3FFF 1
            00D5 3FFF 1
            00D6 3FFF 1
            00D7 3FFF 1
            00D8 3FFF 1
            00D9 3FFF 1
            00DA 3FFF 1
            00DB 3FFF 1
            00DC 3FFF 1
            00DD 3FFF 1
            00DE 3FFF 1
            00DF 3FFF 1
            00E0 3FFF 1
            00E1 3FFF 1
            00E2 3FFF 1
            00E3 3FFF 1
            00E4 3FFF 1
            00E5 3FFF 1
            00E6 3FFF 1
            00E7 3FFF 1
            00E8 3FFF 1
            00E9 3FFF 1
            00EA 3FFF 1
            00EB 3FFF 1
            00EC 3FFF 1
            00ED 3FFF 1
            00EE 3FFF 1
            00EF 3FFF 1
            00F0 3FFF 1
            00F1 3FFF 1
            00F2 3FFF 1
            00F3 3FFF 1
            00F4 3FFF 1
            00F5 3FFF 1
            00F6 3FFF 1
            00F7 3FFF 1
            00F8 3FFF 1
            00F9 3FFF 1
            00FA 3FFF 1
            00FB 3FFF 1
            00FC 3FFF 1
            00FD 3FFF 1
            00FE 3FFF 1
            00FF 3FFF 1
            0100 3FFF 1
            0101 3FFF 1
            0102 3FFF 1
            0103 3FFF 1
            0104 3FFF 1
            0105 3FFF 1
            0106 3FFF 1
            0107 3FFF 1
            0108 3FFF 1
            0109 3FFF 1
            010A 3FFF 1
            010B 3FFF 1
            010C 3FFF 1
            010D 3FFF 1
            010E 3FFF 1
            010F 3FFF 1
            0110 3FFF 1
            0111 3FFF 1
            0112 3FFF 1
            0113 3FFF 1
            0114 3FFF 1
            0115 3FFF 1
            0116 3FFF 1
            0117 3FFF 1
            0118 3FFF 1
            0119 3FFF 1
            011A 3FFF 1
            011B 3FFF 1
            011C 3FFF 1
            011D 3FFF 1
            011E 3FFF 1
            011F 3FFF 1
            0120 3FFF 1
            0121 3FFF 1
            0122 3FFF 1
            0123 3FFF 1
            0124 3FFF 1
            0125 3FFF 1
            0126 3FFF 1
            0127 3FFF 1
            0128 3FFF 1
            0129 3FFF 1
            012A 3FFF 1
            012B 3FFF 1
            012C 3FFF 1
            012D 3FFF 1
            012E 3FFF 1
            012F 3FFF 1
            0130 3FFF 1
            0131 3FFF 1
            0132 3FFF 1
            0133 3FFF 1
            0134 3FFF 1
            0135 3FFF 1
            0136 3FFF 1
            0137 3FFF 1
            0138 3FFF 1
            0139 3FFF 1
            013A 3FFF 1
            013B 3FFF 1
            013C 3FFF 1
            013D 3FFF 1
            013E 3FFF 1
            013F 3FFF 1
            0140 3FFF 1
            0141 3FFF 1
            0142 3FFF 1
            0143 3FFF 1
            0144 3FFF 1
            0145 3FFF 1
            0146 3FFF 1
            0147 3FFF 1
            0148 3FFF 1
            0149 3FFF 1
            014A 3FFF 1
            014B 3FFF 1
            014C 3FFF 1
            014D 3FFF 1
            014E 3FFF 1
            014F 3FFF 1
            0150 3FFF 1
            0151 3FFF 1
            0152 3FFF 1
            0153 3FFF 1
            0154 3FFF 1
            0155 3FFF 1
            0156 3FFF 1
            0157 3FFF 1
            0158 3FFF 1
            0159 3FFF 1
            015A 3FFF 1
            015B 3FFF 1
            015C 3FFF 1
            015D 3FFF 1
            015E 3FFF 1
            015F 3FFF 1
            0160 3FFF 1
            0161 3FFF 1
            0162 3FFF 1
            0163 3FFF 1
            0164 3FFF 1
            0165 3FFF 1
            0166 3FFF 1
            0167 3FFF 1
            0168 3FFF 1
            0169 3FFF 1
            016A 3FFF 1
            016B 3FFF 1
            016C 3FFF 1
            016D 3FFF 1
            016E 3FFF 1
            016F 3FFF 1
            0170 3FFF 1
            0171 3FFF 1
            0172 3FFF 1
            0173 3FFF 1
            0174 3FFF 1
            0175 3FFF 1
            0176 3FFF 1
            0177 3FFF 1
            0178 3FFF 1
            0179 3FFF 1
            017A 3FFF 1
            017B 3FFF 1
            017C 3FFF 1
            017D 3FFF 1
            017E 3FFF 1
            017F 3FFF 1
            0180 3FFF 1
            0181 3FFF 1
            0182 3FFF 1
            0183 3FFF 1
            0184 3FFF 1
            0185 3FFF 1
            0186 3FFF 1
            0187 3FFF 1
            0188 3FFF 1
            0189 3FFF 1
            018A 3FFF 1
            018B 3FFF 1
            018C 3FFF 1
            018D 3FFF 1
            018E 3FFF 1
            018F 3FFF 1
            0190 3FFF 1
            0191 3FFF 1
            0192 3FFF 1
            0193 3FFF 1
            0194 3FFF 1
            0195 3FFF 1
            0196 3FFF 1
            0197 3FFF 1
            0198 3FFF 1
            0199 3FFF 1
            019A 3FFF 1
            019B 3FFF 1
            019C 3FFF 1
            019D 3FFF 1
            019E 3FFF 1
            019F 3FFF 1
            01A0 3FFF 1
            01A1 3FFF 1
            01A2 3FFF 1
            01A3 3FFF 1
            01A4 3FFF 1
            01A5 3FFF 1
            01A6 3FFF 1
            01A7 3FFF 1
            01A8 3FFF 1
            01A9 3FFF 1
            01AA 3FFF 1
            01AB 3FFF 1
            01AC 3FFF 1
            01AD 3FFF 1
            01AE 3FFF 1
            01AF 3FFF 1
            01B0 3FFF 1
            01B1 3FFF 1
            01B2 3FFF 1
            01B3 3FFF 1
            01B4 3FFF 1
            01B5 3FFF 1
            01B6 3FFF 1
            01B7 3FFF 1
            01B8 3FFF 1
            01B9 3FFF 1
            01BA 3FFF 1
            01BB 3FFF 1
            01BC 3FFF 1
            01BD 3FFF 1
            01BE 3FFF 1
            01BF 3FFF 1
            01C0 3FFF 1
            01C1 3FFF 1
            01C2 3FFF 1
            01C3 3FFF 1
            01C4 3FFF 1
            01C5 3FFF 1
            01C6 3FFF 1
            01C7 3FFF 1
            01C8 3FFF 1
            01C9 3FFF 1
            01CA 3FFF 1
            01CB 3FFF 1
            01CC 3FFF 1
            01CD 3FFF 1
            01CE 3FFF 1
            01CF 3FFF 1
            01D0 3FFF 1
            01D1 3FFF 1
            01D2 3FFF 1
            01D3 3FFF 1
            01D4 3FFF 1
            01D5 3FFF 1
            01D6 3FFF 1
            01D7 3FFF 1
            01D8 3FFF 1
            01D9 3FFF 1
            01DA 3FFF 1
            01DB 3FFF 1
            01DC 3FFF 1
            01DD 3FFF 1
            01DE 3FFF 1
            01DF 3FFF 1
            01E0 3FFF 1
            01E1 3FFF 1
            01E2 3FFF 1
            01E3 3FFF 1
            01E4 3FFF 1
            01E5 3FFF 1
            01E6 3FFF 1
            01E7 3FFF 1
            01E8 3FFF 1
            01E9 3FFF 1
            01EA 3FFF 1
            01EB 3FFF 1
            01EC 3FFF 1
            01ED 3FFF 1
            01EE 3FFF 1
            01EF 3FFF 1
            01F0 3FFF 1
            01F1 3FFF 1
            01F2 3FFF 1
            01F3 3FFF 1
            01F4 3FFF 1
            01F5 3FFF 1
            01F6 3FFF 1
            01F7 3FFF 1
            01F8 3FFF 1
            01F9 3FFF 1
            01FA 3FFF 1
            01FB 3FFF 1
            01FC 3FFF 1
            01FD 3FFF 1
            01FE 3FFF 1
            01FF 3FFF 1
            0200 3FFF 1
            0201 3FFF 1
            0202 3FFF 1
            0203 3FFF 1
            0204 3FFF 1
            0205 3FFF 1
            0206 3FFF 1
            0207 3FFF 1
            0208 3FFF 1
            0209 3FFF 1
            020A 3FFF 1
            020B 3FFF 1
            020C 3FFF 1
            020D 3FFF 1
            020E 3FFF 1
            020F 3FFF 1
            0210 3FFF 1
            0211 3FFF 1
            0212 3FFF 1
            0213 3FFF 1
            0214 3FFF 1
            0215 3FFF 1
            0216 3FFF 1
            0217 3FFF 1
            0218 3FFF 1
            0219 3FFF 1
            021A 3FFF 1
            021B 3FFF 1
            021C 3FFF 1
            021D 3FFF 1
            021E 3FFF 1
            021F 3FFF 1
            0220 3FFF 1
            0221 3FFF 1
            0222 3FFF 1
            0223 3FFF 1
            0224 3FFF 1
            0225 3FFF 1
            0226 3FFF 1
            0227 3FFF 1
            0228 3FFF 1
            0229 3FFF 1
            022A 3FFF 1
            022B 3FFF 1
            022C 3FFF 1
            022D 3FFF 1
            022E 3FFF 1
            022F 3FFF 1
            0230 3FFF 1
            0231 3FFF 1
            0232 3FFF 1
            0233 3FFF 1
            0234 3FFF 1
            0235 3FFF 1
            0236 3FFF 1
            0237 3FFF 1
            0238 3FFF 1
            0239 3FFF 1
            023A 3FFF 1
            023B 3FFF 1
            023C 3FFF 1
            023D 3FFF 1
            023E 3FFF 1
            023F 3FFF 1
            0240 3FFF 1
            0241 3FFF 1
            0242 3FFF 1
            0243 3FFF 1
            0244 3FFF 1
            0245 3FFF 1
            0246 3FFF 1
            0247 3FFF 1
            0248 3FFF 1
            0249 3FFF 1
            024A 3FFF 1
            024B 3FFF 1
            024C 3FFF 1
            024D 3FFF 1
            024E 3FFF 1
            024F 3FFF 1
            0250 3FFF 1
            0251 3FFF 1
            0252 3FFF 1
            0253 3FFF 1
            0254 3FFF 1
            0255 3FFF 1
            0256 3FFF 1
            0257 3FFF 1
            0258 3FFF 1
            0259 3FFF 1
            025A 3FFF 1
            025B 3FFF 1
            025C 3FFF 1
            025D 3FFF 1
            025E 3FFF 1
            025F 3FFF 1
            0260 3FFF 1
            0261 3FFF 1
            0262 3FFF 1
            0263 3FFF 1
            0264 3FFF 1
            0265 3FFF 1
            0266 3FFF 1
            0267 3FFF 1
            0268 3FFF 1
            0269 3FFF 1
            026A 3FFF 1
            026B 3FFF 1
            026C 3FFF 1
            026D 3FFF 1
            026E 3FFF 1
            026F 3FFF 1
            0270 3FFF 1
            0271 3FFF 1
            0272 3FFF 1
            0273 3FFF 1
            0274 3FFF 1
            0275 3FFF 1
            0276 3FFF 1
            0277 3FFF 1
            0278 3FFF 1
            0279 3FFF 1
            027A 3FFF 1
            027B 3FFF 1
            027C 3FFF 1
            027D 3FFF 1
            027E 3FFF 1
            027F 3FFF 1
            0280 3FFF 1
            0281 3FFF 1
            0282 3FFF 1
            0283 3FFF 1
            0284 3FFF 1
            0285 3FFF 1
            0286 3FFF 1
            0287 3FFF 1
            0288 3FFF 1
            0289 3FFF 1
            028A 3FFF 1
            028B 3FFF 1
            028C 3FFF 1
            028D 3FFF 1
            028E 3FFF 1
            028F 3FFF 1
            0290 3FFF 1
            0291 3FFF 1
            0292 3FFF 1
            0293 3FFF 1
            0294 3FFF 1
            0295 3FFF 1
            0296 3FFF 1
            0297 3FFF 1
            0298 3FFF 1
            0299 3FFF 1
            029A 3FFF 1
            029B 3FFF 1
            029C 3FFF 1
            029D 3FFF 1
            029E 3FFF 1
            029F 3FFF 1
            02A0 3FFF 1
            02A1 3FFF 1
            02A2 3FFF 1
            02A3 3FFF 1
            02A4 3FFF 1
            02A5 3FFF 1
            02A6 3FFF 1
            02A7 3FFF 1
            02A8 3FFF 1
            02A9 3FFF 1
            02AA 3FFF 1
            02AB 3FFF 1
            02AC 3FFF 1
            02AD 3FFF 1
            02AE 3FFF 1
            02AF 3FFF 1
            02B0 3FFF 1
            02B1 3FFF 1
            02B2 3FFF 1
            02B3 3FFF 1
            02B4 3FFF 1
            02B5 3FFF 1
            02B6 3FFF 1
            02B7 3FFF 1
            02B8 3FFF 1
            02B9 3FFF 1
            02BA 3FFF 1
            02BB 3FFF 1
            02BC 3FFF 1
            02BD 3FFF 1
            02BE 3FFF 1
            02BF 3FFF 1
            02C0 3FFF 1
            02C1 3FFF 1
            02C2 3FFF 1
            02C3 3FFF 1
            02C4 3FFF 1
            02C5 3FFF 1
            02C6 3FFF 1
            02C7 3FFF 1
            02C8 3FFF 1
            02C9 3FFF 1
            02CA 3FFF 1
            02CB 3FFF 1
            02CC 3FFF 1
            02CD 3FFF 1
            02CE 3FFF 1
            02CF 3FFF 1
            02D0 3FFF 1
            02D1 3FFF 1
            02D2 3FFF 1
            02D3 3FFF 1
            02D4 3FFF 1
            02D5 3FFF 1
            02D6 3FFF 1
            02D7 3FFF 1
            02D8 3FFF 1
            02D9 3FFF 1
            02DA 3FFF 1
            02DB 3FFF 1
            02DC 3FFF 1
            02DD 3FFF 1
            02DE 3FFF 1
            02DF 3FFF 1
            02E0 3FFF 1
            02E1 3FFF 1
            02E2 3FFF 1
            02E3 3FFF 1
            02E4 3FFF 1
            02E5 3FFF 1
            02E6 3FFF 1
            02E7 3FFF 1
            02E8 3FFF 1
            02E9 3FFF 1
            02EA 3FFF 1
            02EB 3FFF 1
            02EC 3FFF 1
            02ED 3FFF 1
            02EE 3FFF 1
            02EF 3FFF 1
            02F0 3FFF 1
            02F1 3FFF 1
            02F2 3FFF 1
            02F3 3FFF 1
            02F4 3FFF 1
            02F5 3FFF 1
            02F6 3FFF 1
            02F7 3FFF 1
            02F8 3FFF 1
            02F9 3FFF 1
            02FA 3FFF 1
            02FB 3FFF 1
            02FC 3FFF 1
            02FD 3FFF 1
            02FE 3FFF 1
            02FF 3FFF 1
            0300 3FFF 1
            0301 3FFF 1
            0302 3FFF 1
            0303 3FFF 1
            0304 3FFF 1
            0305 3FFF 1
            0306 3FFF 1
            0307 3FFF 1
            0308 3FFF 1
            0309 3FFF 1
            030A 3FFF 1
            030B 3FFF 1
            030C 3FFF 1
            030D 3FFF 1
            030E 3FFF 1
            030F 3FFF 1
            0310 3FFF 1
            0311 3FFF 1
            0312 3FFF 1
            0313 3FFF 1
            0314 3FFF 1
            0315 3FFF 1
            0316 3FFF 1
            0317 3FFF 1
            0318 3FFF 1
            0319 3FFF 1
            031A 3FFF 1
            031B 3FFF 1
            031C 3FFF 1
            031D 3FFF 1
            031E 3FFF 1
            031F 3FFF 1
            0320 3FFF 1
            0321 3FFF 1
            0322 3FFF 1
            0323 3FFF 1
            0324 3FFF 1
            0325 3FFF 1
            0326 3FFF 1
            0327 3FFF 1
            0328 3FFF 1
            0329 3FFF 1
            032A 3FFF 1
            032B 3FFF 1
            032C 3FFF 1
            032D 3FFF 1
            032E 3FFF 1
            032F 3FFF 1
            0330 3FFF 1
            0331 3FFF 1
            0332 3FFF 1
            0333 3FFF 1
            0334 3FFF 1
            0335 3FFF 1
            0336 3FFF 1


The unknown bit is thus probably just garbage from switching from input to output.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 26, 2018, 04:32:52 am
Some more info about the jumpers of the programmer. If you connect JP2, you will have the following pinout at the 40 pin ZIF socket:

pinsignal
5VDD
6PA7
7PA6
8PA5
33PA3
34PA4
35PA0
36GND

As described in my last posting, the bottom 8 pins of the ZIF socket are always connected to the programmer signals, and the jumpers are just connecting it to the other pins. This means you can measure the pinout for the other jumpers with a continuity tester.

For my Padauk SOT-23-6 to DIP14 adapter this means I just have to insert the adapter with a shift of 1, see attached image. Then I can use this writer line in my PRE file and it works:

Code: [Select]
.writer package 14, 4, 32, 8, 9, 7, 6, 32, 11, 0x0000, 0x0000, 1

The last number 1 is for the IC shift. But the connections are defined by the jumpers, so you can't just set it to any value you want. I guess it is only used for the open/short tests and for the GUI.

So no need anymore for a custom connector board or the jumper wire mess on JP7 :) Maybe this helps someone who also have a PMS150C in SOT-23-6, the manual is not very clear about the required writer setup. BTW, when starting the writer software, it still says "Check Jump: S08: JP2 /IC Shift 4". I guess it reads this from an internal database for the PMS150C chip, and ignores the custom writer declaration of the PDK file. It still works, just insert it with a IC shift of 1.

PS: how were the nice chip diagrams at https://free-pdk.github.io drawn? I used KiCad for my diagram and copied it to Gimp and then edited it there, but I guess there is some software out there which makes it easier?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 26, 2018, 09:48:53 am
So apparently yes, the data from writer to IC gets sampled on rising edge, but from IC to writer gets sampled on the falling edge.

If we parse "Verify" on the falling edge we get:
Code: [Select]
    804582: FLASH_READ_A_N2

            ADDR DATA ?
            -----------
            0000 0060 0
            0001 1F00 0
            0002 0300 0
...

The unknown bit is thus probably just garbage from switching from input to output.

Unfortunately this does not seem right as well. "Verify" should read back the same content as in SimpleBlink PDK starting with "0070 ...".

I made a new capture of "Verify" using higher sampling frequency (5MHz). Maybe this will solve the "read" instability.
To increase buffer size I removed the analog voltage capture.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 26, 2018, 10:20:16 am
PS: how were the nice chip diagrams at https://free-pdk.github.io drawn? I used KiCad for my diagram and copied it to Gimp and then edited it there, but I guess there is some software out there which makes it easier?

Hi,

I repurposed "James' Dodgy Arduino-Oriented Pinout Maker For Microcontrollers" from here: https://github.com/sleemanj/ArduinoOrientedChipPinoutCreator
Just some hacking and fiddeling later it is now possible to create one of those pictures using just a simple syntax like this:

Code: [Select]
        {
          Name   : 'PFS154-S16/D16',
          Package: '2SIDED'  ,
          Pins   :  16     ,
          PRC    :   { Vcc:5, Gnd:12, Reset: 8, XTAL1: 6, XTAL2:7 },
          PWM    :   [1,2,3,4,8,9,10,11,15,16],
          PA :   [11,0,0,9,10,8,7,6],
          PB :   [13,14,15,16,1,2,3,4],
          Analog :   [],
          Peripherals: { }
        }


One big problem is to capture the output image. Right now I print it to PDF or just take a screenshot from browser.
I plan to automate this by adding a canvas capture and save to image function later.

When all is fixed I will release the generator on github.

Have fun,

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 26, 2018, 11:01:19 am
So apparently yes, the data from writer to IC gets sampled on rising edge, but from IC to writer gets sampled on the falling edge.

If we parse "Verify" on the falling edge we get:
Code: [Select]
    804582: FLASH_READ_A_N2

            ADDR DATA ?
            -----------
            0000 0060 0
            0001 1F00 0
            0002 0300 0
...


The unknown bit is thus probably just garbage from switching from input to output.

Unfortunately this does not seem right as well. "Verify" should read back the same content as in SimpleBlink PDK starting with "0070 ...".

I made a new capture of "Verify" using higher sampling frequency (5MHz). Maybe this will solve the "read" instability.
To increase buffer size I removed the analog voltage capture.

JS
Code: [Select]
      2527: FLASH_READ_A
            No data (dummy read)

     67967: FLASH_READ_A
            No data (dummy read)

    179611: FLASH_READ_A

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 3FFF 0
            07E2 3FFF 1
            07E3 3FFF 1
            07E4 3FFF 1
            07E5 3FFF 1
            07E6 3FFF 1
            07E7 3FFF 1
            07E8 3FFF 1
            07E9 3FFF 1
            07EA 3FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027A 1
            07EF 1FFE 0
            07F0 0027 0
            07F1 0025 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F74 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 3FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

    316754: FLASH_READ_A
            No data (dummy read)

   1711828: FLASH_READ_A

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 3FFF 0
            07E2 3FFF 1
            07E3 3FFF 1
            07E4 3FFF 1
            07E5 3FFF 1
            07E6 3FFF 1
            07E7 3FFF 1
            07E8 3FFF 1
            07E9 3FFF 1
            07EA 3FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0681 1
            07EE 027E 1
            07EF 1FFE 0
            07F0 0065 0
            07F1 0025 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F74 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 3FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

   1848671: FLASH_READ_A

            ADDR DATA ?
            -----------
            07E0 3FFF 0
            07E1 3FFF 0
            07E2 3FFF 1
            07E3 3FFF 1
            07E4 3FFF 1
            07E5 3FFF 1
            07E6 3FFF 1
            07E7 3FFF 1
            07E8 3FFF 1
            07E9 3FFF 1
            07EA 3FFF 1
            07EB 3FFF 1
            07EC 3FFF 1
            07ED 0281 1
            07EE 027E 1
            07EF 3FFE 0
            07F0 006D 0
            07F1 006D 1
            07F2 3FFF 0
            07F3 3FFF 0
            07F4 3FFF 1
            07F5 3FFF 1
            07F6 3FFF 1
            07F7 3FFF 1
            07F8 1850 1
            07F9 3F54 1
            07FA 3FFF 1
            07FB 3FFF 1
            07FC 3FFF 1
            07FD 3FFF 1
            07FE 0282 1
            07FF 31FD 1

   1985807: FLASH_READ_A

            ADDR DATA ?
            -----------
            0000 0070 0
            0001 2F00 0
            0002 0182 0
            0003 3FED 0
            0004 018B 0
            0005 3FEE 1
            0006 019E 0
            0007 2F81 1
            0008 019B 0
            0009 2F1C 0
            000A 0183 0
            000B 3FFE 0
            000C 2BFF 0
            000D 30D4 1
            000E 3FED 0
            000F 0B81 1
            0010 1F91 1
            0011 2F05 0
            0012 0B80 1
            0013 1AD0 0
            0014 3013 0
            0015 1F90 1
            0016 0063 1
            0017 3016 1
            0018 1180 0
            0019 3016 1
            001A 3D90 1
            001B 18D0 1
            001C 301B 1
            001D 2F01 1
            001E 1950 1
            001F 2FFF 0
            0020 1C01 1
            0021 018B 0
            0022 0B83 0
            0023 3AD0 0
            0024 3023 0
            0025 1B50 1
            0026 304F 1
            0027 2F04 1
            0028 0188 1
            0029 18D0 0
            002A 3029 0
            002B 2F02 1
            002C 0182 1
            002D 1304 0
            002E 1305 0
            002F 2F6E 1
            0030 0B82 1
            0031 2F00 0
            0032 0B83 0
            0033 0006 0
            0034 0B04 0
            0035 0007 0
            0036 0805 0
            0037 1584 0
            0038 1685 0
            0039 1004 1
            003A 1282 1
            003B 3083 1
            003C 1A40 1
            003D 3077 1
            003E 1FB0 1
            003F 1ED1 1
            0040 303F 1
            0041 1D84 1
            0042 1685 1
            0043 0591 1
            0044 18D0 1
            0045 3044 0
            0046 1950 1
            0047 303F 1
            0048 1D90 1
            0049 1BF0 1
            004A 3049 1
            004B 18D0 1
            004C 304B 1
            004D 1B50 1
            004E 302B 1
            004F 18D0 1
            0050 304F 1
            0051 1B50 1
            0052 3011 1
            0053 3053 1
            0054 018B 1
            0055 1ED1 1
            0056 1ED0 0
            0057 2F07 1
            0058 0BC1 1
            0059 2F8A 0
            005A 1BC0 0
            005B 2FD6 0
            005C 0063 0
            005D 30DC 0
            005E 11C0 0
            005F 305C 1
            0060 11C1 1
            0061 305C 1
            0062 1CD0 1
            0063 2F03 1
            0064 0BC1 1
            0065 2F8E 0
            0066 0BC0 0
            0067 2F56 0
            0068 0063 0
            0069 3068 0
            006A 11C0 0
            006B 3068 1
            006C 31C1 1
            006D 3068 1
            006E 3056 1
            006F 3FFF 1
            0070 3FFF 1
            0071 3FFF 1
            0072 3FFF 1
            0073 3FFF 1
            0074 3FFF 1
            0075 3FFF 1
            0076 3FFF 1
            0077 3FFF 1
            0078 3FFF 1
            0079 3FFF 1
            007A 3FFF 1
            007B 3FFF 1
            007C 3FFF 1
            007D 3FFF 1
            007E 3FFF 1
            007F 3FFF 1
            0080 3FFF 1
            0081 3FFF 1
            0082 3FFF 1
            0083 3FFF 1
            0084 3FFF 1
            0085 3FFF 1
            0086 3FFF 1
            0087 3FFF 1
            0088 3FFF 1
            0089 3FFF 1
            008A 3FFF 1
            008B 3FFF 1
            008C 3FFF 1
            008D 3FFF 1
            008E 3FFF 1
            008F 3FFF 1
            0090 3FFF 1
            0091 3FFF 1
            0092 3FFF 1
            0093 3FFF 1
            0094 3FFF 1
            0095 3FFF 1
            0096 3FFF 1
            0097 3FFF 1
            0098 3FFF 1
            0099 3FFF 1
            009A 3FFF 1
            009B 3FFF 1
            009C 3FFF 1
            009D 3FFF 1
            009E 3FFF 1
            009F 3FFF 1
            00A0 3FFF 1
            00A1 3FFF 1
            00A2 3FFF 1
            00A3 3FFF 1
            00A4 3FFF 1
            00A5 3FFF 1
            00A6 3FFF 1
            00A7 3FFF 1
            00A8 3FFF 1
            00A9 3FFF 1
            00AA 3FFF 1
            00AB 3FFF 1
            00AC 3FFF 1
            00AD 3FFF 1
            00AE 3FFF 1
            00AF 3FFF 1
            00B0 3FFF 1
            00B1 3FFF 1
            00B2 3FFF 1
            00B3 3FFF 1
            00B4 3FFF 1
            00B5 3FFF 1
            00B6 3FFF 1
            00B7 3FFF 1
            00B8 3FFF 1
            00B9 3FFF 1
            00BA 3FFF 1
            00BB 3FFF 1
            00BC 3FFF 1
            00BD 3FFF 1
            00BE 3FFF 1
            00BF 3FFF 1
            00C0 3FFF 1
            00C1 3FFF 1
            00C2 3FFF 1
            00C3 3FFF 1
            00C4 3FFF 1
            00C5 3FFF 1
            00C6 3FFF 1
            00C7 3FFF 1
            00C8 3FFF 1
            00C9 3FFF 1
            00CA 3FFF 1
            00CB 3FFF 1
            00CC 3FFF 1
            00CD 3FFF 1
            00CE 3FFF 1
            00CF 3FFF 1
            00D0 3FFF 1
            00D1 3FFF 1
            00D2 3FFF 1
            00D3 3FFF 1
            00D4 3FFF 1
            00D5 3FFF 1
            00D6 3FFF 1
            00D7 3FFF 1
            00D8 3FFF 1
            00D9 3FFF 1
            00DA 3FFF 1
            00DB 3FFF 1
            00DC 3FFF 1
            00DD 3FFF 1
            00DE 3FFF 1
            00DF 3FFF 1
            00E0 3FFF 1
            00E1 3FFF 1
            00E2 3FFF 1
            00E3 3FFF 1
            00E4 3FFF 1
            00E5 3FFF 1
            00E6 3FFF 1
            00E7 3FFF 1
            00E8 3FFF 1
            00E9 3FFF 1
            00EA 3FFF 1
            00EB 3FFF 1
            00EC 3FFF 1
            00ED 3FFF 1
            00EE 3FFF 1
            00EF 3FFF 1
            00F0 3FFF 1
            00F1 3FFF 1
            00F2 3FFF 1
            00F3 3FFF 1
            00F4 3FFF 1
            00F5 3FFF 1
            00F6 3FFF 1
            00F7 3FFF 1
            00F8 3FFF 1
            00F9 3FFF 1
            00FA 3FFF 1
            00FB 3FFF 1
            00FC 3FFF 1
            00FD 3FFF 1
            00FE 3FFF 1
            00FF 3FFF 1
            0100 3FFF 1
            0101 3FFF 1
            0102 3FFF 1
            0103 3FFF 1
            0104 3FFF 1
            0105 3FFF 1
            0106 3FFF 1
            0107 3FFF 1
            0108 3FFF 1
            0109 3FFF 1
            010A 3FFF 1
            010B 3FFF 1
            010C 3FFF 1
            010D 3FFF 1
            010E 3FFF 1
            010F 3FFF 1
            0110 3FFF 1
            0111 3FFF 1
            0112 3FFF 1
            0113 3FFF 1
            0114 3FFF 1
            0115 3FFF 1
            0116 3FFF 1
            0117 3FFF 1
            0118 3FFF 1
            0119 3FFF 1
            011A 3FFF 1
            011B 3FFF 1
            011C 3FFF 1
            011D 3FFF 1
            011E 3FFF 1
            011F 3FFF 1
            0120 3FFF 1
            0121 3FFF 1
            0122 3FFF 1
            0123 3FFF 1
            0124 3FFF 1
            0125 3FFF 1
            0126 3FFF 1
            0127 3FFF 1
            0128 3FFF 1
            0129 3FFF 1
            012A 3FFF 1
            012B 3FFF 1
            012C 3FFF 1
            012D 3FFF 1
            012E 3FFF 1
            012F 3FFF 1
            0130 3FFF 1
            0131 3FFF 1
            0132 3FFF 1
            0133 3FFF 1
            0134 3FFF 1
            0135 3FFF 1
            0136 3FFF 1
            0137 3FFF 1
            0138 3FFF 1
            0139 3FFF 1
            013A 3FFF 1
            013B 3FFF 1
            013C 3FFF 1
            013D 3FFF 1
            013E 3FFF 1
            013F 3FFF 1
            0140 3FFF 1
            0141 3FFF 1
            0142 3FFF 1
            0143 3FFF 1
            0144 3FFF 1
            0145 3FFF 1
            0146 3FFF 1
            0147 3FFF 1
            0148 3FFF 1
            0149 3FFF 1
            014A 3FFF 1
            014B 3FFF 1
            014C 3FFF 1
            014D 3FFF 1
            014E 3FFF 1
            014F 3FFF 1
            0150 3FFF 1
            0151 3FFF 1
            0152 3FFF 1
            0153 3FFF 1
            0154 3FFF 1
            0155 3FFF 1
            0156 3FFF 1
            0157 3FFF 1
            0158 3FFF 1
            0159 3FFF 1
            015A 3FFF 1
            015B 3FFF 1
            015C 3FFF 1
            015D 3FFF 1
            015E 3FFF 1
            015F 3FFF 1
            0160 3FFF 1
            0161 3FFF 1
            0162 3FFF 1
            0163 3FFF 1
            0164 3FFF 1
            0165 3FFF 1
            0166 3FFF 1
            0167 3FFF 1
            0168 3FFF 1
            0169 3FFF 1
            016A 3FFF 1
            016B 3FFF 1
            016C 3FFF 1
            016D 3FFF 1
            016E 3FFF 1
            016F 3FFF 1
            0170 3FFF 1
            0171 3FFF 1
            0172 3FFF 1
            0173 3FFF 1
            0174 3FFF 1
            0175 3FFF 1
            0176 3FFF 1
            0177 3FFF 1
            0178 3FFF 1
            0179 3FFF 1
            017A 3FFF 1
            017B 3FFF 1
            017C 3FFF 1
            017D 3FFF 1
            017E 3FFF 1
            017F 3FFF 1
            0180 3FFF 1
            0181 3FFF 1
            0182 3FFF 1
            0183 3FFF 1
            0184 3FFF 1
            0185 3FFF 1
            0186 3FFF 1
            0187 3FFF 1
            0188 3FFF 1
            0189 3FFF 1
            018A 3FFF 1
            018B 3FFF 1
            018C 3FFF 1
            018D 3FFF 1
            018E 3FFF 1
            018F 3FFF 1
            0190 3FFF 1
            0191 3FFF 1
            0192 3FFF 1
            0193 3FFF 1
            0194 3FFF 1
            0195 3FFF 1
            0196 3FFF 1
            0197 3FFF 1
            0198 3FFF 1
            0199 3FFF 1
            019A 3FFF 1
            019B 3FFF 1
            019C 3FFF 1
            019D 3FFF 1
            019E 3FFF 1
            019F 3FFF 1
            01A0 3FFF 1
            01A1 3FFF 1
            01A2 3FFF 1
            01A3 3FFF 1
            01A4 3FFF 1
            01A5 3FFF 1
            01A6 3FFF 1
            01A7 3FFF 1
            01A8 3FFF 1
            01A9 3FFF 1
            01AA 3FFF 1
            01AB 3FFF 1
            01AC 3FFF 1
            01AD 3FFF 1
            01AE 3FFF 1
            01AF 3FFF 1
            01B0 3FFF 1
            01B1 3FFF 1
            01B2 3FFF 1
            01B3 3FFF 1
            01B4 3FFF 1
            01B5 3FFF 1
            01B6 3FFF 1
            01B7 3FFF 1
            01B8 3FFF 1
            01B9 3FFF 1
            01BA 3FFF 1
            01BB 3FFF 1
            01BC 3FFF 1
            01BD 3FFF 1
            01BE 3FFF 1
            01BF 3FFF 1
            01C0 3FFF 1
            01C1 3FFF 1
            01C2 3FFF 1
            01C3 3FFF 1
            01C4 3FFF 1
            01C5 3FFF 1
            01C6 3FFF 1
            01C7 3FFF 1
            01C8 3FFF 1
            01C9 3FFF 1
            01CA 3FFF 1
            01CB 3FFF 1
            01CC 3FFF 1
            01CD 3FFF 1
            01CE 3FFF 1
            01CF 3FFF 1
            01D0 3FFF 1
            01D1 3FFF 1
            01D2 3FFF 1
            01D3 3FFF 1
            01D4 3FFF 1
            01D5 3FFF 1
            01D6 3FFF 1
            01D7 3FFF 1
            01D8 3FFF 1
            01D9 3FFF 1
            01DA 3FFF 1
            01DB 3FFF 1
            01DC 3FFF 1
            01DD 3FFF 1
            01DE 3FFF 1
            01DF 3FFF 1
            01E0 3FFF 1
            01E1 3FFF 1
            01E2 3FFF 1
            01E3 3FFF 1
            01E4 3FFF 1
            01E5 3FFF 1
            01E6 3FFF 1
            01E7 3FFF 1
            01E8 3FFF 1
            01E9 3FFF 1
            01EA 3FFF 1
            01EB 3FFF 1
            01EC 3FFF 1
            01ED 3FFF 1
            01EE 3FFF 1
            01EF 3FFF 1
            01F0 3FFF 1
            01F1 3FFF 1
            01F2 3FFF 1
            01F3 3FFF 1
            01F4 3FFF 1
            01F5 3FFF 1
            01F6 3FFF 1
            01F7 3FFF 1
            01F8 3FFF 1
            01F9 3FFF 1
            01FA 3FFF 1
            01FB 3FFF 1
            01FC 3FFF 1
            01FD 3FFF 1
            01FE 3FFF 1
            01FF 3FFF 1
            0200 3FFF 1
            0201 3FFF 1
            0202 3FFF 1
            0203 3FFF 1
            0204 3FFF 1
            0205 3FFF 1
            0206 3FFF 1
            0207 3FFF 1
            0208 3FFF 1
            0209 3FFF 1
            020A 3FFF 1
            020B 3FFF 1
            020C 3FFF 1
            020D 3FFF 1
            020E 3FFF 1
            020F 3FFF 1
            0210 3FFF 1
            0211 3FFF 1
            0212 3FFF 1
            0213 3FFF 1
            0214 3FFF 1
            0215 3FFF 1
            0216 3FFF 1
            0217 3FFF 1
            0218 3FFF 1
            0219 3FFF 1
            021A 3FFF 1
            021B 3FFF 1
            021C 3FFF 1
            021D 3FFF 1
            021E 3FFF 1
            021F 3FFF 1
            0220 3FFF 1
            0221 3FFF 1
            0222 3FFF 1
            0223 3FFF 1
            0224 3FFF 1
            0225 3FFF 1
            0226 3FFF 1
            0227 3FFF 1
            0228 3FFF 1
            0229 3FFF 1
            022A 3FFF 1
            022B 3FFF 1
            022C 3FFF 1
            022D 3FFF 1
            022E 3FFF 1
            022F 3FFF 1
            0230 3FFF 1
            0231 3FFF 1
            0232 3FFF 1
            0233 3FFF 1
            0234 3FFF 1
            0235 3FFF 1
            0236 3FFF 1
            0237 3FFF 1
            0238 3FFF 1
            0239 3FFF 1
            023A 3FFF 1
            023B 3FFF 1
            023C 3FFF 1
            023D 3FFF 1
            023E 3FFF 1
            023F 3FFF 1
            0240 3FFF 1
            0241 3FFF 1
            0242 3FFF 1
            0243 3FFF 1
            0244 3FFF 1
            0245 3FFF 1
            0246 3FFF 1
            0247 3FFF 1
            0248 3FFF 1
            0249 3FFF 1
            024A 3FFF 1
            024B 3FFF 1
            024C 3FFF 1
            024D 3FFF 1
            024E 3FFF 1
            024F 3FFF 1
            0250 3FFF 1
            0251 3FFF 1
            0252 3FFF 1
            0253 3FFF 1
            0254 3FFF 1
            0255 3FFF 1
            0256 3FFF 1
            0257 3FFF 1
            0258 3FFF 1
            0259 3FFF 1
            025A 3FFF 1
            025B 3FFF 1
            025C 3FFF 1
            025D 3FFF 1
            025E 3FFF 1
            025F 3FFF 1
            0260 3FFF 1
            0261 3FFF 1
            0262 3FFF 1
            0263 3FFF 1
            0264 3FFF 1
            0265 3FFF 1
            0266 3FFF 1
            0267 3FFF 1
            0268 3FFF 1
            0269 3FFF 1
            026A 3FFF 1
            026B 3FFF 1
            026C 3FFF 1
            026D 3FFF 1
            026E 3FFF 1
            026F 3FFF 1
            0270 3FFF 1
            0271 3FFF 1
            0272 3FFF 1
            0273 3FFF 1
            0274 3FFF 1
            0275 3FFF 1
            0276 3FFF 1
            0277 3FFF 1
            0278 3FFF 1
            0279 3FFF 1
            027A 3FFF 1
            027B 3FFF 1
            027C 3FFF 1
            027D 3FFF 1
            027E 3FFF 1
            027F 3FFF 1
            0280 3FFF 1
            0281 3FFF 1
            0282 3FFF 1
            0283 3FFF 1
            0284 3FFF 1
            0285 3FFF 1
            0286 3FFF 1
            0287 3FFF 1
            0288 3FFF 1
            0289 3FFF 1
            028A 3FFF 1
            028B 3FFF 1
            028C 3FFF 1
            028D 3FFF 1
            028E 3FFF 1
            028F 3FFF 1
            0290 3FFF 1
            0291 3FFF 1
            0292 3FFF 1
            0293 3FFF 1
            0294 3FFF 1
            0295 3FFF 1
            0296 3FFF 1
            0297 3FFF 1
            0298 3FFF 1
            0299 3FFF 1
            029A 3FFF 1
            029B 3FFF 1
            029C 3FFF 1
            029D 3FFF 1
            029E 3FFF 1
            029F 3FFF 1
            02A0 3FFF 1
            02A1 3FFF 1
            02A2 3FFF 1
            02A3 3FFF 1
            02A4 3FFF 1
            02A5 3FFF 1
            02A6 3FFF 1
            02A7 3FFF 1
            02A8 3FFF 1
            02A9 3FFF 1
            02AA 3FFF 1
            02AB 3FFF 1
            02AC 3FFF 1
            02AD 3FFF 1
            02AE 3FFF 1
            02AF 3FFF 1
            02B0 3FFF 1
            02B1 3FFF 1
            02B2 3FFF 1
            02B3 3FFF 1
            02B4 3FFF 1
            02B5 3FFF 1
            02B6 3FFF 1
            02B7 3FFF 1
            02B8 3FFF 1
            02B9 3FFF 1
            02BA 3FFF 1
            02BB 3FFF 1
            02BC 3FFF 1
            02BD 3FFF 1
            02BE 3FFF 1
            02BF 3FFF 1
            02C0 3FFF 1
            02C1 3FFF 1
            02C2 3FFF 1
            02C3 3FFF 1
            02C4 3FFF 1
            02C5 3FFF 1
            02C6 3FFF 1
            02C7 3FFF 1
            02C8 3FFF 1
            02C9 3FFF 1
            02CA 3FFF 1
            02CB 3FFF 1
            02CC 3FFF 1
            02CD 3FFF 1
            02CE 3FFF 1
            02CF 3FFF 1
            02D0 3FFF 1
            02D1 3FFF 1
            02D2 3FFF 1
            02D3 3FFF 1
            02D4 3FFF 1
            02D5 3FFF 1
            02D6 3FFF 1
            02D7 3FFF 1
            02D8 3FFF 1
            02D9 3FFF 1
            02DA 3FFF 1
            02DB 3FFF 1
            02DC 3FFF 1
            02DD 3FFF 1
            02DE 3FFF 1
            02DF 3FFF 1
            02E0 3FFF 1
            02E1 3FFF 1
            02E2 3FFF 1
            02E3 3FFF 1
            02E4 3FFF 1
            02E5 3FFF 1
            02E6 3FFF 1
            02E7 3FFF 1
            02E8 3FFF 1
            02E9 3FFF 1
            02EA 3FFF 1
            02EB 3FFF 1
            02EC 3FFF 1
            02ED 3FFF 1
            02EE 3FFF 1
            02EF 3FFF 1
            02F0 3FFF 1
            02F1 3FFF 1
            02F2 3FFF 1
            02F3 3FFF 1
            02F4 3FFF 1
            02F5 3FFF 1
            02F6 3FFF 1
            02F7 3FFF 1
            02F8 3FFF 1
            02F9 3FFF 1
            02FA 3FFF 1
            02FB 3FFF 1
            02FC 3FFF 1
            02FD 3FFF 1
            02FE 3FFF 1
            02FF 3FFF 1
            0300 3FFF 1
            0301 3FFF 1
            0302 3FFF 1
            0303 3FFF 1
            0304 3FFF 1
            0305 3FFF 1
            0306 3FFF 1
            0307 3FFF 1
            0308 3FFF 1
            0309 3FFF 1
            030A 3FFF 1
            030B 3FFF 1
            030C 3FFF 1
            030D 3FFF 1
            030E 3FFF 1
            030F 3FFF 1
            0310 3FFF 1
            0311 3FFF 1
            0312 3FFF 1
            0313 3FFF 1
            0314 3FFF 1
            0315 3FFF 1
            0316 3FFF 1
            0317 3FFF 1
            0318 3FFF 1
            0319 3FFF 1
            031A 3FFF 1
            031B 3FFF 1
            031C 3FFF 1
            031D 3FFF 1
            031E 3FFF 1
            031F 3FFF 1
            0320 3FFF 1
            0321 3FFF 1
            0322 3FFF 1
            0323 3FFF 1
            0324 3FFF 1
            0325 3FFF 1
            0326 3FFF 1
            0327 3FFF 1
            0328 3FFF 1
            0329 3FFF 1
            032A 3FFF 1
            032B 3FFF 1
            032C 3FFF 1
            032D 3FFF 1
            032E 3FFF 1
            032F 3FFF 1
            0330 3FFF 1
            0331 3FFF 1
            0332 3FFF 1
            0333 3FFF 1
            0334 3FFF 1
            0335 3FFF 1
            0336 3FFF 1
            0337 3FFF 1
            0338 3FFF 1
            0339 3FFF 1
            033A 3FFF 1
            033B 3FFF 1
            033C 3FFF 1
            033D 3FFF 1
            033E 3FFF 1
            033F 3FFF 1
            0340 3FFF 1
            0341 3FFF 1
            0342 3FFF 1
            0343 3FFF 1
            0344 3FFF 1
            0345 3FFF 1
            0346 3FFF 1
            0347 3FFF 1
            0348 3FFF 1
            0349 3FFF 1
            034A 3FFF 1
            034B 3FFF 1
            034C 3FFF 1
            034D 3FFF 1
            034E 3FFF 1
            034F 3FFF 1
            0350 3FFF 1
            0351 3FFF 1
            0352 3FFF 1
            0353 3FFF 1
            0354 3FFF 1
            0355 3FFF 1
            0356 3FFF 1
            0357 3FFF 1
            0358 3FFF 1
            0359 3FFF 1
            035A 3FFF 1
            035B 3FFF 1
            035C 3FFF 1
            035D 3FFF 1
            035E 3FFF 1
            035F 3FFF 1
            0360 3FFF 1
            0361 3FFF 1
            0362 3FFF 1
            0363 3FFF 1
            0364 3FFF 1
            0365 3FFF 1
            0366 3FFF 1
            0367 3FFF 1
            0368 3FFF 1
            0369 3FFF 1
            036A 3FFF 1
            036B 3FFF 1
            036C 3FFF 1
            036D 3FFF 1
            036E 3FFF 1
            036F 3FFF 1
            0370 3FFF 1
            0371 3FFF 1
            0372 3FFF 1
            0373 3FFF 1
            0374 3FFF 1
            0375 3FFF 1
            0376 3FFF 1
            0377 3FFF 1
            0378 3FFF 1
            0379 3FFF 1
            037A 3FFF 1
            037B 3FFF 1
            037C 3FFF 1
            037D 3FFF 1
            037E 3FFF 1
            037F 3FFF 1
            0380 3FFF 1
            0381 3FFF 1
            0382 3FFF 1
            0383 3FFF 1
            0384 3FFF 1
            0385 3FFF 1
            0386 3FFF 1
            0387 3FFF 1
            0388 3FFF 1
            0389 3FFF 1
            038A 3FFF 1
            038B 3FFF 1
            038C 3FFF 1
            038D 3FFF 1
            038E 3FFF 1
            038F 3FFF 1
            0390 3FFF 1
            0391 3FFF 1
            0392 3FFF 1
            0393 3FFF 1
            0394 3FFF 1
            0395 3FFF 1
            0396 3FFF 1
            0397 3FFF 1
            0398 3FFF 1
            0399 3FFF 1
            039A 3FFF 1
            039B 3FFF 1
            039C 3FFF 1
            039D 3FFF 1
            039E 3FFF 1
            039F 3FFF 1
            03A0 3FFF 1
            03A1 3FFF 1
            03A2 3FFF 1
            03A3 3FFF 1
            03A4 3FFF 1
            03A5 3FFF 1
            03A6 3FFF 1
            03A7 3FFF 1
            03A8 3FFF 1
            03A9 3FFF 1
            03AA 3FFF 1
            03AB 3FFF 1
            03AC 3FFF 1
            03AD 3FFF 1
            03AE 3FFF 1
            03AF 3FFF 1
            03B0 3FFF 1
            03B1 3FFF 1
            03B2 3FFF 1
            03B3 3FFF 1
            03B4 3FFF 1
            03B5 3FFF 1
            03B6 3FFF 1
            03B7 3FFF 1
            03B8 3FFF 1
            03B9 3FFF 1
            03BA 3FFF 1
            03BB 3FFF 1
            03BC 3FFF 1
            03BD 3FFF 1
            03BE 3FFF 1
            03BF 3FFF 1
            03C0 3FFF 1
            03C1 3FFF 1
            03C2 3FFF 1
            03C3 3FFF 1
            03C4 3FFF 1
            03C5 3FFF 1
            03C6 3FFF 1
            03C7 3FFF 1
            03C8 3FFF 1
--- everything after this are just more 3FFF ---

I still had the same issue when parsing at the rising edge, but it looks fine and matches the decrypted PDK if sampling on the falling edge.

Commands, unlike sampling at the falling edge at 2MHz, also are properly detected.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 26, 2018, 11:14:10 am
Nope, after analyzing properly the .bin being read back I'm still getting one bit offs. I've attached the correct .bin and the two .bins read on falling and rising edges  :palm:

I'm also attaching the latest version of my parsing tools. "parsespivdd.py" is the script that converts the TXTs from Zeroplus to a series of frames, in case somebody manages to make any sense of this mess.

Example:
Code: [Select]
./parsespivdd.py --txt verify_5mhz.txt --data PA6_ICPDA --clock PA3_ICPCK --enable VDD --falling | tee verify_5mhz_frames_falling.txtRemove --falling to sample on the rising edge.

parsecommands.py has no options:
Code: [Select]
cat verify_5mhz_frames_falling.txt | ./parsecommands.py
EDIT: It looks like this could be still too slow for correct sampling:
(https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/?action=dlattach;attach=605575)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 26, 2018, 06:12:39 pm
Nope, after analyzing properly the .bin being read back I'm still getting one bit offs. I've attached the correct .bin and the two .bins read on falling and rising edges  :palm:

EDIT: It looks like this could be still too slow for correct sampling:
(https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/?action=dlattach;attach=605575)

Hi,

thanks for your hard work.

I don't think that the sampling frequency is the problem. Each clock cycle is clearly >=5 time cycles which implies that the real clock used is indeed 1 MHz only.

One possibility could be that you might need to add a delay before taking the sample:
e.g. CLK goes high, take the value from *next* sample for DAT. But this is very uncommon.

I also thought about the "garbage" bits in reads. From what I remember from the calibration routine:
It could be that this is an ACK from WRITER. So after IC sent out some bits, direction is changed and IC waits for signal from host. Either just a clock or clock+value (so sampling edge might change for this bit again).

I will be away from my WRITER/LogicAnalyzer for the next few days, participating 35C3. Anybody there? PM me if you like to meet.

JS
 
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 26, 2018, 06:22:29 pm
One big problem is to capture the output image. Right now I print it to PDF or just take a screenshot from browser.
I plan to automate this by adding a canvas capture and save to image function later.

When all is fixed I will release the generator on github.

Sounds good. Please add SVG output as well, or let me know when you are done and I can add it, because then I can just insert it in Open Office documents without bitmap quality loss.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 27, 2018, 01:28:38 am
I have been able to extract 1:1 the binary from Verify_5MHz.txt by using a weird trick, instead of sampling at rising or falling edge.

For each clock cycle, I output a one if the data pin is high for at least one sample while the clock pin is high. Otherwise, I output a zero. This seems to work just fine for both data and commands.

However, I am not sure why would this work - I don't see why would anybody use something so convoluted as a "level-sensitive" latch for communication (specially since I doubt that would help them lower costs).

I can only think that there must be some jitter somewhere trashing the experiment (which would also explain why the clock is so iregular - a bitbanged SPI using a "while" loop wouldn't certainly do that!)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: lucas.hartmann on December 27, 2018, 02:21:36 am
My guess would be the programmer's bitbang code changes the data right before setting the clock, and uses a software loop to limit the frequency.

The sample rate of the logic analyzer is fast enough to see all clocks, but maybe not enough to consistently get the short delay between changing of data and rising of clock.

A hardware shift register should have a setup time in the ns range, so the target MCU reads nicely.

Enviado de meu SM-N910C usando o Tapatalk

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 27, 2018, 06:02:31 pm
The voltage levels look suspiciously like zener voltages.

Could it be that they are 2.7V, 5.6V and 8.2V upon closer inspection?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 28, 2018, 11:05:30 am
The voltage levels look suspiciously like zener voltages.

Could it be that they are 2.7V, 5.6V and 8.2V upon closer inspection?

Nice catch.

This also brought to my attention that the singal voltage might be smaller than standard TTL and this might require setting a lower trigger level in logic analyzer ( http://www.zeroplus.com.tw/logic-analyzer_en/faq_hardware.php (http://www.zeroplus.com.tw/logic-analyzer_en/faq_hardware.php) ).

With the wrong (to high) trigger level (from TTL) it would explain why the signal is not captured 100% correctly especially with clock rates >=1 MHz.

When I'm back I will try to make a new capture with lower trigger level.

Nevertheless we should have all the information now to start writing down a draft of the flashing protocol and start with some experiments,

Anybody has a an idea how to create a cheap circuit to create different voltages (12V / 8.5V / 6.5 V / 5V / 3V ...) based on MCU output (using some digital outputs).

Have fun,

JS
 
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 28, 2018, 11:21:59 am
Anybody has a an idea how to create a cheap circuit to create different voltages (12V / 8.5V / 6.5 V / 5V / 3V ...) based on MCU output (using some digital outputs).

This would be easy, just a LM317 and 2 resistors per voltage (and a decoupling capacitor). Then maybe some FETs to switch the output on and off, if it needs more power than a 4051 multiplexer can do.

For the construction I would do it the way PICkit and other programmers work:

(https://images-na.ssl-images-amazon.com/images/I/51JJF3CShXL._SX342_.jpg)

Just the required programming signals on a pinheader on a small device. This could be plugged into any adapter etc. someone wants.

Meanwhile I got one channel of my ADC working. I can now sample with 8 bit resolution, -10 V to +10 V, and 25 MHz samplerate:

https://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/msg2073310/#msg2073310 (https://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/msg2073310/#msg2073310)

Will solder the other 3 channels and finish the FPGA programming, then I can record a full programming cycle, with 25 MHz sampling rate for all 4 channels, and optionally 8 channels with a second board and still 25 MHz, if the bandwidth to the DDR3 RAM works out. Even if we don't need it anymore, was still fun to build it :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 28, 2018, 11:41:32 am

This would be easy, just a LM317 and 2 resistors per voltage (and a decoupling capacitor). Then maybe some FETs to switch the output on and off, if it needs more power than a 4051 multiplexer can do.

Can you draw a small schematic of this so i can assemble it on a bread board? I'm not so good with building circuits...

I have some 74HC4050 and CD4007UBE for signal level shifting (either up or down, just as we need for input/output of digital signals from MCU to/from IC).

Meanwhile I got one channel of my ADC working. I can now sample with 8 bit resolution, -10 V to +10 V, and 25 MHz samplerate:

https://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/msg2073310/#msg2073310 (https://www.eevblog.com/forum/projects/4-channel-adc-10-mhz-8-bit-design/msg2073310/#msg2073310)

Will solder the other 3 channels and finish the FPGA programming, then I can record a full programming cycle, with 25 MHz sampling rate for all 4 channels, and optionally 8 channels with a second board and still 25 MHz, if the bandwidth to the DDR3 RAM works out. Even if we don't need it anymore, was still fun to build it :)

I'm very interested in this project and would love to see a 1GByte 8 channel analog logic analyzer :-) If it works good I will get / build one for sure.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 28, 2018, 03:18:35 pm
The 74HC4050 looks good when the microcontroller wants to send back data, e.g. for the verify cycle.

I don't know much either about analog circuits, but I think it is called high-side switch what we would need, like this:

http://cq.cx/interface.pl#13 (http://cq.cx/interface.pl#13)

I tried to simulate it in LTSpice, but it switches really slow:

(https://i.imgur.com/t89M68b.png)

If I reduce R3 to 100 ohm, it gets better, but then the transistor Q1 might get very warm. There are all in one ICs as well for high side switches, but not as fun as DIY :)

For the voltage regulator, just look at the datasheet of the LM317 (https://www.st.com/content/ccc/resource/technical/document/datasheet/8e/b2/ea/56/ad/8c/43/d8/CD00000549.pdf/files/CD00000549.pdf/jcr:content/translations/en.CD00000549.pdf), figure 3, and the formula for R1 and R2 in chapter 6. It works up to 37 V, but it is a linear regulator, so it gets hot when the programmed IC needs much power (e.g. supply voltage is 20 V, you want 8 V output, and with 100 mA, then 12 V * 0.1 A = 1.2 W is dissipated in heat at the regulator). But should be fine with a 12 V power supply to generate all voltages. Could be generated with a step-up converter, so that it would work with a 5 V USB power supply, or even from the USB port, if it doesn't need much power.

I think first we should measure the required currents and the required timings. Then we could design the programmer circuit. I guess it doesn't matter if it needs like 100 us to turn on a higher voltage for VPP with a relatively high current. We could use a few of these high side switches to select different voltages. But then for the logic signals, which might need only uA, we could use 4051 multiplexers to switch the VPP signal to and from the logic inputs very fast.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 28, 2018, 03:20:10 pm
Attached is the LTspice simulation for the high-side switch.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 28, 2018, 03:21:49 pm
I was thinking about putting some zener diodes in parallel and switching them with an uln2003.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 28, 2018, 03:38:08 pm
The ULN2003 switches to GND. But if it the IC needs just a few milliampere, the LM317 etc. might be overkill, and you could use a zener diode, and then just pull it low with a ULN2003, and wire-or the different voltages with more diodes. But wouldn't be very accurate and wasting some power. I think my solution would cost like EUR 2 per voltage.

Another idea would be to use a cheap DAC and OpAmp to control the voltage. This would allow any voltage without a voltage regulator (but a reference voltage IC for the DAC), and would be even cheaper.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 28, 2018, 03:44:06 pm
The ULN2003 switches to GND.

Exactly. Zener on top, ULN switch on the bottom. ULN on -> current flows through the zener reducing the voltage to the IC to that value. Input voltage cant be to high obviously ;) but there could be a pull-down resistor in parallel with the zeners also switched with the uln2003 to limit the voltage to something safe.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 28, 2018, 03:50:12 pm
And if the current isnt to high the uln2003 could be replaced with the output pin of a microcontroller.
~20 mA.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: lucas.hartmann on December 28, 2018, 04:05:40 pm
You could use low output to enable and Z to disable a zener, except you will have a voltage swing limit due to the clamping diodes on every GPIO.

If you use a 3.3V microcontroller and have a 3.0V zener for the outputs then it will max your voltage output at 3.3 + 0.7 + 3.0. You will not be able to get 12V from this circuit.

Enviado de meu SM-N910C usando o Tapatalk

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on December 28, 2018, 04:17:33 pm
TPIC6C595 is a nice upgrade from the old ULN2003. The DMOS outputs get close to ground (the darlingtons in the ULN only go down to about 1V) and it only requires only 3 GPIO from the microcontroller. The only thing I don't like about it is that it is a 5V part.

http://www.ti.com/lit/ds/symlink/tpic6c595.pdf (http://www.ti.com/lit/ds/symlink/tpic6c595.pdf)

TPIC6B595 and TPIC6A595 have lower Rdson, so they can handle a bit more current.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 28, 2018, 04:21:26 pm
You have to power the micro anyway.
So my thinking was to use 12v standard supply and then reduce the voltage to the appropriate level using the zeners.
As the uln2003 (or micro) switches to gnd that shouldnt be a problem.

I ordered some  ULN2003V12S16-13 a while back, was thinking of using those when they arrive.
They're 3.3V compatible.

Somewhat like this:
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 28, 2018, 07:59:30 pm
For generating VDD and VPP I'd just use any random linear regulator, with NMOS for switching the divider resistor, one for each pin.

I think it should be even possible to remove the NMOS altogether, using GPIO from the programming microcontroller and switching between high impedance and open collector, given how little current this draws.

I think it would be even possible to drive VDD straight from 3.3V or 5V (with another MOSFET for switching on and off), and thus have the regulator for switching between 5.6/8.2V only on the VPP pin.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 28, 2018, 08:10:17 pm
For generating VDD and VPP I'd just use any random linear regulator, with NMOS for switching the divider resistor, one for each pin.

I dont know how fast the voltage transitions have to be.
From the pictures in Davids video they seem to be rather fast.
Voltage regulators typically have settling times that are rather long.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 28, 2018, 08:26:05 pm
For generating VDD and VPP I'd just use any random linear regulator, with NMOS for switching the divider resistor, one for each pin.

I dont know how fast the voltage transitions have to be.
From the pictures in Davids video they seem to be rather fast.
Voltage regulators typically have settling times that are rather long.
They're not that fast, you can actually see it settling on the Verify file that was uploaded with the analog Vpp.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 28, 2018, 09:06:18 pm
It would be nice to have the feature to set any voltage from 2.0V to 12.0V

2.0V - 5.0V are needed for calibration later (at least with 0.1V steps).

6.5, 8.5, 12.0 are needed for programing (OTP need higer voltages).

I was looking at something like PWM output and LM371T but the refernce schematic looks big (lots of components and an opamp).

JS

The voltage is not changed very often. The trace from Dave just showed that no capacitator was used to stabelize the vdd voltage...
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 28, 2018, 09:18:06 pm
It would be nice to have the feature to set any voltage from 2.0V to 12.0V

Then maybe this would be something to look at:
http://openprog.altervista.org/OP_eng.html#Regulator (http://openprog.altervista.org/OP_eng.html#Regulator)
boost converter with feedback by using only a microcontroller

And for lower voltages you can just do pwm.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 28, 2018, 09:21:57 pm
2.0V - 5.0V are needed for calibration later (at least with 0.1V steps).
How is that? What are those used for?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 29, 2018, 12:03:50 am
2.0V - 5.0V are needed for calibration later (at least with 0.1V steps).
How is that? What are those used for?
After writing the firmware, the IC can be calibrated. Due to manufacturing differences the internal clock might need some tuning (up or down) to produce the exact desired frequency of e.g. 16MHz. This also depends on the supply voltage (VDD). So if you plan to use the IC with 3.1V later you need to calibrate it using 3.1V for VDD. Calibration itself is a very simple process. You just let the IC run a loop with e.g. 5000000 cycles, The IC outputs a signal when it starts and when it finishs. The flasher captures the time it took and then can increase or decrease the clock a tiny tiny bit to calibrate it.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 29, 2018, 12:26:28 am
I was looking at something like PWM output and LM371T but the refernce schematic looks big (lots of components and an opamp).

The basic circuit is simple, and at least in LTspice it works:

(https://i.imgur.com/0uFPbRv.png)

The 0-3 V is translated to 0-9 V. The 2SCR542P transistor is really nice: can switch up to 5 A, with a beefy TO-243 package and costs only 56 cent at Digikey.

To generate the 0-3 V control voltage, you could use a cheap DAC, like the MCP4901. Together with a reference voltage IC, like the LM4040, it should be pretty accurate without calibration.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 29, 2018, 03:12:33 pm
Many thanks for all your suggestions but it still looks complicated to me.

After searching around and considering my limited electronics skills I came up with this idea:

LM317 (adjustable ldo, approx USD 0.5)
MCP4141 (digital potentiometer, approx USD 0.7))
2 caps, 1 resistor

Would this work? For sure is easy to assemble  :).

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on December 29, 2018, 03:53:00 pm
The datasheet for the digital potentiometer says in the absolute maximum ratings table: "Voltage on all other pins (PxA, PxW, PxB..." = -0.3 V to Vdd + 0.3 V. Recommended max supply voltage for Vdd is 5.5 V. This means at the potentiometer pins you can use max 5.8 V, and probably it won't work at all for voltages > Vdd.

But my solution doesn't look too complicated. You can get all chips in DIP as well, and the LM4040 voltage reference in TO92-3 (looks like a transistor) for easier testing on a breadboard (the 3 V version of the reference would be the right choice, if the microcontroller and DAC runs with 3.3 V). For the OpAmp anything should do it, like a LM324, if you don't need to go to 0 V (it is not a rail-to-rail OpAmp). But might need some extra calibration. The ADA4522 has low offset voltage and low drift, which means it would be very accurate relatively to the voltage reference without calibration. I would just design a PCB for it and then use all SMD parts, it is actually easier to solder and would be a nice compact module.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 29, 2018, 03:58:06 pm
You could also do a variation of
http://www.circuitstoday.com/few-lm317-voltage-regulator-circuits (http://www.circuitstoday.com/few-lm317-voltage-regulator-circuits)
look for "Adjustable regulator with digitally selected output"

Replace the transistors with a ULN2003.
I think they cost USD 0.15 plus a few resistors.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 29, 2018, 04:20:21 pm
You could also do a variation of
http://www.circuitstoday.com/few-lm317-voltage-regulator-circuits (http://www.circuitstoday.com/few-lm317-voltage-regulator-circuits)
look for "Adjustable regulator with digitally selected output"

Replace the transistors with a ULN2003.
I think they cost USD 0.15 plus a few resistors.
That's exactly what I thought about in my previous post, but that won't work if you also need to calibrate it running from 3 to 5V. It may work if you don't really give a damn about calibrating and use it only for programming, or allow calibrating only at preset voltages (which to be honest, would be the case - aside from 3.3, 3.6 and 5V, who really needs any other voltages?)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 29, 2018, 04:58:47 pm
You could also do a variation of
http://www.circuitstoday.com/few-lm317-voltage-regulator-circuits (http://www.circuitstoday.com/few-lm317-voltage-regulator-circuits)
look for "Adjustable regulator with digitally selected output"

Replace the transistors with a ULN2003.
I think they cost USD 0.15 plus a few resistors.
That's exactly what I thought about in my previous post, but that won't work if you also need to calibrate it running from 3 to 5V. It may work if you don't really give a damn about calibrating and use it only for programming, or allow calibrating only at preset voltages (which to be honest, would be the case - aside from 3.3, 3.6 and 5V, who really needs any other voltages?)

No, no. You can choose the resistor values as you want and also switch them in parallel, kind of like a digital potentiometer (but they usually have the resistors in series).
1/R = 1/R1 + 1/R2 + ...
One would have to figure out the appropriate values though...
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 29, 2018, 05:13:50 pm
Yeah, if you're doing that you'd better switch them in parallel, because the moment you leave none connected (ie when switching from one to the other) you're gonna pass the full voltage to the output  ;D

For regulating, you probably want to use the resistors as a rudimentary R2R ladder. For having 0.1V range from 2 to 5V you'll need ceil(log2((5-2)/0.1))=5 resistors, which aren't too many.

EDIT: I think this is slightly too overkill - we'll need probably 5 precision resistors with non-standard values, or five pots. I think just using a LM317 and a DAC as an offset for its ground should work better.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: imo on December 29, 2018, 07:46:11 pm
You may consider a PWM DAC - below one gives you almost any Vout from 0-12V.
You may set the upper range by R2/R3, here

Vmax = 3.3V*(1+R2/R3), where 3.3V is MCUs log1

and the actual voltage by setting the PWM duty. The higher the PWM freq the faster settling with smaller R1C1.
Example only.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 30, 2018, 08:31:43 am
You may consider a PWM DAC - below one gives you almost any Vout from 0-12V.

Nice.

Going along those lines: (Voltage Regulator Control with DAC) -> Actually describes using PWM to control a voltage regulator
https://www.microchip.com/forums/FindPost/985974 (https://www.microchip.com/forums/FindPost/985974)

If the output voltage is sampled with an ADC there's no need for an opamp (or precision ;) and transients would be handled by the voltage regulator.

I wonder if a fixed voltage regulator could be used by modifying the current/voltage on the GND lead. (I know that putting zeners there shift the output voltage)

EDIT: seems that you can easily:
https://electronicsforu.com/electronics-projects/hardware-diy/variable-power-supply-using-fixed-voltage-regulator-ic (https://electronicsforu.com/electronics-projects/hardware-diy/variable-power-supply-using-fixed-voltage-regulator-ic)

Makes it very cheap SC1117-3.3V regulators cost less than USD 0.03

But cant go lower than the fixed voltage apparently :(
Also adjustable regulators of the same kind also cost less than USD 0.03 :)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 30, 2018, 01:11:03 pm
Just use a normal adjustable regulator, such as the LM317 (1.25V reference) or LM431 (2.5V reference). They're less than 0.10$ a piece in TO-92.

IMHO I think we're trying to overdesign this. Having just a set of common reference voltages for VDD should work for calibrating - after all, if you really want a somewhat stable clock (as it'll also drift from temperature changes), you'll use a regulated power supply at a standard voltage such as 3.3V or 5V.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 30, 2018, 06:31:54 pm
Attached is the design I'd use for Vdd.

I'm using a HT7133 because it's a cheap linear regulator, it's available in TO92 for easy prototyping, and has a Vref of 3.3 which means you can buy many for using as 3.3V regulator with no resistors in other circuits.

The 200ohm resistor must be that value our lower, to ensure there are always 10mA of current being consumed -the minimum according to datasheet- any moment to ensure the regulator doesn't output a voltage higher than designed.

I'd try if the Padauk ICs can use 3.3V in place of 2.6V (used in non-RW operations and during command transmission) and 5V in place of 4.3V (used during flash reads), since that would make everything much easier. Otherwise m we would probably need to put a DAC for more accurate control, as I'm not sure adding more and more resistors scale.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 30, 2018, 09:43:53 pm
I did a new capture of VERIFY.

This time I lowered the voltage to detect a 1 down to 1.2V (was 1.5V).
I also found a way to capture the complete VERIFY command at 200MHz (the logic analyzer has a compression feature).
This messed up my trigger a bit (you see the scanning spikes before and after the command, which are used by writer to detect IC presence).
I hope now we can read the signal 100% ok without any tricks.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 31, 2018, 01:39:28 am
I did a new capture of VERIFY.

This time I lowered the voltage to detect a 1 down to 1.2V (was 1.5V).
I also found a way to capture the complete VERIFY command at 200MHz (the logic analyzer has a compression feature).
This messed up my trigger a bit (you see the scanning spikes before and after the command, which are used by writer to detect IC presence).
I hope now we can read the signal 100% ok without any tricks.

JS

When sampling on rising edge now:
Code: [Select]
116050251: FLASH_READ_B
    No data (dummy read)

 121460163: FLASH_READ_B

    ADDR DATA ?
    -----------
    07EF 1FFE 0
    07F0 0025 0
    07F1 0025 1

 125171746: ??? (1010010110100101101001011010001100001010101000010)

 132819271: ??? (1010010110100101101001011010011001101010101000010)

 189653978: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07F0 0026 3FFF 3FFF 3FFF


 194375712: FLASH_READ_B

    ADDR DATA ?
    -----------
    07F0 0026 0

 198033461: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07F0 3FFF 0026 3FFF 3FFF


 202755194: FLASH_READ_B

    ADDR DATA ?
    -----------
    07F1 0002 1

 206415006: FLASH_READ_B

    ADDR DATA ?
    -----------
    07E0 1FFF 0
    07E1 1FFF 0
    07E2 1FFF 1
    07E3 1FFF 1
    07E4 1FFF 1
    07E5 1FFF 1
    07E6 1FFF 1
    07E7 1FFF 1
    07E8 1FFF 1
    07E9 1FFF 1
    07EA 1FFF 1
    07EB 1FFF 1
    07EC 1FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0002 0
    07F1 0002 1
    07F2 1FFF 0
    07F3 1FFF 0
    07F4 1FFF 1
    07F5 1FFF 1
    07F6 1FFF 1
    07F7 1FFF 1
    07F8 1FFF 1
    07F9 1FFF 1
    07FA 1FFF 1
    07FB 1FFF 1
    07FC 1FFF 1
    07FD 1FFF 1
    07FE 1FFF 1
    07FF 1FFF 1

 210876950: FLASH_READ_B

    ADDR DATA ?
    -----------
    07E0 1FFF 0
    07E1 1FFF 0
    07E2 1FFF 1
    07E3 1FFF 1
    07E4 1FFF 1
    07E5 1FFF 1
    07E6 1FFF 1
    07E7 1FFF 1
    07E8 1FFF 1
    07E9 1FFF 1
    07EA 1FFF 1
    07EB 1FFF 1
    07EC 1FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 1FFF 0
    07F3 1FFF 0
    07F4 1FFF 1
    07F5 1FFF 1
    07F6 1FFF 1
    07F7 1FFF 1
    07F8 1FFF 1
    07F9 1FFF 1
    07FA 1FFF 1
    07FB 1FFF 1
    07FC 1FFF 1
    07FD 1FFF 1
    07FE 1FFF 1
    07FF 1FFF 1

 216360622: FLASH_READ_B

    ADDR DATA ?
    -----------
    0000 1FFF 0
    0001 1FFF 0
    0002 1FFF 1
    0003 1FFF 1
    0004 1FFF 1
    0005 1FFF 1
    0006 1FFF 1
    0007 1FFF 1
    0008 1FFF 1
    0009 1FFF 1
    000A 1FFF 1
    000B 1FFF 1
    000C 1FFF 1
    000D 1FFF 1
    000E 1FFF 1
    000F 1FFF 1
    0010 1FFF 1
    0011 1FFF 1
    0012 1FFF 1
    0013 1FFF 1
    0014 1FFF 1
    0015 1FFF 1
    0016 1FFF 1
    0017 1FFF 1
    0018 1FFF 1
    0019 1FFF 1
    001A 1FFF 1
    001B 1FFF 1
    001C 1FFF 1
    001D 1FFF 1
    001E 1FFF 1
    001F 1FFF 1
    0020 1FFF 1
    0021 1FFF 1
    0022 1FFF 1
    0023 1FFF 1
    0024 1FFF 1
    0025 1FFF 1
    0026 1FFF 1
    0027 1FFF 1
    0028 1FFF 1
    0029 1FFF 1
    002A 1FFF 1
    002B 1FFF 1
    002C 1FFF 1
    002D 1FFF 1
    002E 1FFF 1
    002F 1FFF 1
    0030 1FFF 1
    0031 1FFF 1
    0032 1FFF 1
    0033 1FFF 1
    0034 1FFF 1
    0035 1FFF 1
    0036 1FFF 1
    0037 1FFF 1
    0038 1FFF 1
    0039 1FFF 1
    003A 1FFF 1
    003B 1FFF 1
    003C 1FFF 1
    003D 1FFF 1
    003E 1FFF 1
    003F 1FFF 1
    0040 1FFF 1
    0041 1FFF 1
    0042 1FFF 1
    0043 1FFF 1
    0044 1FFF 1
    0045 1FFF 1
    0046 1FFF 1
    0047 1FFF 1
    0048 1FFF 1
    0049 1FFF 1
    004A 1FFF 1
    004B 1FFF 1
    004C 1FFF 1
    004D 1FFF 1
    004E 1FFF 1
    004F 1FFF 1
    0050 1FFF 1
    0051 1FFF 1
    0052 1FFF 1
    0053 1FFF 1
    0054 1FFF 1
    0055 1FFF 1
    0056 1FFF 1
    0057 1FFF 1
    0058 1FFF 1
    0059 1FFF 1
    005A 1FFF 1
    005B 1FFF 1
    005C 1FFF 1
    005D 1FFF 1
    005E 1FFF 1
    005F 1FFF 1
    0060 1FFF 1
    0061 1FFF 1
    0062 1FFF 1
    0063 1FFF 1
    0064 1FFF 1
    0065 1FFF 1
    0066 1FFF 1
    0067 1FFF 1
    0068 1FFF 1
    0069 1FFF 1
    006A 1FFF 1
    006B 1FFF 1
    006C 1FFF 1
    006D 1FFF 1
    006E 1FFF 1
    006F 1FFF 1
    0070 1FFF 1
    0071 1FFF 1
    0072 1FFF 1
    0073 1FFF 1
    0074 1FFF 1
    0075 1FFF 1
    0076 1FFF 1
    0077 1FFF 1
    0078 1FFF 1
    0079 1FFF 1
    007A 1FFF 1
    007B 1FFF 1
    007C 1FFF 1
    007D 1FFF 1
    007E 1FFF 1
    007F 1FFF 1
    0080 1FFF 1
    0081 1FFF 1
    0082 1FFF 1
    0083 1FFF 1
    0084 1FFF 1
    0085 1FFF 1
    0086 1FFF 1
    0087 1FFF 1
    0088 1FFF 1
    0089 1FFF 1
    008A 1FFF 1
    008B 1FFF 1
    008C 1FFF 1
    008D 1FFF 1
    008E 1FFF 1
    008F 1FFF 1
    0090 1FFF 1
    0091 1FFF 1
    0092 1FFF 1
    0093 1FFF 1
    0094 1FFF 1
    0095 1FFF 1
    0096 1FFF 1
    0097 1FFF 1
    0098 1FFF 1
    0099 1FFF 1
    009A 1FFF 1
    009B 1FFF 1
    009C 1FFF 1
    009D 1FFF 1
    009E 1FFF 1
    009F 1FFF 1
    00A0 1FFF 1
    00A1 1FFF 1
    00A2 1FFF 1
    00A3 1FFF 1
    00A4 1FFF 1
    00A5 1FFF 1
    00A6 1FFF 1
    00A7 1FFF 1
    00A8 1FFF 1
    00A9 1FFF 1
    00AA 1FFF 1
    00AB 1FFF 1
    00AC 1FFF 1
    00AD 1FFF 1
    00AE 1FFF 1
    00AF 1FFF 1
    00B0 1FFF 1
    00B1 1FFF 1
    00B2 1FFF 1
    00B3 1FFF 1
    00B4 1FFF 1
    00B5 1FFF 1
    00B6 1FFF 1
    00B7 1FFF 1
    00B8 1FFF 1
    00B9 1FFF 1
    00BA 1FFF 1
    00BB 1FFF 1
    00BC 1FFF 1
    00BD 1FFF 1
    00BE 1FFF 1
    00BF 1FFF 1
    00C0 1FFF 1
    00C1 1FFF 1
    00C2 1FFF 1
    00C3 1FFF 1
    00C4 1FFF 1
    00C5 1FFF 1
    00C6 1FFF 1
    00C7 1FFF 1
    00C8 1FFF 1
    00C9 1FFF 1
    00CA 1FFF 1
    00CB 1FFF 1
    00CC 1FFF 1
    00CD 1FFF 1
    00CE 1FFF 1
    00CF 1FFF 1
    00D0 1FFF 1
    00D1 1FFF 1
    00D2 1FFF 1
    00D3 1FFF 1
    00D4 1FFF 1
    00D5 1FFF 1
    00D6 1FFF 1
    00D7 1FFF 1
    00D8 1FFF 1
    00D9 1FFF 1
    00DA 1FFF 1
    00DB 1FFF 1
    00DC 1FFF 1
    00DD 1FFF 1
    00DE 1FFF 1
    00DF 1FFF 1
    00E0 1FFF 1
    00E1 1FFF 1
    00E2 1FFF 1
    00E3 1FFF 1
    00E4 1FFF 1
    00E5 1FFF 1
    00E6 1FFF 1
    00E7 1FFF 1
    00E8 1FFF 1
    00E9 1FFF 1
    00EA 1FFF 1
    00EB 1FFF 1
    00EC 1FFF 1
    00ED 1FFF 1
    00EE 1FFF 1
    00EF 1FFF 1
    00F0 1FFF 1
    00F1 1FFF 1
    00F2 1FFF 1
    00F3 1FFF 1
    00F4 1FFF 1
    00F5 1FFF 1
    00F6 1FFF 1
    00F7 1FFF 1
    00F8 1FFF 1
    00F9 1FFF 1
    00FA 1FFF 1
    00FB 1FFF 1
    00FC 1FFF 1
    00FD 1FFF 1
    00FE 1FFF 1
    00FF 1FFF 1
    0100 1FFF 1
    0101 1FFF 1
    0102 1FFF 1
    0103 1FFF 1
    0104 1FFF 1
    0105 1FFF 1
    0106 1FFF 1
    0107 1FFF 1
    0108 1FFF 1
    0109 1FFF 1
    010A 1FFF 1
    010B 1FFF 1
    010C 1FFF 1
    010D 1FFF 1
    010E 1FFF 1
    010F 1FFF 1
    0110 1FFF 1
    0111 1FFF 1
    0112 1FFF 1
    0113 1FFF 1
    0114 1FFF 1
    0115 1FFF 1
    0116 1FFF 1
    0117 1FFF 1
    0118 1FFF 1
    0119 1FFF 1
    011A 1FFF 1
    011B 1FFF 1
    011C 1FFF 1
    011D 1FFF 1
    011E 1FFF 1
    011F 1FFF 1
    0120 1FFF 1
    0121 1FFF 1
    0122 1FFF 1
    0123 1FFF 1
    0124 1FFF 1
    0125 1FFF 1
    0126 1FFF 1
    0127 1FFF 1
    0128 1FFF 1
    0129 1FFF 1
    012A 1FFF 1
    012B 1FFF 1
    012C 1FFF 1
    012D 1FFF 1
    012E 1FFF 1
    012F 1FFF 1
    0130 1FFF 1
    0131 1FFF 1
    0132 1FFF 1
    0133 1FFF 1
    0134 1FFF 1
    0135 1FFF 1
    0136 1FFF 1
    0137 1FFF 1
    0138 1FFF 1
    0139 1FFF 1
    013A 1FFF 1
    013B 1FFF 1
    013C 1FFF 1
    013D 1FFF 1
    013E 1FFF 1
    013F 1FFF 1
    0140 1FFF 1
    0141 1FFF 1
    0142 1FFF 1
    0143 1FFF 1
    0144 1FFF 1
    0145 1FFF 1
    0146 1FFF 1
    0147 1FFF 1
    0148 1FFF 1
    0149 1FFF 1
    014A 1FFF 1
    014B 1FFF 1
    014C 1FFF 1
    014D 1FFF 1
    014E 1FFF 1
    014F 1FFF 1
    0150 1FFF 1
    0151 1FFF 1
    0152 1FFF 1
    0153 1FFF 1
    0154 1FFF 1
    0155 1FFF 1
    0156 1FFF 1
    0157 1FFF 1
    0158 1FFF 1
    0159 1FFF 1
    015A 1FFF 1
    015B 1FFF 1
    015C 1FFF 1
    015D 1FFF 1
    015E 1FFF 1
    015F 1FFF 1
    0160 1FFF 1
    0161 1FFF 1
    0162 1FFF 1
    0163 1FFF 1
    0164 1FFF 1
    0165 1FFF 1
    0166 1FFF 1
    0167 1FFF 1
    0168 1FFF 1
    0169 1FFF 1
    016A 1FFF 1
    016B 1FFF 1
    016C 1FFF 1
    016D 1FFF 1
    016E 1FFF 1
    016F 1FFF 1
    0170 1FFF 1
    0171 1FFF 1
    0172 1FFF 1
    0173 1FFF 1
    0174 1FFF 1
    0175 1FFF 1
    0176 1FFF 1
    0177 1FFF 1
    0178 1FFF 1
    0179 1FFF 1
    017A 1FFF 1
    017B 1FFF 1
    017C 1FFF 1
    017D 1FFF 1
    017E 1FFF 1
    017F 1FFF 1
    [cut to keep message under 50k chars - they're all 1FFF anyway]
    07C0 1FFF 1
    07C1 1FFF 1
    07C2 1FFF 1
    07C3 1FFF 1
    07C4 1FFF 1
    07C5 1FFF 1
    07C6 1FFF 1
    07C7 1FFF 1
    07C8 1FFF 1
    07C9 1FFF 1
    07CA 1FFF 1
    07CB 1FFF 1
    07CC 1FFF 1
    07CD 1FFF 1
    07CE 1FFF 1
    07CF 1FFF 1
    07D0 1FFF 1
    07D1 1FFF 1
    07D2 1FFF 1
    07D3 1FFF 1
    07D4 1FFF 1
    07D5 1FFF 1
    07D6 1FFF 1
    07D7 1FFF 1
    07D8 1FFF 1
    07D9 1FFF 1
    07DA 1FFF 1
    07DB 1FFF 1
    07DC 1FFF 1
    07DD 1FFF 1
    07DE 1FFF 1
    07DF 1FFF 1

 274899016: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    0000 0070 2F00 0182 3FED
    0004 018B 3FEE 019A 2F80
    0008 019B 2F1C 0183 3FFE
    000C 2AFF 3054 3FED 0B81
    0010 1F91 2F05 0B80 1AD0
    0014 3013 1F90 0063 3016
    0018 1180 3016 1D90 18D0
    001C 301B 2F01 1950 2FFF
    0020 0C01 018B 0B81 1AD0
    0024 3023 1B50 304F 2F04
    0028 0188 18D0 3029 2F02
    002C 0182 1304 1305 2F6E
    0030 0B82 2F00 0B83 0006
    0034 0B04 0007 0805 1584
    0038 1685 1004 1282 1083
    003C 1A40 3033 1F90 1AD0
    0040 303F 1584 1685 0590
    0044 18D0 3044 1950 303F
    0048 1D90 1AD0 3049 18D0
    004C 304B 1B50 302B 18D0
    0050 304F 1B50 3011 3053
    0054 018B 1ED1 1ED0 2F03
    0058 0BC1 2F8A 0BC0 2F56
    005C 0063 305C 11C0 305C
    0060 11C1 305C 1CD0 2F03
    0064 0BC1 2F8A 0BC0 2F56
    0068 0063 3068 11C0 3068
    006C 11C1 3068 3056 3FFF


 282886516: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07EC 3FFF 0281 027A 1FFE
    07F0 0026 0026 3FFF 3FFF
    07F8 1850 3F54 3FFF 3FFF
    07FC 3FFF 3FFF 02FF 31FD


 290648067: FLASH_READ_B

    ADDR DATA ?
    -----------
    07E0 1FFF 0
    07E1 1FFF 0
    07E2 1FFF 1
    07E3 1FFF 1
    07E4 1FFF 1
    07E5 1FFF 1
    07E6 1FFF 1
    07E7 1FFF 1
    07E8 1FFF 1
    07E9 1FFF 1
    07EA 1FFF 1
    07EB 1FFF 1
    07EC 1FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 1FFF 0
    07F3 1FFF 0
    07F4 1FFF 1
    07F5 1FFF 1
    07F6 1FFF 1
    07F7 1FFF 1
    07F8 1850 1
    07F9 1F54 1
    07FA 1FFF 1
    07FB 1FFF 1
    07FC 1FFF 1
    07FD 1FFF 1
    07FE 02FF 1
    07FF 11FD 1

 296125972: FLASH_READ_B

    ADDR DATA ?
    -----------
    0000 0070 0
    0001 0F00 0
    0002 0182 0
    0003 1FED 0
    0004 018B 0
    0005 1FEE 1
    0006 019A 0
    0007 0F80 1
    0008 019B 0
    0009 0F1C 0
    000A 0183 0
    000B 1FFE 0
    000C 0AFF 0
    000D 1054 1
    000E 1FED 0
    000F 0B81 1
    0010 1F91 1
    0011 0F05 0
    0012 0B80 1
    0013 1AD0 0
    0014 1013 0
    0015 1F90 1
    0016 0063 1
    0017 1016 1
    0018 1180 0
    0019 1016 1
    001A 1D90 1
    001B 18D0 1
    001C 101B 1
    001D 0F01 1
    001E 1950 1
    001F 0FFF 0
    0020 0C01 1
    0021 018B 0
    0022 0B81 0
    0023 1AD0 0
    0024 1023 0
    0025 1B50 1
    0026 104F 1
    0027 0F04 1
    0028 0188 1
    0029 18D0 0
    002A 1029 0
    002B 0F02 1
    002C 0182 1
    002D 1304 0
    002E 1305 0
    002F 0F6E 1
    0030 0B82 1
    0031 0F00 0
    0032 0B83 0
    0033 0006 0
    0034 0B04 0
    0035 0007 0
    0036 0805 0
    0037 1584 0
    0038 1685 0
    0039 1004 1
    003A 1282 1
    003B 1083 1
    003C 1A40 1
    003D 1033 1
    003E 1F90 1
    003F 1AD0 1
    0040 103F 1
    0041 1584 1
    0042 1685 1
    0043 0590 1
    0044 18D0 1
    0045 1044 0
    0046 1950 1
    0047 103F 1
    0048 1D90 1
    0049 1AD0 1
    004A 1049 1
    004B 18D0 1
    004C 104B 1
    004D 1B50 1
    004E 102B 1
    004F 18D0 1
    0050 104F 1
    0051 1B50 1
    0052 1011 1
    0053 1053 1
    0054 018B 1
    0055 1ED1 1
    0056 1ED0 0
    0057 0F03 1
    0058 0BC1 1
    0059 0F8A 0
    005A 0BC0 0
    005B 0F56 0
    005C 0063 0
    005D 105C 0
    005E 11C0 0
    005F 105C 1
    0060 11C1 1
    0061 105C 1
    0062 1CD0 1
    0063 0F03 1
    0064 0BC1 1
    0065 0F8A 0
    0066 0BC0 0
    0067 0F56 0
    0068 0063 0
    0069 1068 0
    006A 11C0 0
    006B 1068 1
    006C 11C1 1
    006D 1068 1
    006E 1056 1
    006F 1FFF 1

 304013520: FLASH_READ_B

    ADDR DATA ?
    -----------
    07E0 1FFF 0
    07E1 1FFF 0
    07E2 1FFF 1
    07E3 1FFF 1
    07E4 1FFF 1
    07E5 1FFF 1
    07E6 1FFF 1
    07E7 1FFF 1
    07E8 1FFF 1
    07E9 1FFF 1
    07EA 1FFF 1
    07EB 1FFF 1
    07EC 1FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0002 0
    07F1 0002 1
    07F2 1FFF 0
    07F3 1FFF 0
    07F4 1FFF 1
    07F5 1FFF 1
    07F6 1FFF 1
    07F7 1FFF 1
    07F8 1850 1
    07F9 1F54 1
    07FA 1FFF 1
    07FB 1FFF 1
    07FC 1FFF 1
    07FD 1FFF 1
    07FE 027F 1
    07FF 11FD 1

 308485046: FLASH_READ_B

    ADDR DATA ?
    -----------
    0000 0070 0
    0001 0F00 0
    0002 0180 0
    0003 1FED 0
    0004 0183 0
    0005 1FEE 0
    0006 0198 0
    0007 0F80 0
    0008 0199 0
    0009 071C 0
    000A 0181 0
    000B 1FFE 0
    000C 02FF 0
    000D 1054 0
    000E 1FED 0
    000F 0981 1
    0010 1F91 1
    0011 0701 0
    0012 0380 0
    0013 1AD0 0
    0014 1013 0
    0015 1F90 1
    0016 0063 1
    0017 1012 1
    0018 1180 0
    0019 1006 0
    001A 1D90 1
    001B 1850 1
    001C 101B 1
    001D 0F00 1
    001E 1910 1
    001F 0FFF 0
    0020 0C00 1
    0021 008B 0
    0022 0B81 0
    0023 1AD0 0
    0024 1023 0
    0025 1950 1
    0026 104F 1
    0027 0F00 0
    0028 0180 1
    0029 18D0 0
    002A 1020 0
    002B 0F02 1
    002C 0080 1
    002D 1304 0
    002E 1301 0
    002F 0F6E 0
    0030 0B80 1
    0031 0F00 0
    0032 0B83 0
    0033 0006 0
    0034 0900 0
    0035 0003 0
    0036 0005 0
    0037 1584 0
    0038 1685 0
    0039 1000 0
    003A 1202 1
    003B 1081 1
    003C 1A40 1
    003D 1013 1
    003E 1F90 1
    003F 1AD0 1
    0040 103F 1
    0041 1584 1
    0042 1285 1
    0043 0590 1
    0044 1850 1
    0045 1004 0
    0046 1910 1
    0047 101F 1
    0048 1C90 1
    0049 1AD0 1
    004A 1000 1
    004B 18D0 1
    004C 1003 1
    004D 1B50 1
    004E 1023 1
    004F 1850 1
    0050 1007 1
    0051 1B50 1
    0052 1011 1
    0053 1013 1
    0054 0183 1
    0055 1ED1 1
    0056 1ED0 0
    0057 0F03 1
    0058 0BC0 1
    0059 0F8A 0
    005A 0BC0 0
    005B 0F56 0
    005C 0063 0
    005D 105C 0
    005E 10C0 0
    005F 101C 1
    0060 11C0 1
    0061 101C 1
    0062 1CD0 1
    0063 0F03 1
    0064 03C0 1
    0065 0F8A 0
    0066 0BC0 0
    0067 0F56 0
    0068 0063 0
    0069 1060 0
    006A 10C0 0
    006B 1028 1
    006C 10C1 1
    006D 1028 1
    006E 1056 1
    006F 1FFF 1

 315382652: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    0000 0070 2F00 0182 3FED
    0004 018B 3FEE 019A 2F80
    0008 019B 2F1C 0183 3FFE
    000C 2AFF 3054 3FED 0B81
    0010 1F91 2F05 0B80 1AD0
    0014 3013 1F90 0063 3016
    0018 1180 3016 1D90 18D0
    001C 301B 2F01 1950 2FFF
    0020 0C01 018B 0B81 1AD0
    0024 3023 1B50 304F 2F04
    0028 0188 18D0 3029 2F02
    002C 0182 1304 1305 2F6E
    0030 0B82 2F00 0B83 0006
    0034 0B04 0007 0805 1584
    0038 1685 1004 1282 1083
    003C 1A40 3033 1F90 1AD0
    0040 303F 1584 1685 0590
    0044 18D0 3044 1950 303F
    0048 1D90 1AD0 3049 18D0
    004C 304B 1B50 302B 18D0
    0050 304F 1B50 3011 3053
    0054 018B 1ED1 1ED0 2F03
    0058 0BC1 2F8A 0BC0 2F56
    005C 0063 305C 11C0 305C
    0060 11C1 305C 1CD0 2F03
    0064 0BC1 2F8A 0BC0 2F56
    0068 0063 3068 11C0 3068
    006C 11C1 3068 3056 3FFF


 326049413: 0000001101001010001110011010010100011100
 348308113: 0000001101001010001110011010010100011100
 373491264: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07EC 3FFF 0281 027A 1FFE
    07F0 0026 0026 3FFF 3FFF
    07F8 1850 3F54 3FFF 3FFF
    07FC 3FFF 3FFF 0282 31FD


 378464965: FLASH_READ_B

    ADDR DATA ?
    -----------
    07E0 1FFF 0
    07E1 1FFF 0
    07E2 1FFF 1
    07E3 1FFF 1
    07E4 1FFF 1
    07E5 1FFF 1
    07E6 1FFF 1
    07E7 1FFF 1
    07E8 1FFF 1
    07E9 1FFF 1
    07EA 1FFF 1
    07EB 1FFF 1
    07EC 1FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 1FFF 0
    07F3 1FFF 0
    07F4 1FFF 1
    07F5 1FFF 1
    07F6 1FFF 1
    07F7 1FFF 1
    07F8 1850 1
    07F9 1F54 1
    07FA 1FFF 1
    07FB 1FFF 1
    07FC 1FFF 1
    07FD 1FFF 1
    07FE 0282 1
    07FF 11FD 1

 383944624: FLASH_READ_B

    ADDR DATA ?
    -----------
    07E0 1FFF 0
    07E1 1FFF 0
    07E2 1FFF 1
    07E3 1FFF 1
    07E4 1FFF 1
    07E5 1FFF 1
    07E6 1FFF 1
    07E7 1FFF 1
    07E8 1FFF 1
    07E9 1FFF 1
    07EA 1FFF 1
    07EB 1FFF 1
    07EC 1FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0002 0
    07F1 0002 1
    07F2 1FFF 0
    07F3 1FFF 0
    07F4 1FFF 1
    07F5 1FFF 1
    07F6 1FFF 1
    07F7 1FFF 1
    07F8 1850 1
    07F9 1F54 1
    07FA 1FFF 1
    07FB 1FFF 1
    07FC 1FFF 1
    07FD 1FFF 1
    07FE 0202 1
    07FF 11FD 1

 388416397: FLASH_WRITE_B

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07EC 3FFF 0281 027A 1FFE
    07F0 0026 0026 3FFF 3FFF
    07F8 1850 3F54 3FFF 3FFF
    07FC 3FFF 3FFF 0282 31FD




And when sampling on the falling edge:
Code: [Select]
116050423: FLASH_READ_A
    No data (dummy read)

 121460335: FLASH_READ_A

    ADDR DATA ?
    -----------
    07EF 1FFE 0
    07F0 0025 0
    07F1 0025 1

 125171918: ??? (1010010110100101101001011010001100011010101000010)

 132819443: ??? (1010010110100101101001011010011001111010101000010)

 189654150: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07F0 0026 3FFF 3FFF 3FFF


 194375883: FLASH_READ_A

    ADDR DATA ?
    -----------
    07F0 0026 0

 198033633: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07F0 3FFF 0026 3FFF 3FFF


 202755366: FLASH_READ_A

    ADDR DATA ?
    -----------
    07F1 0026 1

 206415178: FLASH_READ_A

    ADDR DATA ?
    -----------
    07E0 3FFF 0
    07E1 3FFF 0
    07E2 3FFF 1
    07E3 3FFF 1
    07E4 3FFF 1
    07E5 3FFF 1
    07E6 3FFF 1
    07E7 3FFF 1
    07E8 3FFF 1
    07E9 3FFF 1
    07EA 3FFF 1
    07EB 3FFF 1
    07EC 3FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 3FFF 0
    07F3 3FFF 0
    07F4 3FFF 1
    07F5 3FFF 1
    07F6 3FFF 1
    07F7 3FFF 1
    07F8 3FFF 1
    07F9 3FFF 1
    07FA 3FFF 1
    07FB 3FFF 1
    07FC 3FFF 1
    07FD 3FFF 1
    07FE 3FFF 1
    07FF 3FFF 1

 210877122: FLASH_READ_A

    ADDR DATA ?
    -----------
    07E0 3FFF 0
    07E1 3FFF 0
    07E2 3FFF 1
    07E3 3FFF 1
    07E4 3FFF 1
    07E5 3FFF 1
    07E6 3FFF 1
    07E7 3FFF 1
    07E8 3FFF 1
    07E9 3FFF 1
    07EA 3FFF 1
    07EB 3FFF 1
    07EC 3FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 3FFF 0
    07F3 3FFF 0
    07F4 3FFF 1
    07F5 3FFF 1
    07F6 3FFF 1
    07F7 3FFF 1
    07F8 3FFF 1
    07F9 3FFF 1
    07FA 3FFF 1
    07FB 3FFF 1
    07FC 3FFF 1
    07FD 3FFF 1
    07FE 3FFF 1
    07FF 3FFF 1

 216360794: FLASH_READ_A

    ADDR DATA ?
    -----------
    0000 3FFF 0
    0001 3FFF 0
    0002 3FFF 1
    0003 3FFF 1
    0004 3FFF 1
    0005 3FFF 1
    0006 3FFF 1
    0007 3FFF 1
    0008 3FFF 1
    0009 3FFF 1
    000A 3FFF 1
    000B 3FFF 1
    000C 3FFF 1
    000D 3FFF 1
    000E 3FFF 1
    000F 3FFF 1
    0010 3FFF 1
    0011 3FFF 1
    0012 3FFF 1
    0013 3FFF 1
    0014 3FFF 1
    0015 3FFF 1
    0016 3FFF 1
    0017 3FFF 1
    0018 3FFF 1
    0019 3FFF 1
    001A 3FFF 1
    001B 3FFF 1
    001C 3FFF 1
    001D 3FFF 1
    001E 3FFF 1
    001F 3FFF 1
    0020 3FFF 1
    0021 3FFF 1
    0022 3FFF 1
    0023 3FFF 1
    0024 3FFF 1
    0025 3FFF 1
    0026 3FFF 1
    0027 3FFF 1
    0028 3FFF 1
    0029 3FFF 1
    002A 3FFF 1
    002B 3FFF 1
    002C 3FFF 1
    002D 3FFF 1
    002E 3FFF 1
    002F 3FFF 1
    0030 3FFF 1
    0031 3FFF 1
    0032 3FFF 1
    0033 3FFF 1
    0034 3FFF 1
    0035 3FFF 1
    0036 3FFF 1
    0037 3FFF 1
    0038 3FFF 1
    0039 3FFF 1
    003A 3FFF 1
    003B 3FFF 1
    003C 3FFF 1
    003D 3FFF 1
    003E 3FFF 1
    003F 3FFF 1
    0040 3FFF 1
    0041 3FFF 1
    0042 3FFF 1
    0043 3FFF 1
    0044 3FFF 1
    0045 3FFF 1
    0046 3FFF 1
    0047 3FFF 1
    0048 3FFF 1
    0049 3FFF 1
    004A 3FFF 1
    004B 3FFF 1
    004C 3FFF 1
    004D 3FFF 1
    004E 3FFF 1
    004F 3FFF 1
    0050 3FFF 1
    0051 3FFF 1
    0052 3FFF 1
    0053 3FFF 1
    0054 3FFF 1
    0055 3FFF 1
    0056 3FFF 1
    0057 3FFF 1
    0058 3FFF 1
    0059 3FFF 1
    005A 3FFF 1
    005B 3FFF 1
    005C 3FFF 1
    005D 3FFF 1
    005E 3FFF 1
    005F 3FFF 1
    0060 3FFF 1
    0061 3FFF 1
    0062 3FFF 1
    0063 3FFF 1
    0064 3FFF 1
    0065 3FFF 1
    0066 3FFF 1
    0067 3FFF 1
    0068 3FFF 1
    0069 3FFF 1
    006A 3FFF 1
    006B 3FFF 1
    006C 3FFF 1
    006D 3FFF 1
    006E 3FFF 1
    006F 3FFF 1
    0070 3FFF 1
    0071 3FFF 1
    0072 3FFF 1
    0073 3FFF 1
    0074 3FFF 1
    0075 3FFF 1
    0076 3FFF 1
    0077 3FFF 1
    0078 3FFF 1
    0079 3FFF 1
    007A 3FFF 1
    007B 3FFF 1
    007C 3FFF 1
    007D 3FFF 1
    007E 3FFF 1
    007F 3FFF 1
    0080 3FFF 1
    0081 3FFF 1
    0082 3FFF 1
    0083 3FFF 1
    0084 3FFF 1
    0085 3FFF 1
    0086 3FFF 1
    0087 3FFF 1
    0088 3FFF 1
    0089 3FFF 1
    008A 3FFF 1
    008B 3FFF 1
    008C 3FFF 1
    008D 3FFF 1
    008E 3FFF 1
    008F 3FFF 1
    0090 3FFF 1
    0091 3FFF 1
    0092 3FFF 1
    0093 3FFF 1
    0094 3FFF 1
    0095 3FFF 1
    0096 3FFF 1
    0097 3FFF 1
    0098 3FFF 1
    0099 3FFF 1
    009A 3FFF 1
    009B 3FFF 1
    009C 3FFF 1
    009D 3FFF 1
    009E 3FFF 1
    009F 3FFF 1
    00A0 3FFF 1
    00A1 3FFF 1
    00A2 3FFF 1
    00A3 3FFF 1
    00A4 3FFF 1
    00A5 3FFF 1
    00A6 3FFF 1
    00A7 3FFF 1
    00A8 3FFF 1
    00A9 3FFF 1
    00AA 3FFF 1
    00AB 3FFF 1
    00AC 3FFF 1
    00AD 3FFF 1
    00AE 3FFF 1
    00AF 3FFF 1
    00B0 3FFF 1
    00B1 3FFF 1
    00B2 3FFF 1
    00B3 3FFF 1
    00B4 3FFF 1
    00B5 3FFF 1
    00B6 3FFF 1
    00B7 3FFF 1
    00B8 3FFF 1
    00B9 3FFF 1
    00BA 3FFF 1
    00BB 3FFF 1
    00BC 3FFF 1
    00BD 3FFF 1
    00BE 3FFF 1
    00BF 3FFF 1
    00C0 3FFF 1
    00C1 3FFF 1
    00C2 3FFF 1
    00C3 3FFF 1
    00C4 3FFF 1
    00C5 3FFF 1
    00C6 3FFF 1
    00C7 3FFF 1
    00C8 3FFF 1
    00C9 3FFF 1
    00CA 3FFF 1
    00CB 3FFF 1
    00CC 3FFF 1
    00CD 3FFF 1
    00CE 3FFF 1
    00CF 3FFF 1
    00D0 3FFF 1
    00D1 3FFF 1
    00D2 3FFF 1
    00D3 3FFF 1
    00D4 3FFF 1
    00D5 3FFF 1
    00D6 3FFF 1
    00D7 3FFF 1
    00D8 3FFF 1
    00D9 3FFF 1
    00DA 3FFF 1
    00DB 3FFF 1
    00DC 3FFF 1
    00DD 3FFF 1
    00DE 3FFF 1
    00DF 3FFF 1
    00E0 3FFF 1
    00E1 3FFF 1
    00E2 3FFF 1
    00E3 3FFF 1
    00E4 3FFF 1
    00E5 3FFF 1
    00E6 3FFF 1
    00E7 3FFF 1
    00E8 3FFF 1
    00E9 3FFF 1
    00EA 3FFF 1
    00EB 3FFF 1
    00EC 3FFF 1
    00ED 3FFF 1
    00EE 3FFF 1
    00EF 3FFF 1
    00F0 3FFF 1
    00F1 3FFF 1
    00F2 3FFF 1
    00F3 3FFF 1
    00F4 3FFF 1
    00F5 3FFF 1
    00F6 3FFF 1
    00F7 3FFF 1
    00F8 3FFF 1
    00F9 3FFF 1
    00FA 3FFF 1
    00FB 3FFF 1
    00FC 3FFF 1
    00FD 3FFF 1
    00FE 3FFF 1
    00FF 3FFF 1
    0100 3FFF 1
    0101 3FFF 1
    0102 3FFF 1
    0103 3FFF 1
    0104 3FFF 1
    0105 3FFF 1
    0106 3FFF 1
    0107 3FFF 1
    0108 3FFF 1
    0109 3FFF 1
    010A 3FFF 1
    010B 3FFF 1
    010C 3FFF 1
    010D 3FFF 1
    010E 3FFF 1
    010F 3FFF 1
    0110 3FFF 1
    0111 3FFF 1
    0112 3FFF 1
    0113 3FFF 1
    0114 3FFF 1
    0115 3FFF 1
    0116 3FFF 1
    0117 3FFF 1
    0118 3FFF 1
    0119 3FFF 1
    011A 3FFF 1
    011B 3FFF 1
    011C 3FFF 1
    011D 3FFF 1
    011E 3FFF 1
    011F 3FFF 1
    0120 3FFF 1
    0121 3FFF 1
    0122 3FFF 1
    0123 3FFF 1
    0124 3FFF 1
    0125 3FFF 1
    0126 3FFF 1
    0127 3FFF 1
    0128 3FFF 1
    0129 3FFF 1
    012A 3FFF 1
    012B 3FFF 1
    012C 3FFF 1
    012D 3FFF 1
    012E 3FFF 1
    012F 3FFF 1
    0130 3FFF 1
    0131 3FFF 1
    0132 3FFF 1
    0133 3FFF 1
    0134 3FFF 1
    0135 3FFF 1
    0136 3FFF 1
    0137 3FFF 1
    0138 3FFF 1
    0139 3FFF 1
    013A 3FFF 1
    013B 3FFF 1
    013C 3FFF 1
    013D 3FFF 1
    013E 3FFF 1
    013F 3FFF 1
    0140 3FFF 1
    0141 3FFF 1
    0142 3FFF 1
    0143 3FFF 1
    0144 3FFF 1
    0145 3FFF 1
    0146 3FFF 1
    0147 3FFF 1
    0148 3FFF 1
    0149 3FFF 1
    014A 3FFF 1
    014B 3FFF 1
    014C 3FFF 1
    014D 3FFF 1
    014E 3FFF 1
    014F 3FFF 1
    0150 3FFF 1
    0151 3FFF 1
    0152 3FFF 1
    0153 3FFF 1
    0154 3FFF 1
    0155 3FFF 1
    0156 3FFF 1
    0157 3FFF 1
    0158 3FFF 1
    0159 3FFF 1
    015A 3FFF 1
    015B 3FFF 1
    015C 3FFF 1
    015D 3FFF 1
    015E 3FFF 1
    015F 3FFF 1
    0160 3FFF 1
    0161 3FFF 1
    0162 3FFF 1
    0163 3FFF 1
    0164 3FFF 1
    0165 3FFF 1
    0166 3FFF 1
    0167 3FFF 1
    0168 3FFF 1
    0169 3FFF 1
    016A 3FFF 1
    016B 3FFF 1
    016C 3FFF 1
    016D 3FFF 1
    016E 3FFF 1
    016F 3FFF 1
    0170 3FFF 1
    0171 3FFF 1
    0172 3FFF 1
    0173 3FFF 1
    0174 3FFF 1
    0175 3FFF 1
    0176 3FFF 1
    0177 3FFF 1
    0178 3FFF 1
    0179 3FFF 1
    017A 3FFF 1
    017B 3FFF 1
    017C 3FFF 1
    017D 3FFF 1
    017E 3FFF 1
    017F 3FFF 1
    [cut to keep under 50k chars - all is 3FFF]
    07C0 3FFF 1
    07C1 3FFF 1
    07C2 3FFF 1
    07C3 3FFF 1
    07C4 3FFF 1
    07C5 3FFF 1
    07C6 3FFF 1
    07C7 3FFF 1
    07C8 3FFF 1
    07C9 3FFF 1
    07CA 3FFF 1
    07CB 3FFF 1
    07CC 3FFF 1
    07CD 3FFF 1
    07CE 3FFF 1
    07CF 3FFF 1
    07D0 3FFF 1
    07D1 3FFF 1
    07D2 3FFF 1
    07D3 3FFF 1
    07D4 3FFF 1
    07D5 3FFF 1
    07D6 3FFF 1
    07D7 3FFF 1
    07D8 3FFF 1
    07D9 3FFF 1
    07DA 3FFF 1
    07DB 3FFF 1
    07DC 3FFF 1
    07DD 3FFF 1
    07DE 3FFF 1
    07DF 3FFF 1

 274899188: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    0000 0070 2F00 0182 3FED
    0004 018B 3FEE 019A 2F80
    0008 019B 2F1C 0183 3FFE
    000C 2AFF 3054 3FED 0B81
    0010 1F91 2F05 0B80 1AD0
    0014 3013 1F90 0063 3016
    0018 1180 3016 1D90 18D0
    001C 301B 2F01 1950 2FFF
    0020 0C01 018B 0B81 1AD0
    0024 3023 1B50 304F 2F04
    0028 0188 18D0 3029 2F02
    002C 0182 1304 1305 2F6E
    0030 0B82 2F00 0B83 0006
    0034 0B04 0007 0805 1584
    0038 1685 1004 1282 1083
    003C 1A40 3033 1F90 1AD0
    0040 303F 1584 1685 0590
    0044 18D0 3044 1950 303F
    0048 1D90 1AD0 3049 18D0
    004C 304B 1B50 302B 18D0
    0050 304F 1B50 3011 3053
    0054 018B 1ED1 1ED0 2F03
    0058 0BC1 2F8A 0BC0 2F56
    005C 0063 305C 11C0 305C
    0060 11C1 305C 1CD0 2F03
    0064 0BC1 2F8A 0BC0 2F56
    0068 0063 3068 11C0 3068
    006C 11C1 3068 3056 3FFF


 282886688: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07EC 3FFF 0281 027A 1FFE
    07F0 0026 0026 3FFF 3FFF
    07F8 1850 3F54 3FFF 3FFF
    07FC 3FFF 3FFF 02FF 31FD


 290648239: FLASH_READ_A

    ADDR DATA ?
    -----------
    07E0 3FFF 0
    07E1 3FFF 0
    07E2 3FFF 1
    07E3 3FFF 1
    07E4 3FFF 1
    07E5 3FFF 1
    07E6 3FFF 1
    07E7 3FFF 1
    07E8 3FFF 1
    07E9 3FFF 1
    07EA 3FFF 1
    07EB 3FFF 1
    07EC 3FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 3FFF 0
    07F3 3FFF 0
    07F4 3FFF 1
    07F5 3FFF 1
    07F6 3FFF 1
    07F7 3FFF 1
    07F8 1850 1
    07F9 3F54 1
    07FA 3FFF 1
    07FB 3FFF 1
    07FC 3FFF 1
    07FD 3FFF 1
    07FE 02FF 1
    07FF 31FD 1

 296126144: FLASH_READ_A

    ADDR DATA ?
    -----------
    0000 0070 0
    0001 2F00 0
    0002 0182 0
    0003 3FED 0
    0004 018B 0
    0005 3FEE 1
    0006 019A 0
    0007 2F80 1
    0008 019B 0
    0009 2F1C 0
    000A 0183 0
    000B 3FFE 0
    000C 2AFF 0
    000D 3054 1
    000E 3FED 0
    000F 0B81 1
    0010 1F91 1
    0011 2F05 0
    0012 0B80 1
    0013 1AD0 0
    0014 3013 0
    0015 1F90 1
    0016 0063 1
    0017 3016 1
    0018 1180 0
    0019 3016 1
    001A 1D90 1
    001B 18D0 1
    001C 301B 1
    001D 2F01 1
    001E 1950 1
    001F 2FFF 0
    0020 0C01 1
    0021 018B 0
    0022 0B81 0
    0023 1AD0 0
    0024 3023 0
    0025 1B50 1
    0026 304F 1
    0027 2F04 1
    0028 0188 1
    0029 18D0 0
    002A 3029 0
    002B 2F02 1
    002C 0182 1
    002D 1304 0
    002E 1305 0
    002F 2F6E 1
    0030 0B82 1
    0031 2F00 0
    0032 0B83 0
    0033 0006 0
    0034 0B04 0
    0035 0007 0
    0036 0805 0
    0037 1584 0
    0038 1685 0
    0039 1004 1
    003A 1282 1
    003B 1083 1
    003C 1A40 1
    003D 3033 1
    003E 1F90 1
    003F 1AD0 1
    0040 303F 1
    0041 1584 1
    0042 1685 1
    0043 0590 1
    0044 18D0 1
    0045 3044 0
    0046 1950 1
    0047 303F 1
    0048 1D90 1
    0049 1AD0 1
    004A 3049 1
    004B 18D0 1
    004C 304B 1
    004D 1B50 1
    004E 302B 1
    004F 18D0 1
    0050 304F 1
    0051 1B50 1
    0052 3011 1
    0053 3053 1
    0054 018B 1
    0055 1ED1 1
    0056 1ED0 0
    0057 2F03 1
    0058 0BC1 1
    0059 2F8A 0
    005A 0BC0 0
    005B 2F56 0
    005C 0063 0
    005D 305C 0
    005E 11C0 0
    005F 305C 1
    0060 11C1 1
    0061 305C 1
    0062 1CD0 1
    0063 2F03 1
    0064 0BC1 1
    0065 2F8A 0
    0066 0BC0 0
    0067 2F56 0
    0068 0063 0
    0069 3068 0
    006A 11C0 0
    006B 3068 1
    006C 11C1 1
    006D 3068 1
    006E 3056 1
    006F 3FFF 1

 304013692: FLASH_READ_A

    ADDR DATA ?
    -----------
    07E0 3FFF 0
    07E1 3FFF 0
    07E2 3FFF 1
    07E3 3FFF 1
    07E4 3FFF 1
    07E5 3FFF 1
    07E6 3FFF 1
    07E7 3FFF 1
    07E8 3FFF 1
    07E9 3FFF 1
    07EA 3FFF 1
    07EB 3FFF 1
    07EC 3FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 3FFF 0
    07F3 3FFF 0
    07F4 3FFF 1
    07F5 3FFF 1
    07F6 3FFF 1
    07F7 3FFF 1
    07F8 1850 1
    07F9 3F54 1
    07FA 3FFF 1
    07FB 3FFF 1
    07FC 3FFF 1
    07FD 3FFF 1
    07FE 02FF 1
    07FF 31FD 1

 308485218: FLASH_READ_A

    ADDR DATA ?
    -----------
    0000 0070 0
    0001 2F00 0
    0002 0182 0
    0003 3FED 0
    0004 018B 0
    0005 3FEE 0
    0006 019A 0
    0007 2F80 0
    0008 019B 0
    0009 2F1C 0
    000A 0183 0
    000B 3FFE 0
    000C 2AFF 0
    000D 3054 0
    000E 3FED 0
    000F 0B81 1
    0010 1F91 1
    0011 2F05 0
    0012 0B80 0
    0013 1AD0 0
    0014 3013 0
    0015 1F90 1
    0016 0063 1
    0017 3016 1
    0018 1180 0
    0019 3016 0
    001A 1D90 1
    001B 18D0 1
    001C 301B 1
    001D 2F01 1
    001E 1950 1
    001F 2FFF 0
    0020 0C01 1
    0021 018B 0
    0022 0B81 0
    0023 1AD0 0
    0024 3023 0
    0025 1B50 1
    0026 304F 1
    0027 2F04 0
    0028 0188 1
    0029 18D0 0
    002A 3029 0
    002B 2F02 1
    002C 0182 1
    002D 1304 0
    002E 1305 0
    002F 2F6E 0
    0030 0B82 1
    0031 2F00 0
    0032 0B83 0
    0033 0006 0
    0034 0B04 0
    0035 0007 0
    0036 0805 0
    0037 1584 0
    0038 1685 0
    0039 1004 0
    003A 1282 1
    003B 1083 1
    003C 1A40 1
    003D 3033 1
    003E 1F90 1
    003F 1AD0 1
    0040 303F 1
    0041 1584 1
    0042 1685 1
    0043 0590 1
    0044 18D0 1
    0045 3044 0
    0046 1950 1
    0047 303F 1
    0048 1D90 1
    0049 1AD0 1
    004A 3049 1
    004B 18D0 1
    004C 304B 1
    004D 1B50 1
    004E 302B 1
    004F 18D0 1
    0050 304F 1
    0051 1B50 1
    0052 3011 1
    0053 3053 1
    0054 018B 1
    0055 1ED1 1
    0056 1ED0 0
    0057 2F03 1
    0058 0BC1 1
    0059 2F8A 0
    005A 0BC0 0
    005B 2F56 0
    005C 0063 0
    005D 305C 0
    005E 11C0 0
    005F 305C 1
    0060 11C1 1
    0061 305C 1
    0062 1CD0 1
    0063 2F03 1
    0064 0BC1 1
    0065 2F8A 0
    0066 0BC0 0
    0067 2F56 0
    0068 0063 0
    0069 3068 0
    006A 11C0 0
    006B 3068 1
    006C 11C1 1
    006D 3068 1
    006E 3056 1
    006F 3FFF 1

 315382824: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    0000 0070 2F00 0182 3FED
    0004 018B 3FEE 019A 2F80
    0008 019B 2F1C 0183 3FFE
    000C 2AFF 3054 3FED 0B81
    0010 1F91 2F05 0B80 1AD0
    0014 3013 1F90 0063 3016
    0018 1180 3016 1D90 18D0
    001C 301B 2F01 1950 2FFF
    0020 0C01 018B 0B81 1AD0
    0024 3023 1B50 304F 2F04
    0028 0188 18D0 3029 2F02
    002C 0182 1304 1305 2F6E
    0030 0B82 2F00 0B83 0006
    0034 0B04 0007 0805 1584
    0038 1685 1004 1282 1083
    003C 1A40 3033 1F90 1AD0
    0040 303F 1584 1685 0590
    0044 18D0 3044 1950 303F
    0048 1D90 1AD0 3049 18D0
    004C 304B 1B50 302B 18D0
    0050 304F 1B50 3011 3053
    0054 018B 1ED1 1ED0 2F03
    0058 0BC1 2F8A 0BC0 2F56
    005C 0063 305C 11C0 305C
    0060 11C1 305C 1CD0 2F03
    0064 0BC1 2F8A 0BC0 2F56
    0068 0063 3068 11C0 3068
    006C 11C1 3068 3056 3FFF


 337347740: 0000001010010100011101010100101000111010
 359606267: 0000001010010100011101010100101000111010
 373491436: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07EC 3FFF 0281 027A 1FFE
    07F0 0026 0026 3FFF 3FFF
    07F8 1850 3F54 3FFF 3FFF
    07FC 3FFF 3FFF 0282 31FD


 378465137: FLASH_READ_A

    ADDR DATA ?
    -----------
    07E0 3FFF 0
    07E1 3FFF 0
    07E2 3FFF 1
    07E3 3FFF 1
    07E4 3FFF 1
    07E5 3FFF 1
    07E6 3FFF 1
    07E7 3FFF 1
    07E8 3FFF 1
    07E9 3FFF 1
    07EA 3FFF 1
    07EB 3FFF 1
    07EC 3FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 3FFF 0
    07F3 3FFF 0
    07F4 3FFF 1
    07F5 3FFF 1
    07F6 3FFF 1
    07F7 3FFF 1
    07F8 1850 1
    07F9 3F54 1
    07FA 3FFF 1
    07FB 3FFF 1
    07FC 3FFF 1
    07FD 3FFF 1
    07FE 0282 1
    07FF 31FD 1

 383944796: FLASH_READ_A

    ADDR DATA ?
    -----------
    07E0 3FFF 0
    07E1 3FFF 0
    07E2 3FFF 1
    07E3 3FFF 1
    07E4 3FFF 1
    07E5 3FFF 1
    07E6 3FFF 1
    07E7 3FFF 1
    07E8 3FFF 1
    07E9 3FFF 1
    07EA 3FFF 1
    07EB 3FFF 1
    07EC 3FFF 1
    07ED 0281 1
    07EE 027A 1
    07EF 1FFE 0
    07F0 0026 0
    07F1 0026 1
    07F2 3FFF 0
    07F3 3FFF 0
    07F4 3FFF 1
    07F5 3FFF 1
    07F6 3FFF 1
    07F7 3FFF 1
    07F8 1850 1
    07F9 3F54 1
    07FA 3FFF 1
    07FB 3FFF 1
    07FC 3FFF 1
    07FD 3FFF 1
    07FE 0282 1
    07FF 31FD 1

 388416569: FLASH_WRITE_A

    ADDR -W1- -W2- -W3- -W4-
    ------------------------
    07EC 3FFF 0281 027A 1FFE
    07F0 0026 0026 3FFF 3FFF
    07F8 1850 3F54 3FFF 3FFF
    07FC 3FFF 3FFF 0282 31FD




We can now be sure that:

EDIT: There's a repo I've made for the tiny Python scripts I'm using, since uploading them manually here is annoying: https://github.com/socram8888/pdkscope
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 31, 2018, 07:15:51 am
Thanks for the new capture.

One odd thing I noticed is that the clock duty cycle changes during the data transmissions (and commands) maybe thats indicative of a handover to the micro being programmed: active output -> pull-up on the programmer side and pulldown on the micro side.

Then the trailing AA1 could be an acknowledge by the micro during commands
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 31, 2018, 07:18:53 am
In this sequence of the verify it looks like the programmer supplies the adress and then the micro responds with the data.

The micro probably samples on rising edges, the programmer on falling.

Format changes as well, 8bitish for the commands, 14 bitish for the data/adresses -> probably different for different core sizes. (PICs have padding to make it all nice and 16bitish ;)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 31, 2018, 09:51:59 am
Whats a bit weird is that it seems to write during verify also.

I assume that its writing because the clocks after command 0x70 and data are slower than usual (8 clock cycles total).
Also while its reading in address/data fashion, it writes 4 words at a time (5*14=70 bits, one address first I assume)

Maybe its re-writing and re-reading bits that didnt match?

Towards the end there seem to be two runs of the calibration program followed by writes to the calibration bytes.

The last command is also a write, that isnt read back/verified. Maybe a usage counter? Why?

Vpp -> Vdd : 200 us
Vdd -> Data : 1000 us
larger pauses to stabilize voltages?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 31, 2018, 10:07:59 am
There was a slightly problem while I was exporting the TXT file for processing, apparently the LAP-C program didn't like exporting a 20GB file and crashed before finishing  ;D

So I'm not sure if the file contains all the commands and all the messages. The program doesn't display what percentage of the file it has processed, so I'm not sure how much data was still remaining to be exported.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 31, 2018, 10:21:54 am
There was a slightly problem while I was exporting the TXT file for processing, apparently the LAP-C program didn't like exporting a 20GB file and crashed before finishing  ;D

So I'm not sure if the file contains all the commands and all the messages. The program doesn't display what percentage of the file it has processed, so I'm not sure how much data was still remaining to be exported.

You dont need to export everything, just the command sequences would be fine. At the beginning and end theres blank checking.
There are two phases where data is read and there are shorter phases in between where I think data is beeing re-writen.
Maybe you can just export shorter parts.

You have to set bars and export from bar to bar. But you can only use A and B bar Why?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 31, 2018, 11:03:33 am
I've just checked by opening the TXT and looking at the timestamps it actually exported everything, from -4864 to 500936754.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 31, 2018, 12:38:19 pm
Great findings from all of you.

I think it's time to test some of the observations. I will start with the VERIFY (READ).

I will assume that VDD/VPP = 3.3V will be ok for this. Then I just can connect the input/output of the host MCU to padauk IC directly.

After looking at the different bit counts for input / output transmissions which can not be mapped to 8 bit I think using the hardware SPI of host MCU will not work out well.

This means I will try to bit bang the protocol with a tight loop (might be hard when capturing input from IC assuming 1MHz clock).

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on December 31, 2018, 12:53:43 pm
I will assume that VDD/VPP = 3.3V will be ok for this. Then I just can connect the input/output of the host MCU to padauk IC directly.

I'm not sure this will work.
The sequence must probably be observed:
Apply Vpp (5.6V) before Vdd (2.6V) (thats the same as with PICs)    -> select programming mode, command phase
Send command
Change Vdd to 4.3V to read data   -> data phase

I think theres a voltage dependent state machine at work that tells the micro what to do.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 31, 2018, 01:09:01 pm
Maybe it does, or maybe it just relies on the order rather than actual voltages. I think it's worth looking before proceeding with designing the programmer.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on December 31, 2018, 05:06:10 pm
First test result:

VPP 3.3V seems NOT to work. IC starts exactly same as when VPP is not applied (52.40ms till blink out starts on PA.3)

Need to add transistor now to toggle 5V.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on December 31, 2018, 06:03:21 pm
First test result:

VPP 3.3V seems NOT to work. IC starts exactly same as when VPP is not applied (52.40ms till blink out starts on PA.3)

Need to add transistor now to toggle 5V.
I'd try 3.3V on VDD rather than VPP.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 01, 2019, 03:25:17 pm
I did some experiments.

Everything up to 5.5V on VPP (PA.5) is ignored (this is maximum rating in IC data sheet for VDD and pins) and IC starts up normally.

As soon >5.6V (tested up to 12V) is present on VPP (PA.5) the startup of the IC is different (I guess programing/command mode).

Need to hook up logic analyzer to bread board now.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 01, 2019, 06:32:44 pm
FIRST BIG SUCCESS...

After some try and error I completed Level1  ^-^ ^-^ : CLOCK is ALWAYS sent from WRITER.

- a command is sent with preamble 0xA5A5A5A followed by 8 bit COMMAND
- after last bit from command was sent DATA switches directions
- IC sends back 0xAA and 4 bit status (maybe something like this: b0001 = ok, b0000 = error), clock must be supplied by WRITER

This only works with VPP > 5.5 V.

JS

EDIT: 3.3V was used for VDD.


Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 01, 2019, 07:09:48 pm
Great job! The IC seems to be sampling the data pin on falling edge, then, is that right?  While it seems the incoming data must be sampled on the rising edge.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 01, 2019, 07:36:17 pm
Great job! The IC seems to be sampling the data pin on falling edge, then, is that right?  While it seems the incoming data must be sampled on the rising edge.

Not there yet ... in command mode it looks like I can sample either on rising or on falling edge.

Could you describe the READ command (0x60) in detail?

>A5A5A5A60
<AA1

>? ? ?
<? ? ?
...

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 01, 2019, 08:20:08 pm
>A5A5A5A60
<AA1

>? ? ?
<? ? ?

AFAICT the programmer supplies the address of the location it wants to read (looking at the dutycycle of the clock) see the picture in my post December 31, 2018, 08:51:59 pm.
Starting with 0 and counting up. 14 bit address from the programmer, then 14 bits of data are returned by the micro.
I guess the clock is supplied by the programmer.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 01, 2019, 08:24:53 pm
Maybe the vdd voltage has to be changed as well. From 2.6V to 4.3V.
Might be important for the micro to distinguish between command and data modes.
However might not be as sensitive to the actual voltage as I thought, so maybe 2.5V and 5V is fine.
Or no change at all ;)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 01, 2019, 08:35:59 pm
Not there yet ... in command mode it looks like I can sample either on rising or on falling edge.

Could you describe the READ command (0x60) in detail?
Sure.
Code: [Select]
Enter read mode:
>A5A5A5A61 (36 bits)
<1010 1010 0001 0 (13 bits)

Voltage is on VDD now raised to 4.3V

Read word:
>address (13 bits)
<word (14 bits)
>unknown, seemingly always 1 (1 bit)
Note command seems to be 61 instead of 60, or at least that what I got from the 200 MHz dump, and from previous using the "sticky" (ie one if it's high on either falling or rising) approach.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 01, 2019, 08:46:36 pm
Maybe the last bit is just an ACK?
If you supply an adress outside of the chips memory range > 2048 for the PFS154 maybe it returns 0?

Maybe thats the stop condition for a read? Edit: Nope.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 01, 2019, 09:02:47 pm
Write command format, in case you want to try it:
Code: [Select]
>A5A5A5A71 (36 bits)
<1010 1010 0001 0 (13 bits)

VPP is raised to 8.3V

<word1 (14 bits)
<word2 (14 bits)
<word3 (14 bits)
<word4 (14 bits)
<address (13 bits)
<000000000 (padding? not sure about the direction of this one - 9 bits)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 01, 2019, 09:49:35 pm
<000000000 (padding? not sure about the direction of this one - 9 bits)

Thats probably just something to get the micro to program the locations after the data has been supplied.

There's also a one right before that that appears on the data line but is not accompanied by a clockcycle. Dont know whats that for or if its even important.

Also shouldn't it be >word above?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 01, 2019, 10:14:21 pm
Level 2 done... complete readout.

Attached the logic analyzer capture from the readout. I decreased some stupid delays and did not make the song and dance at the beginning. Just send command 0x60 and then read data.

Summary:
VPP: 5.6V
VDD: 3.3V
>0xA5A5A5A
>0x60
<0xAA1
>0x0000  (14 bit addr)
<0x0070  (14 bit data)
>0x0001  (14 bit addr)
<0x2F00  (14 bit data)
...
>0x07FF  (14 bit addr)
<0x31FD (14 bit data)
VDD: 0V
VPP: 0V

 8) 8) 8) 8) 8)

JS


EDIT: I'm tempted to set security bit.... and try again ;-)

EDIT2: It was not working when using 13 bit address... not sure why. Maybe clock style is wrong or pullup/down or ... is needed?

EDIT3: Reading from address 0x800 ... returns same as 0x000 ... (so address just wraps around)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 01, 2019, 10:18:10 pm
Write command format, in case you want to try it:
Code: [Select]
>A5A5A5A71 (36 bits)
<1010 1010 0001 0 (13 bits)

VPP is raised to 8.3V

<word1 (14 bits)
<word2 (14 bits)
<word3 (14 bits)
<word4 (14 bits)
<address (13 bits)
<000000000 (padding? not sure about the direction of this one - 9 bits)

This is next I will try... (tomorrow maybe).

> VPP is raised to 8.3V

What I found out... READ is also working with VPP 8.3V and VPP 12.0V  so maybe just 12V VPP is needed :-) ?

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 01, 2019, 10:27:02 pm
Write command format, in case you want to try it:
Code: [Select]
>A5A5A5A71 (36 bits)
<1010 1010 0001 0 (13 bits)

VPP is raised to 8.3V

<word1 (14 bits)
<word2 (14 bits)
<word3 (14 bits)
<word4 (14 bits)
<address (13 bits)
<000000000 (padding? not sure about the direction of this one - 9 bits)

This is next I will try... (tomorrow maybe).

> VPP is raised to 8.3V

What I found out... READ is also working with VPP 8.3V and VPP 12.0V  so maybe just 12V VPP is needed :-) ?

JS

That would also simplify voltage regulation significantly.
Just double (triple) Vdd and apply to Vpp. (Does it really need to be 8.3V ???)
That can be done with a charge pump.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 01, 2019, 10:29:46 pm
Could you please try also with 0x61? I wonder why I'm getting that if it's 0x60.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 01, 2019, 10:39:37 pm
Could you please try also with 0x61? I wonder why I'm getting that if it's 0x60.

OK, tested 0x60, 0x61, 0x62, ... 0x6F ... all same result: VALID READ  :)

=> seems command is just 0x6  and then 4 dummy clocks are used before switching mode (the 4 clocks are really needed, I thought maybe preamble 28 bit + 4 bit command = nice 32 bit... but nope)

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 01, 2019, 11:16:18 pm
Could you please try also with 0x61? I wonder why I'm getting that if it's 0x60.

OK, tested 0x60, 0x61, 0x62, ... 0x6F ... all same result: VALID READ  :)

=> seems command is just 0x6  and then 4 dummy clocks are used before switching mode (the 4 clocks are really needed, I thought maybe preamble 28 bit + 4 bit command = nice 32 bit... but nope)

JS
That seems correct. It looks like the writer itself is using 0x67 at some point for reading in place of 0x61 and 0x60.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 02, 2019, 07:31:03 pm
FIRST BIG SUCCESS...

After some try and error I completed Level1  ^-^ ^-^ : CLOCK is ALWAYS sent from WRITER.

- a command is sent with preamble 0xA5A5A5A followed by 8 bit COMMAND
- after last bit from command was sent DATA switches directions
- IC sends back 0xAA and 4 bit status (maybe something like this: b0001 = ok, b0000 = error), clock must be supplied by WRITER

This only works with VPP > 5.5 V.

JS

EDIT: 3.3V was used for VDD.


I tried to replicate your experiment with the 0x60 command (minus powercycling I just switch it on), but I only have blank chips.
They dont respond at all.

Could you try with a blank chip?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 02, 2019, 08:00:36 pm
I tried to replicate your experiment with the 0x60 command (minus powercycling I just switch it on), but I only have blank chips.
They dont respond at all.

Could you try with a blank chip?

Which IC do you try to use?
I use PFS154-S16 (erasable flash, 1000 write cycles)

I use the following sequence (I tested with 200kHz up to almost 2MHz for CLK pulses, all working):

- enable VPP 6.0V (I use external power supply for VPP and switch it on using a transistor)
- wait 100µs
- enable VDD 3.3V (driven from STM32 GPIO output pin directly)
- wait 500µs
- switch DAT to output
- send preamble + command bit by bit (28 bit + 8 bit): 0xA5A5A5A60
    bit send loop:
   * set current bit on DAT (MSB first)
   * CLK high
     * optional wait 1µs
   * CLK low
     * optional wait 1µs
- switch DAT to input
- receive ACK (12 bit):
    bit receive loop:
    * CLK high
    * read DAT bit (MSB)
      * optional wait 1µs
    * CLK low
      * optional wait 1µs
- check that ACK is 0xAA1

- 1 extra clock
   * CLK high
     * optional wait 1µs
   * CLK low
     * optional wait 1µs
- switch DAT to output

- send address (13 bit)
- switch DAT to input
- recv data (14 bit)
- 1 extra clock
   * CLK high
     * optional wait 1µs
   * CLK low
     * optional wait 1µs
- switch DAT to output

...

- send address (13 bit)
- switch DAT to input
- recv data (14 bit)
- 1 extra clock
   * CLK high
     * optional wait 1µs
   * CLK low
     * optional wait 1µs
- switch DAT to output

- wait 100µs
- disable VDD
- wait 20µs
- disable VPP

----------------

I think the sequence "VPP on, wait 100µs, VDD on, wait 500µs, send command" is essential.
Also if you make a mistake like sending a wrong preamble or bad command the IC will exit special mode and just start normal execution.

I will try to read an empty IC later.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 02, 2019, 08:24:16 pm
I use an arduino (clone).
The code I use is a bit of a mess right now because I hardcoded the command.
My futile attempt to remove errors ;)
However it should be almost identical to the code you have.

So powercycling timing seems to be important.

Code: [Select]
void PADAUK_write_bit (unsigned char b) {
  digitalWrite(PA6_data, b);
  delayMicroseconds(1);
  digitalWrite(PA3_clk, 1);
  delayMicroseconds(1);
  digitalWrite(PA3_clk, 0);
  delayMicroseconds(1); 
}

unsigned char PADAUK_read_bit () {
  digitalWrite(PA3_clk, 1);
  delayMicroseconds(1);
  unsigned char b = digitalRead(PA6_data);
  digitalWrite(PA3_clk, 0);
  delayMicroseconds(1); 
  return b;
}

void PADAUK_command(unsigned char cmd) {
//A
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
//5
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
//A
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
//5
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
//A
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
//5
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
//A
PADAUK_write_bit(1);
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
//6
PADAUK_write_bit(0);
PADAUK_write_bit(1);
PADAUK_write_bit(1);
PADAUK_write_bit(0);
//0
PADAUK_write_bit(0);
PADAUK_write_bit(0);
PADAUK_write_bit(0);
PADAUK_write_bit(0);

pinMode(PA6_data, INPUT_PULLUP);
delayMicroseconds(1);

PADAUK_read_bit();
PADAUK_read_bit();
PADAUK_read_bit();
PADAUK_read_bit();

PADAUK_read_bit();
PADAUK_read_bit();
PADAUK_read_bit();
PADAUK_read_bit();

PADAUK_read_bit();
PADAUK_read_bit();
PADAUK_read_bit();
PADAUK_read_bit();

pinMode(PA6_data, OUTPUT);
digitalWrite(PA6_data, 0);
}

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 02, 2019, 08:25:19 pm
The output waveform looks identical to your capture otherwise.

Vdd is 5V, Vpp is 7.8 right now but I have tried several values from 5.6 to 12 V.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 02, 2019, 10:17:28 pm
Level 3 done  8) :

I just got ERASE working.

I had to insert one small extra CLK directly after command, so ERASE sequence was like this (maybe can be stripped down):
- enable VPP 8.3V
- wait 100µs
- enable VDD 3.3V
- wait 500 µs
- send preamble+command (28 bit + 8 bit): 0xA5A5A5A30
- receive ack (12 bit)
- CLK_UP
- CLK_DOWN
- wait 10000µs
- CLK UP
- wait 5000µs
- CLK_DOWN
- CLK_UP
- CLK_DOWN
- CLK_UP
- wait 5000µs
- CLK_DOWN
- CLK_UP
- CLK_DOWN
- wait 150 µs
- disable VDD
- wait 250 µs
- disable VPP

---------

complete IC (PFS154) was erased *EXCEPT* 3 words stayed constant:
@0x7ED : 0x0281    => RET 0x81
@0x7EF : 0x027A    => RET 0x7A
@0x7F0 : 0x1FFF    ? ? ? maybe a "magic value"

So looks like to identify a flash IC the 0x1FFF is detected (followed by 2 times erase counter, which was erased :-) )
The specific part is encoded @0x7ED, @0x7EF (guess: coded as "RET k" so calibration routine or user program can use it to identify IC it is running on) => IC type is 0x7A81 or 0x817A 

Have fun,

JS

EDIT: BONUS points: If erase counter is erased (0x3FFF) then it starts with 0 again when using original WRITER to program the IC. It made my test IC "virgin" again :-)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 03, 2019, 01:12:09 am
AFAIK that extra clock is needed by all commands. I'm not sure how you are being able to use the read with  12 bit reply in place of the 13 as the scope shows.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: oPossum on January 03, 2019, 02:21:25 am
I am going to try using a DAC + opamp to generate the necessary variable voltages needed for programming. Driving a capacitive load with an opamp is generaly a bad idea - they will tend to oscillate. TI has a chip that they say is "awesome for driving capacitive loads!!!", so I am going to see if it really is. Hope to have all the parts in a few weeks.

http://www.ti.com/lit/ds/symlink/alm2402-q1.pdf (http://www.ti.com/lit/ds/symlink/alm2402-q1.pdf)
http://www.ti.com/lit/ds/symlink/dac084s085.pdf (http://www.ti.com/lit/ds/symlink/dac084s085.pdf)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 03, 2019, 03:03:46 pm
AFAIK that extra clock is needed by all commands. I'm not sure how you are being able to use the read with  12 bit reply in place of the 13 as the scope shows.

After looking at the captures some more time it looks like the following happens:

Example PFS154 READ:

>preamble 28 bit
>command 4 bit
- 4 clocks
<ack 12 bit
- 1 clock
>addr 13 bit
<data 14 bit
- 1 clock
>addr 13 bit
< data 14 bit
- 1 clock
...
>addr 13 bit
< data 14 bit
- 1 clock

(It looks like whenever a switch from DAT-INPUT mode to DAT-OUTPUT mode is performed this extra "1 clock" is required)

My previous READ was working since I used 14 bit as address, which supplied the extra clock after switching DAT form input to output.

I will edit previous posts to have 13 bit address.

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 04, 2019, 12:50:50 am
Still not fully done...

I changed my READ to use 13 bit and sending extra clock.

Now I have a very reliable READ and ERASE.

However the WRITE is not working yet. Not a single bit is written. I massaged my DAT/CLK output to be almost identical to the one from WRITER.
The only difference I found is that it looks like after WRITER sent command "WRITE" VPP gets increased to 8V followed by delay of 5ms (maybe waiting for stabilization) and then (different to ERASE) also VPP is increased to 5.6V followed again by a delay of 5ms (wait for stabilization...) and then data is sent.

In order to have this feature I need to add one more transistor and power rail to my bread board and also must put a level shifter between input pins / output pins of MCU and IC ... ?? really ??

Stay tuned...

JS
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: amyk on January 04, 2019, 02:57:48 am
Think of it this way: The official programmer wouldn't have done so if it wasn't required ;)

Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: ali_asadzadeh on January 04, 2019, 10:06:45 am
That's great work :-+ :-+ :-+ any progress regarding the OTP ones? also any other part in the family?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: socram on January 04, 2019, 10:36:42 am
I could try running the SPI decoder on the OTP ones, but I'd need a scope dump first.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: spth on January 05, 2019, 06:19:47 pm
Today, I made a first step to inefficently compiling a small subset of C to Padauk asm code. The current version is very restricted and generates very inefficient code; it is untested.

There is no assembler / linker support, so the resulting .asm file has to be assembled in other ways.

[…]

Code in svn at https://svn.code.sf.net/p/sdcc/code/branches/pdk/sdcc, use -mpdk14 to target Padauk (despite the name, the set of instructions emitted is part of the common subset of the Padauk instruction sets).

On the second day, wrt. completeness of implementation of the C standard, this has now far surpassed Mini-C.

Noticeable remaining restrictions:

* Variables can only reside in RAM, not in code space
* Global and static variables are not initialized.
* No floating-point or bit-fields.
* Functions can return at most 2 bytes (i.e. no long or long long).
* Multiplicative operators are not supported.
* Functions are not reentrant.
* No support for variable arguments.
* No standard library.
* struct / union cannot be assigned, passed as arguments or returned.
* No compoundliterals.
* No access to I/O from C.

There is no glue to connect this to assembler / linker yet, so the only useable output is asm code.
The generated asm code is still very inefficient. I will look into improving that a bit soon.

Philipp

Most of the above restrictions still apply.
There is now I/O support via __sfr, __sfr16.
There is rudimentary support for reentrant functions and variable arguments, but so far it only works for simple functions).

But there are still substantial improvements. There are fewer errors during compilation, the generated code is more efficient. A large part of the standard library (i.e. nearly everything that does not rely on return values > 16 bit) now compiles without errors.

My next main goals for this month are improving the support for reentrant functions / variable arguments, implementing initialization of global and static variables and getting something basic working for the glue between compiler, assembler and linker.

Philipp

P.S.:
At this point it would be really helpful for my work on sdcc if someone with access to the hardware could find out how push af works exactly.
Does a go to [sp] and f to [sp + 1]? Does a go to [sp + 1] and f to [sp]?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on January 06, 2019, 05:44:40 pm
A first usable version of the sampling software for my ADC4 board is done with the 1 GB RAM. As always needed a bit longer than expected, not as easy as it should be to access DDR3 RAM from a FPGA. I included a test mode which saves a counter in the RAM to check it, and also a CRC8 checksum because I'm transferring it over an external serial port connection. Sometimes there are transfer errors, but the CRC8 checksum detects it and I transfer the block then again. So the data should be very accurate.

I recorded the programming cycle of a PMS150C with SOT-23-6 package. There is no extra information with 25 MHz, so I used 12.5 MHz samplerate.

I stored the data in Sigrok format to view with PulseView (https://sigrok.org/wiki/PulseView), which is the best open source program for viewing analog data that I could find. It works for Windows, Linux and Mac. I couldn't find a way for GTKWave to show voltage divs. PulseView forgets the settings always when you load a new file, but at least it can be configured with 1 V per div and horizontal lines for each div, and navigating even in big datasets is fast and smooth. This is an example how you configure it when you click on the channel arrow:

(https://i.imgur.com/Jt9tzND.png)

You can also see the cursor, which is enabled by clicking on the blue cursor symbol in the toolbar, and which is useful for measuring time deltas.

All files are here:

http://www.frank-buss.de/tmp/dumps.zip (http://www.frank-buss.de/tmp/dumps.zip)

A *.sr file is just a zip file, and the analog-1-1-1 files are binary files of the voltages, with 4 byte float values for each sample, which could be converted back to float in Python with struct.unpack. But for easier reading I stored it in CSV format as well. The files in detail:

blinker.zip: the Padauk project and PDK file, compiled with IDE version 0.84
dump1.sr/csv: programming an already programmed PMS150C OTP chip with the blinker OTP. The following signals are connected to the channels:

CH1: PA4
CH2: PA6
CH3: VDD
CH4: PA5

The full sequence looks like this:

(https://i.imgur.com/biGVOAK.png)

PA5 (CH4) doesn't look very interesting. So for the next files dump2.sr/csv, I sampled the following signals, now using CH4 for PA3:

CH1: PA4
CH2: PA6
CH3: VDD
CH4: PA3

It looks like this:

(https://i.imgur.com/n1F36RA.png)

You can use the signals which are identical in the two dumps to correlate the PA5 signal in relation to PA3, if needed.

Then I used an empty chip and programmed it and saved it as dump3. The channel configuration is the same as used first:

CH1: PA4
CH2: PA6
CH3: VDD
CH4: PA5

It needs longer, so I sampled 2 seconds, with the same resolution of 12.5 MHz samplerate as the other dumps. Looks like this:

(https://i.imgur.com/GZMhY5a.png)

Finally I used another empty chip and programmed it, and saved the dump as dump4, now recording PA3 again instead of PA5 with CH4:

CH1: PA4
CH2: PA6
CH3: VDD
CH4: PA3

Looks like this:

(https://i.imgur.com/wjevexw.png)

I don't have much time to analyze it myself, but I guess now it shouldn't be too difficult to reverse engineer the full protocol.

PS: I disabled the open/short test with the ".writer" directive in the blinker.PRE file, because there were some problems with it with the SOT23-6 to DIP14 adapter, so some details of the dump might be different compared to the other dumps.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: tim_ on January 06, 2019, 06:40:22 pm
Thank you, that is extremely useful.

From a first glance, the programming interface of the PMC150 seems to be straight forward. The main difference to the PFS154 is that it does not seem to use a bidirectional data line, but a normal SPI interface.

My guess is that the pinout is as follows:


The program mode entry sequence is very similar to the PFS:


VPP is 7.5V during read and ~10.5V during writing. This seems rather low. Are the ADCs calibrated correctly or may there be some offset/gain error?

VDD is 6V during programming, 4V during reading and 2V for verification. I would guess that it should be ok to keep VDD at 5V if you don't want to verify all corner cases.

To understand the protocoll it will be necessary to extract the logs using an SPI protocol analyzer. I will try to use PulseView for that. I am using it for the first time. It looks nice, but seems to be lacking some functionality. For example, how is it possible to display voltage values of specific data points`?

Edit: One comment: I find the entry sequence rather odd. Usually you would try to avoid under all circumstances applying a high voltage to a CMOS input when VDD is not connected due to latch up risk and potential damage to the ESD circuit. The programmer needs to control this sequence carefully to prevent frying the device.

-
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: DocBen on January 06, 2019, 10:02:28 pm
A first usable version of the sampling software for my ADC4 board is done with the 1 GB RAM.

Not to nit-pick, but it seems there is a lot of cross talk and bouncing going on. Also clock and data seem to be out of phase in some areas.
Don't if that is really the case or if the data for the otp is really that different from the pfs154.

Have you tried to sample test signals?
Ie clock of a micro on one channel and look what the rest does?
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on January 06, 2019, 11:31:58 pm
VPP is 7.5V during read and ~10.5V during writing. This seems rather low. Are the ADCs calibrated correctly or may there be some offset/gain error?

VDD is 6V during programming, 4V during reading and 2V for verification. I would guess that it should be ok to keep VDD at 5V if you don't want to verify all corner cases.

To understand the protocoll it will be necessary to extract the logs using an SPI protocol analyzer. I will try to use PulseView for that. I am using it for the first time. It looks nice, but seems to be lacking some functionality. For example, how is it possible to display voltage values of specific data points`?


There could be an error of about 0.1 V - 0.2 V, the potentiometers are a bit sensitive, and it clips at about 10.24 V: Everything higher than this is 10.24 V. Maybe I should calibrate it for 12 V, but then the resolution gets worse.

But I verified PA5 (right, looks like VPP) with my Agilent scope and the rest should be pretty accurate. From dump3 with PulseView:

(https://i.imgur.com/Ci5YJNT.png)

And you are right, PulseView is very limited. I couldn't find a way to read the exact voltages at a location. When you move the mouse over a location, it shows it in millivolt if it is below 1 V, and only if zoomed in like crazy, and if it is above 1 V, it is rounded to closest integer values. Looks like the programmers never used a real scope  :palm: But the workaround I described works pretty well: click on the channel label, then set "number of pos vertical divs" to 10, and vertical resolution to 1 V / div. Then you will have at least each 1 V div a horizontal line.

This is how it looks like when I record it with my scope. Not the same recording sequence, but again programming an empty chip:

(https://i.imgur.com/faSjHIX.png)

As you can see, the 7.5 V is about the same, and then you can see the clipping.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: tim_ on January 06, 2019, 11:34:53 pm
Ah, interesting, that makes a lot of sense. Have you checked what the actual VPP is, instead of 10.5V? I suppose it is 12V or higher?

I got pretty far decoding the protocol, I am mainly stuck at writing right now. I will post my notes soon.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on January 06, 2019, 11:48:42 pm
Not to nit-pick, but it seems there is a lot of cross talk and bouncing going on. Also clock and data seem to be out of phase in some areas.
Don't if that is really the case or if the data for the otp is really that different from the pfs154.

Have you tried to sample test signals?
Ie clock of a micro on one channel and look what the rest does?

You are right, cross talk is terrible. But I think the recording should be very accurate regarding the timing and the phase of the signals.

I verified it with my signal generator and because of the nature of the sampling on the FPGA it is very unlikely that there is a phase error. But of course there could be still bugs in the Python script etc. If you think there are any wrong or strange signals, I can record any 2 signals with my real oscilloscope to verify it. This is a screenshot of my oscilloscope Python script, with 4 Vpp and 500 kHz from the signal generator, channel 2 phase shifted 180°:

(https://i.imgur.com/2upAumM.png)
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: tim_ on January 06, 2019, 11:53:49 pm
You are right, cross talk is terrible. But I think the recording should be very accurate regarding the timing and the phase of the signals.

From what I see, there is mainly crosstalk from Clk to VDD and MISO/MOSI. I suppose this crosstalk could also be internal to the MCU (from CMOS switching), since it is fully clocked externally in programming mode. Apart from the truncation of Vpp voltage, the logs look fine to me.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on January 06, 2019, 11:58:32 pm
Have you checked what the actual VPP is, instead of 10.5V? I suppose it is 12V or higher?

This is the full cycle of VPP with my scope:

(https://i.imgur.com/qeU5it4.png)

I verified it and the scope has no problems to measure more than 12 V, no clipping here. So it looks like the max level is about 10.8 V.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on January 07, 2019, 12:02:22 am
PS: I noticed that it looked like the programmer loads a new firmware when I switch from the PMS150C to the PMC884. So it is plausible that some parts of the programming sequence are very different depending on the chip.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: tim_ on January 07, 2019, 02:48:51 am
Please find attached my notes on analysing the programming sequence from Frank. Sorry for the bad image quality, I had to limit the filesize. I can upload it somewhere else later.

The information is not yet very structured, but I believe it should be enough to create a programmer for the PMS150C from scratch.

Something I have not yet looking into, is the clock calibration/code checksum. So, for a start, it would be easier to generate binaries without the initialization code that the Padauk IDE adds.

Many parts of the programming sequence are only to verify operation at different corner cases of the operating voltage. It is probably sufficient to stay at a single level of VDD, e.g. 5V.

A challenge that remains will be to come up with hardware that allows controlling VPP at 7.5V and 10.8V. Maybe some of the existing PIC programmers can be used as a reference.

Btw, one issue that could also be existent with the PFS154 is a strange behavior of MISO during data direction changes (see slides 12/13). Many bidirectional protocols (e.g. SWD) introduce an additional cycle for direction reversal. Padauk has omitted this, which leads to unexpected "features". Generally,  there are some parts of the protocol that look like workarounds. I'd guess they fixed things as they come, so probably there are also some inconsistencies between devices.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: FrankBuss on January 07, 2019, 05:58:54 am
Please find attached my notes on analysing the programming sequence from Frank.

Great work! The different programming voltages shouldn't be a problem. The circuit diagram from @oPossum looks good, the ALM2402 can drive up to 400 mA, so maybe no external transistor amplifier is even needed. But it has only a gain bandwidth of 600 kHz, maybe would be good to use some additional 4051 for the high frequency data lines. Could be all controlled with a cheap Arduino nano, and a simple Python script to control it and send the programming file over serial port.

I wonder why they do all these tests. I guess they don't do much tests when they produce the ICs? So far I've used about 20 PMS150C for testing, programming little things etc. One IC was not programmable. Might be a good idea if a DIY programmer would do all the verifies at different voltage levels etc. as well.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 07, 2019, 10:22:19 am
Hi,

Thanks @FrankBuss for the new captures and @tim_ for having a look at them. This confirms our previous findings of VDD/VPP sequence, CLK/DAT usage and some of the deciphered commands (READ/WRITE).
The only difference is that PMC150 just uses 12 bit address and 13 bit program words and that IC_DAT_IN and IC_DAT_OUT might be 2 different pins instead of 1 shared pin on PFS154.

JS

BTW: @tim_ (cpldcpu): Do you think it is ok to claim that this all your own work, based on captures from FrankBuss?
from page 2: > All of this work is solely based on analyzing datalogs of the programming sequence as provided here: https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg2096917/#msg2096917 (https://www.eevblog.com/forum/blog/eevblog-1144-padauk-programmer-reverse-engineering/msg2096917/#msg2096917)
Maybe next time you could also mention the work of the eevblog forums community members.
Title: Re: EEVblog #1144 - Padauk Programmer Reverse Engineering
Post by: js_12345678_55AA on January 07, 2019, 10:48:37 am

The different programming voltages shouldn't be a problem. The circuit diagram from @oPossum looks good, the ALM2402 can drive up to 400 mA, so maybe no external transistor amplifier is even needed. But it has only a gain bandwidth of 600 kHz, maybe would be good to use some additional 4051 for the high frequency data lines. Could be all controlled with a cheap Arduino nano, and a simple Python script to control it and send the programming file over serial port.

I wonder why they do all these tests. I guess they don't do much tests when they produce the ICs? So far I've used about 20 PMS150C for testing, programming little things etc. One IC was not programmable. Might be a good idea if a DIY programmer would do all the verifies at different voltage levels etc. as well.

Over the weekend I spe