Skip to content

Commit

Permalink
support for LONG-CZ J9
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyakurdyukov authored Oct 31, 2024
1 parent e254c11 commit 133cf54
Show file tree
Hide file tree
Showing 13 changed files with 475 additions and 79 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ All feature phone LCDs I've seen are vertical, if you have a phone with a horizo
| 48 | Fontel FP100 | SC6531 | 128x64 ST7567A | all d-pad |
| 49 | Joy's S16 | SC6530C | 96x68 HX1230 | up |
| 50 | Joy's S19 | SC6531 | 128x64 ST7565R | 3 |
| 51 | Vertex M114 | SC6530C | 96x68 HX1230 | up |
| 52 | LONG-CZ J9 | SC6531E | 64x48 SSD1306 | right soft |

* Nobby 170B: use `--spi 1 --mac 0xa8` without `--rotate`
* Smart Watch DZ09: use `--spi 0 --lcd 0x80009307`, no controls - you can only watch replays, no boot key - use boot cable
Expand All @@ -115,10 +117,11 @@ All feature phone LCDs I've seen are vertical, if you have a phone with a horizo
* Texet TM-B307: use `--gpio_init`, to prevent the flashlight from turning on
* Texet TM-B316: use `--lcd 0x8083760f --rotate 1,0`
* Texet TM-B323, Texet TM-B208: use `--rotate 3,0 --keyflags 1`
* Texet TM-B323: only games on the Build engine work with this resolution, others need `--scaler 1` option
* Texet TM-B323: very rare resolution, not the best support for it
* Tokky FP10, Fontel FP100: use `--lcd 0x7567`
* Joy's S16: use `--lcd 0x1230`
* Joy's S19: use `--lcd 0x7565`
* LONG-CZ J9: use `--lcd 0x1306`

- monochrome LCDs: can't be detected, support varies across ports and LCDs, better for screens with ST7567A

Expand Down
22 changes: 21 additions & 1 deletion fpbuild/fp_layer.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ int setvideomode(int x, int y, int c, int fs) {
int h = y;
x = 320; y = 224;
if (h == 68) y = 226;
if (h == 48) y = 240;
}
if (sys_data.scaler == 1) x <<= 1, y <<= 1;
buildprintf("Setting video mode %dx%d\n", x, y);
Expand Down Expand Up @@ -559,6 +560,21 @@ DEF(void, scr_update_96x68, (uint8_t *s, void *dest)) {
#undef X
}

#if LIBC_SDIO == 0
DEF(void, scr_update_64x48, (uint8_t *s, void *dest)) {
uint8_t *d = (uint8_t*)dest, *c8 = d - 256;
unsigned x, y, h = 48;
for (; h; h--, s += 320 * 4)
for (x = 64; x; x--, s += 5) {
const uint8_t *s2 = s; uint32_t a = 0;
for (y = 5; y; y--, s2 += 320)
a += c8[s2[0]] + c8[s2[1]] +
c8[s2[2]] + c8[s2[3]] + c8[s2[4]];
*d++ = (a * 0x147b + (3 << 16)) >> 18; /* div25 */
}
}
#endif

#undef DEF
#ifdef USE_ASM
extern int scr_update_data[2];
Expand All @@ -571,7 +587,7 @@ extern int scr_update_data[2];
#endif

uint8_t *framebuffer_init(void) {
static const uint8_t pal_size[] = { 2, 4, 1, 1 };
static const uint8_t pal_size[] = { 2, 4, 1, 1, 1 };
static const struct {
void (*pal_update)(uint8_t *pal, void *dest, const uint8_t *gamma);
void (*scr_update)(uint8_t *src, void *dest);
Expand All @@ -580,6 +596,9 @@ uint8_t *framebuffer_init(void) {
{ pal_update32, scr_update_1d2 },
{ pal_update8, scr_update_128x64 },
{ pal_update8, scr_update_96x68 },
#if LIBC_SDIO == 0
{ pal_update8, scr_update_64x48 },
#endif
};
struct sys_display *disp = &sys_data.display;
int w = disp->w2, h = disp->h2;
Expand All @@ -606,6 +625,7 @@ void lcd_appinit(void) {
if (h <= 68) {
mode = 2;
if (h == 68) mode = 3;
if (h == 48) mode = 4;
} else {
if (h > w) h = w;
mode = h <= 128;
Expand Down
168 changes: 149 additions & 19 deletions fpdoom/asmcode.s
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,25 @@ CODE32_FN int_vectors
1: b 1b // undefined
1: b 1b // swi
1: b 1b // prefetch
1: b 1b // data
1: b 4f // data
1: b 1b // reserved
b 2f // irq
1: b 1b // fiq
3: .long 0
5: .long 0

2: sub lr, #4
push {r0-r4,r12,lr}
ldr lr, 3b
blx lr
ldm sp!, {r0-r4,r12,pc}^

4: sub lr, #8
push {r0-r4,r12,lr}
ldr lr, 5b
blx lr
ldm sp!, {r0-r4,r12,pc}^

.global int_vectors_end
int_vectors_end:

Expand Down Expand Up @@ -103,33 +111,155 @@ CODE32_FN clean_invalidate_dcache_range
mcr p15, #0, r0, c7, c10, #4 // drain write buffer
bx lr

CODE32_FN lcd_gpio_send_asm
CODE32_FN lcd_send_hx1230_asm
mov r12, #0x8a000000
orr r12, #(0x28 >> 4) << 7
lsl r1, #24
ldr r2, [r12]
ldr r2, [r12, #0x20 << 3]!
orr r1, #1 << 23
1: bic r2, #0x700
orr r2, r2, r0, lsl #8
bic r2, #0x700
1: orr r0, r2, r0, lsl #8
str r0, [r12]
orr r3, r0, #0x200
lsr r0, r1, #31
lsls r1, #1
str r3, [r12]
bne 1b
orr r2, #0x700
str r2, [r12]
// 1 + (4 * 2 - 2) + 2 = 9
mov r0, #2 // 1
2: subs r0, #1 // 1
bne 2b // 3/1
orr r2, #0x200
mov r0, #1 // 1
bx lr

CODE32_FN lcd_send_ssd1306_asm
mov r12, #0x8a000000
ldr r3, [r12, #0x40 << 3]
lsls r1, #25
eor r0, r3
ands r0, #1
eor r3, r0
strne r3, [r12, #0x40 << 3]
ldr r2, [r12, #0x10 << 3]!
orr r1, #1 << 24
1: bic r2, #0x1c00
orrcs r2, #0x400
str r2, [r12]
// (4 * 1 - 2) + 2 + 3 + 2 = 9
2: subs r0, #1 // 1
bne 2b // 3/1
lsr r0, r1, #31
orr r2, #0x800
lsls r1, #1
bne 1b // 3/1
b 2f // 3
2: orr r2, #0x700
str r2, [r12]
bne 1b
orr r2, #0x1c00
str r2, [r12]
bx lr

CODE32_FN lcd_refresh_hx1230_asm
push {r4-r10,lr}
add r4, r0, #96
ldr r8, =0x80808080
mov r7, #9
1: rsb r1, r7, #0xb9
and r10, r1, #8
mov r0, #0
bl lcd_send_hx1230_asm
mov r1, #0x10
mov r0, #0
bl lcd_send_hx1230_asm
mov r1, #0
mov r0, #0
bl lcd_send_hx1230_asm

lsr r10, #1
sub r7, #96 << 16
2: sub r4, #4
mov r9, r4
add r5, r4, #96 * 68
mov r6, #0x3f
lsr r6, r10
3: ldr r0, [r9], #96
ldr r1, [r5]
ldr r2, [r9], #96
ldr r3, [r5, #96]
add r0, r1
add r2, r3
bic r1, r0, r8
bic r3, r2, r8
str r1, [r5], #96
and r0, r8
str r3, [r5], #96
and r2, r8
orr r0, r2, r0, lsr #1
orrs r6, r0, r6, lsr #2
bcs 3b
lsr r6, r10
mvn r1, r6, lsr #24
mov r0, #1
bl lcd_send_hx1230_asm
mvn r1, r6, lsr #16
mov r0, #1
bl lcd_send_hx1230_asm
mvn r1, r6, lsr #8
mov r0, #1
bl lcd_send_hx1230_asm
mvn r1, r6
mov r0, #1
bl lcd_send_hx1230_asm
adds r7, #4 << 16
bmi 2b
add r4, #96 * 9
subs r7, #1
bhi 1b
pop {r4-r10,pc}

CODE32_FN lcd_refresh_ssd1306_asm
push {r4-r8,lr}
mov r4, r0
ldr r8, =0x80808080
mov r7, #6
1: rsb r1, r7, #0xb6
mov r0, #0
bl lcd_send_ssd1306_asm
mov r1, #0
mov r0, #0
bl lcd_send_ssd1306_asm
mov r1, #0x12
mov r0, #0
bl lcd_send_ssd1306_asm

sub r7, #64 << 16
2: add r5, r4, #64 * 48
mov r6, #0x3f
3: ldr r0, [r4], #64
ldr r1, [r5]
ldr r2, [r4], #64
ldr r3, [r5, #64]
add r0, r1
add r2, r3
bic r1, r0, r8
bic r3, r2, r8
str r1, [r5], #64
and r0, r8
str r3, [r5], #64
and r2, r8
orr r0, r2, r0, lsr #1
orrs r6, r0, r6, lsr #2
bcs 3b
mov r1, r6
mov r0, #1
bl lcd_send_ssd1306_asm
lsr r1, r6, #8
mov r0, #1
bl lcd_send_ssd1306_asm
lsr r1, r6, #16
mov r0, #1
bl lcd_send_ssd1306_asm
lsr r1, r6, #24
mov r0, #1
bl lcd_send_ssd1306_asm
sub r4, #64 * 8 - 4
adds r7, #4 << 16
bmi 2b
add r4, #64 * 7
subs r7, #1
bhi 1b
pop {r4-r8,pc}

CODE32_FN __gnu_thumb1_case_uqi
bic r12, lr, #1
ldrb r12, [r12, r0]
Expand Down
6 changes: 4 additions & 2 deletions fpdoom/entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,10 @@ void entry_main(char *image_addr, uint32_t image_size, uint32_t bss_size) {
if (a - 1 < 4) sys_data.spi_mode = a;
argc -= 2; argv += 2;
} else if (argc >= 2 && !strcmp(argv[0], "--lcd")) {
sys_data.lcd_id = strtol(argv[1], NULL, 0);
if (sys_data.lcd_id == 0x1230) sys_data.gpio_init = 1;
unsigned id = strtol(argv[1], NULL, 0);
sys_data.lcd_id = id;
if (id == 0x1230 || id == 0x1306)
sys_data.gpio_init = 1;
argc -= 2; argv += 2;
} else if (argc >= 2 && !strcmp(argv[0], "--mac")) {
unsigned a = strtol(argv[1], NULL, 0);
Expand Down
51 changes: 51 additions & 0 deletions fpdoom/lcd_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,50 @@ static const uint8_t cmd7C89F0_init[] = {
LCM_END
};

#if LIBC_SDIO == 0
static const uint8_t cmd1306_init[] = {
LCM_DELAY(20),
LCM_CMD(0xae, 0), // Display OFF
//LCM_CMD(0x00, 0), // Set Column Address (low)
//LCM_CMD(0x12, 0), // Set Column Address (high)
LCM_CMD(0x40, 0), // Set Start Line (0)
//LCM_CMD(0xb0, 0), // Set Page Address
LCM_CMD(0x81, 0), // Set Contrast Control
#if 0 // orig
LCM_CMD(0xff, 0), // (value)
#else
LCM_CMD(0x80, 0), // (value)
#endif
//LCM_CMD(0xa1, 0), // SEG Direction (MX=1)
//LCM_CMD(0xa7, 0), // Inverse Display (INV=1)
LCM_CMD(0xa8, 0), // Set Multiplex Ratio
LCM_CMD(0x2f, 0), // (value)
//LCM_CMD(0xc8, 0), // COM Direction (MY=1)
LCM_CMD(0xd3, 0), // Set Display Offset
LCM_CMD(0x00, 0), // (value)
LCM_CMD(0xd5, 0), // Set Display Clock
#if 0 // orig
LCM_CMD(0x80, 0), // (value)
#else // max freq
LCM_CMD(0xf0, 0), // (value)
#endif
LCM_CMD(0xd9, 0), // Set Pre-charge Period
#if 0 // orig
LCM_CMD(0x21, 0), // (value)
#else
LCM_CMD(0x11, 0), // (value)
#endif
LCM_CMD(0xda, 0), // Set COM Pins
LCM_CMD(0x12, 0), // (value)
LCM_CMD(0xdb, 0), // Set VCOMH Deselect Level
LCM_CMD(0x40, 0), // (value)
LCM_CMD(0x8d, 0), // Charge Pump Setting
LCM_CMD(0x14, 0), // Enable Charge Pump
LCM_CMD(0xaf, 0), // Display ON
LCM_END
};
#endif

// SC6530/SC6531

static const uint8_t cmd9106_chip2_init[] = {
Expand Down Expand Up @@ -1532,6 +1576,13 @@ static const lcd_config_t lcd_config1[] = {

// Sitronix ST7735S BOE
X(0x7c89f0, 128,160, 0xd0, 150,150,150,150,150,150, 0, cmd7C89F0)

#if LIBC_SDIO == 0 /* no SD card slot */
/* LONG-CZ J9 */

// Solomon Systech SSD1306
X(0x001306, 64,48, 0x1c1, 15,120,75,15,35,35, 0, cmd1306)
#endif
};

static const lcd_config_t lcd_config2[] = {
Expand Down
Loading

0 comments on commit 133cf54

Please sign in to comment.