Help with DIY XenoGC emulation
Posted: Tue Jun 02, 2020 7:49 pm
Hello everyone,
I have recently set about attempting to make my own XenoGC drive chip based off the released source code and translating that to a PIC18LF25K80. I have a few questions that I think this community will be able to help me answer, I'll put the questions in list format with documentation for ease when answering.
Reference Material:
(A) viewtopic.php?t=403
(B) viewtopic.php?t=439
(C) https://www.gc-forever.com/yagcd/
(1) Does the SPI port on the drive chip operate in SPI mode 3? What CLK speed should transmissions be sent? Are bytes sent lsb first?
- Probing the CLK line of the GC when powered on shows an idle state of high, narrowing the possible modes to 2 & 3. Based on the source code in reference B (in the XenoAT.c file, specifically the io function within that file) I initially thought the falling edge of the CLK line sampled data (SPI mode 2). However, after failing to get expected responses I changed my code to sample on the rising edge and the data I receive appears accurate.
- I set my clock speed to approximately 5 kHz, a post on the second page of reference A states that the per bit time frame is about 130 us. Not sure if he means the whole period or the half period, but 130 us and 260 us equates to 7.62 kHz and 3.85 kHz, respectively. At my set speed I receive good data, so I am assuming the CLK speed is not an issue.
- From the source code in reference B (in the XenoAT.c file, send8 function) it appears that bytes are shifted out lsb first to the io function. Just wanting to confirm that I am correct in that assumption.
(2) What is the memory location that I must read to determine the state of the buttons being pressed on a connected controller?
- From the source code in reference B (in the XenoAT.c file, when the read_mem function is called) the base address read appears to be 0x40D100 with a read length of 2 bytes. From a post in source A, on page 1, the response to issuing the read_mem command (which is the following sequence of bytes: 0xFF,0x00,0xD1,0x00,0x00,0x40,0x00,0x00,0x02,0x00) should be: 0x00,0x00,0xFF,0xFD. However, when I issue the command I receive: 0x00,0x00,0x5D,0x49 or sometimes: 0x00,0x00,DD,0xFF. From the source code in reference B (in the XenoAT.c file, read_mem function) I know that the first 2 bytes returned are related to any errors that might occur, with 0x00 for both bytes meaning the request was error free. I attempted to find a memory map of where various values are stored, I searched all through reference C, and read them back as a sanity check, but I cannot find complete enough documentation that is clear enough to me to do so (my opinion of reference C).
Below is a snippet of the code execution halted right after receiving the response to the read command, I have highlighted the important values:
https://imgur.com/LjUUCWi
(3) Does the required upload.bin, qcodes.bin and credits.bin need to be read out in a special way? (weird question, let me clarify)
- I am not a novice in embedded coding, but instead of including the .bin files when I compile my source code I have opted to have them stored in an array within my source code (makes more sense to me that way). To do this, I wrote a small python program that reads in the .bin files (byte at a time) and then outputs them to a new text file in the form of: {0x00,0x00,0x00,etc} for copying to my program and also outputs the total length of the array.
- After reading the controller state, which may not even be working, I begin to write the associated "upload.bin" in its array form starting at the memory location 0x40D000 (reference B, in the XenoAT.c file). In reference A, in a first page post, I am able to track the commands he recorded with my code until about the 6th write transmission:
Synchronizing CMD: {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} Response: 0xEE,0xEE
Read (0x40D100) CMD: {0xFF,0x00,0xD1,0x00,0x00,0x40,0x00,0x00,0x02,0x00} Response: 0x00,0x00,0x5D,0x49 (suppose to be 0x00,0x00,0xFF,0xFD???)
Write (0x40D000) CMD: {0xFE,0x00,0xD0,0x00,0xF7,0x40,0x10,0x00,0x02,0x00} Response: 0x00,0x00,0xF7,0x10
Write (0x40D002) CMD: {0xFE,0x00,0xD0,0x02,0xFF,0x40,0xF7,0x00,0x02,0x00} Response: 0x00,0x00,0xFF,0xF7
Write (0x40D004) CMD: {0xFE,0x00,0xD0,0x04,0xF5,0x40,0xD9,0x00,0x02,0x00} Response: 0x00,0x00,0xF5,0xD9
Write (0x40D006) CMD: {0xFE,0x00,0xD0,0x06,0xC8,0x40,0xFF,0x00,0x02,0x00} Response: 0x00,0x00,0xC8,0xFF
Write (0x40D008) CMD: {0xFE,0x00,0xD0,0x08,0xF4,0x40,0xC0,0x00,0x02,0x00} Response: 0x00,0x00,0xC4,0xC0
Write (0x40D00A) CMD: {0xFE,0x00,0xD0,0x08,0xF4,0x40,0xC0,0x00,0x02,0x00}
------*My Write CMD is: {0xFE,0x00,0xD0,0x08,0xA0,0x40,0xF4,0x00,0x02,0x00}
- Since my command packets seem to match with what an actual XenoGC would send out, I believe that the method I used to convert the upload.bin to array format might be causing the data to be inaccurate after the 10th byte in the array.
Thank you for any help, I've had fun so far attempting this emulation/hack. Ill upload my main.c for viewing and supply more info if needed.
I have recently set about attempting to make my own XenoGC drive chip based off the released source code and translating that to a PIC18LF25K80. I have a few questions that I think this community will be able to help me answer, I'll put the questions in list format with documentation for ease when answering.
Reference Material:
(A) viewtopic.php?t=403
(B) viewtopic.php?t=439
(C) https://www.gc-forever.com/yagcd/
(1) Does the SPI port on the drive chip operate in SPI mode 3? What CLK speed should transmissions be sent? Are bytes sent lsb first?
- Probing the CLK line of the GC when powered on shows an idle state of high, narrowing the possible modes to 2 & 3. Based on the source code in reference B (in the XenoAT.c file, specifically the io function within that file) I initially thought the falling edge of the CLK line sampled data (SPI mode 2). However, after failing to get expected responses I changed my code to sample on the rising edge and the data I receive appears accurate.
- I set my clock speed to approximately 5 kHz, a post on the second page of reference A states that the per bit time frame is about 130 us. Not sure if he means the whole period or the half period, but 130 us and 260 us equates to 7.62 kHz and 3.85 kHz, respectively. At my set speed I receive good data, so I am assuming the CLK speed is not an issue.
- From the source code in reference B (in the XenoAT.c file, send8 function) it appears that bytes are shifted out lsb first to the io function. Just wanting to confirm that I am correct in that assumption.
(2) What is the memory location that I must read to determine the state of the buttons being pressed on a connected controller?
- From the source code in reference B (in the XenoAT.c file, when the read_mem function is called) the base address read appears to be 0x40D100 with a read length of 2 bytes. From a post in source A, on page 1, the response to issuing the read_mem command (which is the following sequence of bytes: 0xFF,0x00,0xD1,0x00,0x00,0x40,0x00,0x00,0x02,0x00) should be: 0x00,0x00,0xFF,0xFD. However, when I issue the command I receive: 0x00,0x00,0x5D,0x49 or sometimes: 0x00,0x00,DD,0xFF. From the source code in reference B (in the XenoAT.c file, read_mem function) I know that the first 2 bytes returned are related to any errors that might occur, with 0x00 for both bytes meaning the request was error free. I attempted to find a memory map of where various values are stored, I searched all through reference C, and read them back as a sanity check, but I cannot find complete enough documentation that is clear enough to me to do so (my opinion of reference C).
Below is a snippet of the code execution halted right after receiving the response to the read command, I have highlighted the important values:
https://imgur.com/LjUUCWi
(3) Does the required upload.bin, qcodes.bin and credits.bin need to be read out in a special way? (weird question, let me clarify)
- I am not a novice in embedded coding, but instead of including the .bin files when I compile my source code I have opted to have them stored in an array within my source code (makes more sense to me that way). To do this, I wrote a small python program that reads in the .bin files (byte at a time) and then outputs them to a new text file in the form of: {0x00,0x00,0x00,etc} for copying to my program and also outputs the total length of the array.
- After reading the controller state, which may not even be working, I begin to write the associated "upload.bin" in its array form starting at the memory location 0x40D000 (reference B, in the XenoAT.c file). In reference A, in a first page post, I am able to track the commands he recorded with my code until about the 6th write transmission:
Synchronizing CMD: {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} Response: 0xEE,0xEE
Read (0x40D100) CMD: {0xFF,0x00,0xD1,0x00,0x00,0x40,0x00,0x00,0x02,0x00} Response: 0x00,0x00,0x5D,0x49 (suppose to be 0x00,0x00,0xFF,0xFD???)
Write (0x40D000) CMD: {0xFE,0x00,0xD0,0x00,0xF7,0x40,0x10,0x00,0x02,0x00} Response: 0x00,0x00,0xF7,0x10
Write (0x40D002) CMD: {0xFE,0x00,0xD0,0x02,0xFF,0x40,0xF7,0x00,0x02,0x00} Response: 0x00,0x00,0xFF,0xF7
Write (0x40D004) CMD: {0xFE,0x00,0xD0,0x04,0xF5,0x40,0xD9,0x00,0x02,0x00} Response: 0x00,0x00,0xF5,0xD9
Write (0x40D006) CMD: {0xFE,0x00,0xD0,0x06,0xC8,0x40,0xFF,0x00,0x02,0x00} Response: 0x00,0x00,0xC8,0xFF
Write (0x40D008) CMD: {0xFE,0x00,0xD0,0x08,0xF4,0x40,0xC0,0x00,0x02,0x00} Response: 0x00,0x00,0xC4,0xC0
Write (0x40D00A) CMD: {0xFE,0x00,0xD0,0x08,0xF4,0x40,0xC0,0x00,0x02,0x00}
------*My Write CMD is: {0xFE,0x00,0xD0,0x08,0xA0,0x40,0xF4,0x00,0x02,0x00}
- Since my command packets seem to match with what an actual XenoGC would send out, I believe that the method I used to convert the upload.bin to array format might be causing the data to be inaccurate after the 10th byte in the array.
Thank you for any help, I've had fun so far attempting this emulation/hack. Ill upload my main.c for viewing and supply more info if needed.