-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
processClocks() #3
Comments
I believe that with the following block of code I borrowed from the client and server, I could achieve it, although there are some Arduino assembly instructions that are not in ESP32. unsigned char picturedata[16*14*8*8]; // max( 16*8*14*8, 16*14*16 ) sensor pixels , tile bytes
void UpdateMatrixRegisters(int dithering)
{
//const unsigned char matrix[] = // high light
//{
// 0x89, 0x92, 0xA2, 0x8F, 0x9E, 0xC6, 0x8A, 0x95, 0xAB, 0x91, 0xA1, 0xCF,
// 0x8D, 0x9A, 0xBA, 0x8B, 0x96, 0xAE, 0x8F, 0x9D, 0xC3, 0x8C, 0x99, 0xB7,
// 0x8A, 0x94, 0xA8, 0x90, 0xA0, 0xCC, 0x89, 0x93, 0xA5, 0x90, 0x9F, 0xC9,
// 0x8E, 0x9C, 0xC0, 0x8C, 0x98, 0xB4, 0x8E, 0x9B, 0xBD, 0x8B, 0x97, 0xB1
//};
const unsigned char matrix[48] = // low light
{
0x8C, 0x98, 0xAC, 0x95, 0xA7, 0xDB, 0x8E, 0x9B, 0xB7, 0x97, 0xAA, 0xE7,
0x92, 0xA2, 0xCB, 0x8F, 0x9D, 0xBB, 0x94, 0xA5, 0xD7, 0x91, 0xA0, 0xC7,
0x8D, 0x9A, 0xB3, 0x96, 0xA9, 0xE3, 0x8C, 0x99, 0xAF, 0x95, 0xA8, 0xDF,
0x93, 0xA4, 0xD3, 0x90, 0x9F, 0xC3, 0x92, 0xA3, 0xCF, 0x8F, 0x9E, 0xBF
};
int i;
for(i = 0; i < 48; i++)
{
if(dithering)
{
writeCartByte(0xA006+i,matrix[i]);
}
else
{
switch(i%3)
{
case 0: writeCartByte(0xA006+i,c1); break;
case 1: writeCartByte(0xA006+i,c2); break;
case 2: writeCartByte(0xA006+i,c3); break;
}
//writeCartByte(0xA006+i,matrix[i%3]);
}
}
}
void processClocks(void)
{
setAddress(0xA000);
setReadMode(0xA000 < 0x8000);
asm volatile (
".equ PORTB,0x05 \n"
".equ PIND,0x09 \n"
"cli \n" // Disable interrupts
"L_%=: \n"
"sbi PORTB,5 \n" // 2 Cycles | PORTB.5 = PHI pin = PIN 13
"nop \n" // 1 Cycle
"nop \n"
"nop \n"
"nop \n"
"nop \n"
"nop \n"
"cbi PORTB,5 \n" // 2 Cycles
//"nop \n" // Comment 1 nop: 16 MHz / 15 = 1066667 Hz (closer to 1048576 Hz than 16 MHz / 16 = 1000000 Hz)
"nop \n"
"nop \n"
"sbic PIND,2 \n" // 1 Cycle if set | Skip next instruction if bit cleared.
"rjmp L_%= \n" // 2 Cycles | PIND.2 = data[0] = PIN 2
"sei \n" // Enable interrupts
::);
setWaitMode();
}
//TakePictureAndTransfer(0x03,0xE4,0,0x07,0xBF,1,0); //Base
void TakePictureAndTransfer(u8 trigger, u8 unk1, u16 exposure_time, u8 unk2, u8 unk3,
int dithering, int thumbnail)
{
// "Taking picture..."
//ramEnable();
writeCartByte(0x0000,0x0A)
// setRegisterMode(); -> SerialWriteData("Z.",2); //set register mode
writeCartByte(0x4000,0x10);
writeCartByte(0xA000,0x00);
writeCartByte(0xA001,unk1);
writeCartByte(0xA002,(exposure_time>>8)&0xFF);
writeCartByte(0xA003,exposure_time&0xFF);
writeCartByte(0xA004,unk2);
writeCartByte(0xA005,unk3);
UpdateMatrixRegisters(dithering);
// setRamModeBank0(); //set ram mode (bank 0)
writeCartByte(0x4000,0);
// Reading Picture (trigger&0xFF)
// ### takePicture
writeCartByte(0x0000,0x0A); // Enable RAM
writeCartByte(0x4000,0x10); // Set register mode
writeCartByte(0xA000,trigger); // Trigger
processClocks(); // Process <- TODO
writeCartByte(0x4000,0x00); // Set RAM mode, bank 0
unsigned int addr = 0xA100;
unsigned int _size = 16 * 14 * 16;
// ## setReadMode(0xA100 < 0x8000);
int i;
for(i = 0; i < 8; i++)
pinMode(data_pins[i], INPUT);
digitalWrite(nwr_pin, HIGH);
digitalWrite(nrd_pin, LOW);
digitalWrite(ncs_pin, LOW);
// ### readPicture
int i;
while(_size--)
{
setAddress(addr++);
unsigned char value = getData();
// Serial.write(value);
picturedata[i] = value;
i++;
}
// setWaitMode();
digitalWrite(ncs_pin, HIGH);
digitalWrite(nwr_pin, HIGH);
digitalWrite(nrd_pin, HIGH);
int i;
for(i = 0; i < 8; i++)
pinMode(data_pins[i], INPUT);
// ramDisable();
writeCartByte(0x0000,0x00)
// ConvertTilesToBitmap();
}
TakePictureAndTransfer(0x03,0xE4,0,0x07,0xBF,1,0); //Base |
The problem is that That function tries to get as close as possible to the regular speed of the clock of the GB. Basically, after you write the registers to initialte the capture, you need the camera to do its job in the same time it would take in a regular GB. So you send a bunch of pulses at the speed that it would see on a regular GB, more or less. I used a multimeter to check that the frequency of the pulse was about the one that I wanted, and left it as assembly with interrupts disabled to make sure that nothing would disturb the process. You will need to find an equivalent way of doing that in your CPU. |
I assume that this question has been answered, so I'm closing this issue. Feel free to reopen it if that's not the case. |
Hello, I believe I've arrived a bit late to the project, I hope you're still around. I'm working on a project with Flipper Zero and an ESP32-S2, which has enough pins to read a Game Boy cartridge.
I've successfully managed to read the images stored in the cartridge's RAM and display them on the Flipper's 128x64 screen.
Now, I wanted to capture photos from the FZ or maybe even do a live video with the GAME BOY Camera, but half of the time, I'm not sure what I'm doing, and I get lost in many parts.
Could you please provide a detailed explanation of what the processClocks method does?
gbcam-rev-engineer/gbcam_arduino_server/gbcam_arduino_server.ino
Lines 185 to 215 in edb26ed
Or, if it's possible, could it be written in Arduino code instead of assembly, like in the following?
I hope you can assist me; I believe I'm very close to achieving it 🙏 ... or maybe quite far, haha. I say "quite far" because the CPU frequency of the ESP32 is much higher than that of an Arduino (240MHz), and I'm not sure if it will work 🤔.
The text was updated successfully, but these errors were encountered: