From: 0x19 Date: Sun, 22 Feb 2026 18:17:43 +0000 (+0100) Subject: port: snom360 X-Git-Url: https://git.0x19.co/screenshots/static/gitweb.css?a=commitdiff_plain;h=7b05702863917813b81e12e7b47a504b170dc126;p=doomgeneric-snom360 port: snom360 Add snom360 port, including some small fixes for the endianness check, as well as the platform driver. --- diff --git a/doomgeneric/Makefile.snom360 b/doomgeneric/Makefile.snom360 new file mode 100644 index 0000000..7dc3b50 --- /dev/null +++ b/doomgeneric/Makefile.snom360 @@ -0,0 +1,58 @@ +################################################################ +# +# $Id:$ +# +# $Log:$ +# + +ifeq ($(V),1) + VB='' +else + VB=@ +endif + +UPX=upx +CC=mips-linux-gcc-3.3.6 + +CFLAGS+=-ggdb3 -Os -std=c99 +CFLAGS+=-DSNOM360 +LDFLAGS+=-Wl,--gc-sections +CFLAGS+=-Wall -DNORMALUNIX -DLINUX -DSNDSERV -D_DEFAULT_SOURCE -static # -DUSEASM +LIBS+=-lm -lc + +# subdirectory for objects +OBJDIR=build +OUTPUT=doomgeneric + +SRC_DOOM = dummy.o am_map.o doomdef.o doomstat.o dstrings.o d_event.o d_items.o d_iwad.o d_loop.o d_main.o d_mode.o d_net.o f_finale.o f_wipe.o g_game.o hu_lib.o hu_stuff.o info.o i_cdmus.o i_endoom.o i_joystick.o i_scale.o i_sound.o i_system.o i_timer.o memio.o m_argv.o m_bbox.o m_cheat.o m_config.o m_controls.o m_fixed.o m_menu.o m_misc.o m_random.o p_ceilng.o p_doors.o p_enemy.o p_floor.o p_inter.o p_lights.o p_map.o p_maputl.o p_mobj.o p_plats.o p_pspr.o p_saveg.o p_setup.o p_sight.o p_spec.o p_switch.o p_telept.o p_tick.o p_user.o r_bsp.o r_data.o r_draw.o r_main.o r_plane.o r_segs.o r_sky.o r_things.o sha1.o sounds.o statdump.o st_lib.o st_stuff.o s_sound.o tables.o v_video.o wi_stuff.o w_checksum.o w_file.o w_main.o w_wad.o z_zone.o w_file_stdc.o i_input.o i_video.o doomgeneric.o doomgeneric_snom360.o snom360.o +OBJS += $(addprefix $(OBJDIR)/, $(SRC_DOOM)) + +all: $(OUTPUT) + +clean: + rm -rf $(OBJDIR) + rm -f $(OUTPUT) + rm -f $(OUTPUT).gdb + rm -f $(OUTPUT).map + +$(OUTPUT): $(OBJS) + @echo [Linking $@] + $(VB)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) \ + -o $(OUTPUT) $(LIBS) -Wl,-Map,$(OUTPUT).map + @echo [Size] + -$(CROSS_COMPILE)size $(OUTPUT) + +$(OBJS): | $(OBJDIR) + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/%.o: %.c + @echo [Compiling $<] + $(VB)$(CC) $(CFLAGS) -c $< -o $@ + +print: + @echo OBJS: $(OBJS) + +compress: $(OUTPUT) + $(UPX) -9 $(OUTPUT) diff --git a/doomgeneric/doomgeneric_snom360.c b/doomgeneric/doomgeneric_snom360.c new file mode 100644 index 0000000..5d962ee --- /dev/null +++ b/doomgeneric/doomgeneric_snom360.c @@ -0,0 +1,199 @@ +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include + +#define IMG_WIDTH DISPLAY_COLS +#define IMG_HEIGHT (DISPLAY_ROWS * 8) +#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT) + +#define KEYQUEUE_SIZE 16 + +#include "doomkeys.h" +#include "doomgeneric.h" + +#include "snom360.h" + +static struct timeval start; +static int contrast = 60; + +static uint8_t greyscale[IMG_SIZE]; +static uint8_t buf[DISPLAY_SIZE]; + +static unsigned short s_KeyQueue[KEYQUEUE_SIZE]; +static unsigned int s_KeyQueueWriteIndex = 0; +static unsigned int s_KeyQueueReadIndex = 0; + +const int snom_led_map[] = { + [1] = SNOM_LED_ONE, + [2] = SNOM_LED_TWO, + [3] = SNOM_LED_THREE, + [4] = SNOM_LED_FOUR, + [5] = SNOM_LED_FIVE, + [6] = SNOM_LED_SIX, + [7] = SNOM_LED_SEVEN, + [8] = SNOM_LED_EIGHT, + [9] = SNOM_LED_NINE, + [10] = SNOM_LED_TEN, + [11] = SNOM_LED_ELEVEN, + [12] = SNOM_LED_TWELVE +}; + +static unsigned char +convertToDoomKey(SnomKey key) +{ + switch(key) { + case SNOM_KEY_QUICK_ONE: + return KEY_ENTER; + case SNOM_KEY_QUICK_TWO: + return KEY_ESCAPE; + case SNOM_KEY_LEFT: + return KEY_LEFTARROW; + case SNOM_KEY_RIGHT: + return KEY_RIGHTARROW; + case SNOM_KEY_UP: + return KEY_UPARROW; + case SNOM_KEY_DOWN: + return KEY_DOWNARROW; + case SNOM_KEY_ACCEPT: + return KEY_FIRE; + case SNOM_KEY_CANCEL: + return KEY_USE; + default: + break; + } + return 0; +} + +static void +addKeyToQueue(SnomKey keyCode) +{ + s_KeyQueue[s_KeyQueueWriteIndex] = keyCode; + s_KeyQueueWriteIndex++; + s_KeyQueueWriteIndex %= KEYQUEUE_SIZE; +} + +void +DG_Init() +{ + snom360_setup(); + snom360_set_led(SNOM_LED_BACKLIGHT, 1); +} + +void +DG_DrawFrame() +{ + SnomKey keyCode = snom360_keyboard_read(); + if (keyCode != -1) addKeyToQueue(keyCode); + + for (int y = 0; y < IMG_HEIGHT; y++) { + for (int x = 0; x < IMG_WIDTH; x++) { + // Sample from source (simple nearest neighbor) + int src_x = (x * 640) / IMG_WIDTH; + int src_y = (y * 400) / (IMG_HEIGHT); + + uint32_t p1 = DG_ScreenBuffer[src_y * 640 + src_x]; + uint32_t p2 = DG_ScreenBuffer[src_y * 640 + src_x + 1]; + uint32_t p3 = DG_ScreenBuffer[(src_y + 1) * 640 + src_x]; + uint32_t p4 = DG_ScreenBuffer[(src_y + 1) * 640 + src_x + 1]; + + // Average the RGB components + unsigned char r = (((p1>>16)&0xFF) + ((p2>>16)&0xFF) + ((p3>>16)&0xFF) + ((p4>>16)&0xFF)) >> 2; + unsigned char g = (((p1>>8)&0xFF) + ((p2>>8)&0xFF) + ((p3>>8)&0xFF) + ((p4>>8)&0xFF)) >> 2; + unsigned char b = ((p1&0xFF) + (p2&0xFF) + (p3&0xFF) + (p4&0xFF)) >> 2; + + // Convert to grayscale + unsigned char gray = (r * 76 + g * 150 + b * 29) >> 8; + + greyscale[y * IMG_WIDTH + x] = gray > contrast; + } + } + + for (int i = 0; i < DISPLAY_ROWS; ++i) { + for (int j = 0; j < DISPLAY_COLS; ++j) { + int pb = i*DISPLAY_COLS + j; + int pr = (DISPLAY_ROWS-1-i)*DISPLAY_COLS*8 + j; + int o = DISPLAY_COLS; + buf[pb] = greyscale[pr+o*0] << 7 + | greyscale[pr+o*1] << 6 + | greyscale[pr+o*2] << 5 + | greyscale[pr+o*3] << 4 + | greyscale[pr+o*4] << 3 + | greyscale[pr+o*5] << 2 + | greyscale[pr+o*6] << 1 + | greyscale[pr+o*7] << 0; + } + } + + snom360_display_draw(buf); +} + +void +DG_SleepMs(uint32_t ms) +{ + usleep(ms * 1000); +} + +uint32_t +DG_GetTicksMs() +{ + struct timeval cur; + long seconds, usec; + + gettimeofday(&cur, NULL); + seconds = cur.tv_sec - start.tv_sec; + usec = cur.tv_usec - start.tv_usec; + + return (seconds * 1000) + (usec / 1000); +} + +int +DG_GetKey(int* pressed, unsigned char* key) +{ + if (s_KeyQueueReadIndex == s_KeyQueueWriteIndex) { + //key queue is empty + + return 0; + } + else { + unsigned short keyCode = s_KeyQueue[s_KeyQueueReadIndex]; + s_KeyQueueReadIndex++; + s_KeyQueueReadIndex %= KEYQUEUE_SIZE; + + *pressed = SNOM_KEY_PRESSED(keyCode); + *key = convertToDoomKey(SNOM_KEY_CODE(keyCode)); + + return 1; + } +} + +void +DG_SetWindowTitle(const char * title) +{ +} + +int main(int argc, char **argv) +{ + int opt = getopt(argc, argv, ":c:"); + + if (opt == 'c') { + contrast = atoi(optarg); + } + + gettimeofday(&start, NULL); + // invalid arguments for doom are apparently ignored, so we can just pass everythin along unmodified + doomgeneric_Create(argc, argv); + + while(true) { + doomgeneric_Tick(); + } + + snom360_close(); + + return 0; +} + diff --git a/doomgeneric/i_swap.h b/doomgeneric/i_swap.h index fa45d4c..405ce6e 100644 --- a/doomgeneric/i_swap.h +++ b/doomgeneric/i_swap.h @@ -31,6 +31,22 @@ #else // __DJGPP__ +#ifdef SNOM360 + +#define SYS_BIG_ENDIAN + +static inline unsigned short swapLE16(unsigned short val) { + return ((val << 8) | (val >> 8)); +} + +static inline unsigned long swapLE32(unsigned long val) { + return ((val << 24) | ((val << 8) & 0x00FF0000) | ((val >> 8) & 0x0000FF00) | (val >> 24)); +} + +#define SHORT(x) ((signed short) swapLE16(x)) +#define LONG(x) ((signed int) swapLE32(x)) + +#else // SNOM360 #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) #define SYS_LITTLE_ENDIAN @@ -65,6 +81,7 @@ static inline unsigned long swapLE32(unsigned long val) { #define doom_wtohs(x) (short int)(x) #endif +#endif // SNOM360 #endif // __DJGPP__ diff --git a/doomgeneric/snom360.c b/doomgeneric/snom360.c new file mode 100644 index 0000000..601d9ba --- /dev/null +++ b/doomgeneric/snom360.c @@ -0,0 +1,249 @@ +#include "snom360.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct inca_port_ioctl_parm { + int port; + int pin; + int value; +}; + +#define INCA_PORT_IOC_MAGIC 0xbf +#define INCA_PORT_IOCDIR _IOW(INCA_PORT_IOC_MAGIC,4,struct inca_port_ioctl_parm) +#define INCA_PORT_IOCOUTPUT _IOW(INCA_PORT_IOC_MAGIC,5,struct inca_port_ioctl_parm) +#define INCA_PORT_IOCINPUT _IOWR(INCA_PORT_IOC_MAGIC,6,struct inca_port_ioctl_parm) +#define INCA_PORT_DISPCMD _IOWR(INCA_PORT_IOC_MAGIC,7,struct inca_port_ioctl_parm) +#define INCA_PORT_DISPDATA _IOWR(INCA_PORT_IOC_MAGIC,8,struct inca_port_ioctl_parm) + +static int inca_fd = -1; +static struct inca_port_ioctl_parm parm; +static int leds[16]; + +int +inca_display_write_serial(int cmd, int value) +{ + parm.port = 2; + parm.pin = 0; + parm.value = value; + + int ret; + + if (cmd) + ret = ioctl(inca_fd, INCA_PORT_DISPCMD, &parm); + else + ret = ioctl(inca_fd, INCA_PORT_DISPDATA, &parm); + + for (int i = 0; i < 1000; ++i) + __asm("nop"); + + return ret; +} + +int +inca_port_dir(int port, int pin, int value) +{ + parm.port = port; + parm.pin = pin; + parm.value = value; + + return ioctl(inca_fd, INCA_PORT_IOCDIR, &parm); +} + +int +inca_port_write(int port, int pin, int value) +{ + parm.port = port; + parm.pin = pin; + parm.value = value; + + return ioctl(inca_fd, INCA_PORT_IOCOUTPUT, &parm); +} + +int +inca_port_read(int port, int pin) +{ + parm.port = port; + parm.pin = pin; + parm.value = 0; + int res = ioctl(inca_fd, INCA_PORT_IOCINPUT, &parm); + + if (res == 0) + return parm.value; + else + return -1; +} + +int +inca_port_read_wait(int port, int pin, int value) +{ + for (int i = 0; i < 5000; ++i) { + if (inca_port_read(2, 0xb) == value) + return 1; + } + return 0; +} + +int +inca_port_write_bit(int bit) +{ + inca_port_dir(2, 10, 1); + + if (bit) inca_port_write(2, 10, 1); + else inca_port_write(2, 10, 0); + + inca_port_write(2, 6, 0); + if (inca_port_read_wait(2, 0xb, 0) == 0) goto finish; + inca_port_dir(2, 10, 0); + inca_port_write(2, 6, 1); + if (inca_port_read_wait(2, 0xb, 1) != 0) return 1; + +finish: + inca_port_dir(2, 10, 0); + return 0; +} + +void +inca_port_setup() +{ + inca_port_dir(2, 7, 1); + inca_port_dir(2, 6, 1); + inca_port_dir(2, 0xb, 0); + inca_port_dir(2, 10, 0); + inca_port_write(2, 6, 1); + inca_port_write(2, 7, 0); +} + +void +inca_port_finish() +{ + inca_port_write(2, 6, 1); + inca_port_write(2, 7, 1); + inca_port_dir(2, 0xb, 1); + inca_port_dir(2, 10, 1); +} + +void +snom360_display_setup() +{ + inca_display_write_serial(1, 0xae); + inca_display_write_serial(1, 0xa0); + inca_display_write_serial(1, 0xc0); + inca_display_write_serial(1, 0x23); + inca_display_write_serial(1, 0x81); + inca_display_write_serial(1, 0x30); + inca_display_write_serial(1, 0xa3); + inca_display_write_serial(1, 0x2f); + inca_display_write_serial(1, 0xaf); + inca_display_write_serial(1, 0xa2); +} + +void +snom360_display_draw(unsigned char *buf) +{ + for (int i = DISPLAY_ROWS - 1; i >= 0; --i) { + inca_display_write_serial(1, i | 0xb0); + inca_display_write_serial(1, 0); + inca_display_write_serial(1, 0x10); + + for (int j = 0; j < DISPLAY_COLS; ++j) + inca_display_write_serial(0, buf[i*DISPLAY_COLS + j]); + } +} + +void +snom360_leds_write() +{ + inca_port_setup(); + if (inca_port_write_bit(0) == 0) { + goto finish; + } + + for (int i = 0; i < 16; ++i) { + if (inca_port_write_bit(leds[i]) == 0) + goto finish; + } + +finish: + inca_port_finish(); +} + +void +snom360_set_led(SnomLed led, int value) +{ + leds[led] = (value != 0); + snom360_leds_write(); +} + +int +snom360_keyboard_poll(int *res) +{ + inca_port_write(2, 6, 0); + if (inca_port_read_wait(2, 0xb, 0) == 0) + return 0; + *res = inca_port_read(2, 10); + inca_port_write(2, 6, 1); + if (inca_port_read_wait(2, 0xb, 1) == 0) + return 0; + return 1; +} + +int +snom360_keyboard_read() +{ + inca_port_setup(); + + if (inca_port_write_bit(1) == 0) + goto finish; + + int res = 0, code = -1; + if (snom360_keyboard_poll(&res) == 0 || res == 0) goto finish; + + code = 0; + for (int i = 0; i < 8; ++i) { + if (snom360_keyboard_poll(&res) == 0) goto finish; + code = code << 1; + if (res) + code |= 1; + } + +finish: + inca_port_finish(); + return code; +} + +void +snom360_setup() +{ + if (inca_fd != -1) { + fprintf(stderr, "INCA Port already opened!"); + exit(EXIT_FAILURE); + } + + if ((inca_fd = open("/dev/inca-port", O_RDWR)) < 0) { + fprintf(stderr, "Couldn't open /dev/inca-port: %s.\n", strerror(errno)); + exit(1); + } + + parm.port = 2; + parm.pin = 0; + parm.value = 0; + + leds[SNOM_LED_BACKLIGHT] = 0; + memset(&leds[1], 1, sizeof(int) * 15); + snom360_leds_write(); + snom360_display_setup(); +} + +void +snom360_close() +{ + close(inca_fd); +} diff --git a/doomgeneric/snom360.h b/doomgeneric/snom360.h new file mode 100644 index 0000000..c93ce80 --- /dev/null +++ b/doomgeneric/snom360.h @@ -0,0 +1,87 @@ +#pragma once + +#define DISPLAY_COLS 132 +#define DISPLAY_ROWS 8 +#define DISPLAY_SIZE (DISPLAY_COLS * DISPLAY_ROWS) + +typedef enum { + SNOM_KEY_HASH = 35, + SNOM_KEY_STAR = 42, + SNOM_KEY_ZERO = 48, + SNOM_KEY_ONE = 49, + SNOM_KEY_TWO = 50, + SNOM_KEY_THREE = 51, + SNOM_KEY_FOUR = 52, + SNOM_KEY_FIVE = 53, + SNOM_KEY_SIX = 54, + SNOM_KEY_SEVEN = 55, + SNOM_KEY_EIGHT = 56, + SNOM_KEY_NINE = 57, + SNOM_KEY_TRANSFER = 65, + SNOM_KEY_HOLD = 66, + SNOM_KEY_DND = 67, + SNOM_KEY_DIAL_ONE = 74, + SNOM_KEY_DIAL_TWO = 68, + SNOM_KEY_DIAL_THREE = 75, + SNOM_KEY_DIAL_FOUR = 69, + SNOM_KEY_DIAL_FIVE = 76, + SNOM_KEY_DIAL_SIX = 70, + SNOM_KEY_DIAL_SEVEN = 77, + SNOM_KEY_DIAL_EIGHT = 71, + SNOM_KEY_DIAL_NINE = 78, + SNOM_KEY_DIAL_TEN = 72, + SNOM_KEY_DIAL_ELEVEN = 79, + SNOM_KEY_DIAL_TWELVE = 73, + SNOM_KEY_QUICK_ONE = 97, + SNOM_KEY_QUICK_TWO = 98, + SNOM_KEY_QUICK_THREE = 99, + SNOM_KEY_QUICK_FOUR = 100, + SNOM_KEY_VOL_DOWN = 101, + SNOM_KEY_VOL_UP = 102, + SNOM_KEY_CANCEL = 103, + SNOM_KEY_ACCEPT = 104, + SNOM_KEY_LEFT = 105, + SNOM_KEY_RIGHT = 106, + SNOM_KEY_UP = 107, + SNOM_KEY_DOWN = 108, + SNOM_KEY_RECORD = 109, + SNOM_KEY_RETRIEVE = 110, + SNOM_KEY_MUTE = 111, + SNOM_KEY_SPEAKER = 112, + SNOM_KEY_HEADSET = 113, + SNOM_KEY_REDIAL = 114, + SNOM_KEY_SETTINGS = 115, + SNOM_KEY_DIRECTORY = 116, + SNOM_KEY_HELP = 117, + SNOM_KEY_MENU = 118, + SNOM_KEY_SNOM = 119, + SNOM_KEY_CONFERENCE = 120, +} SnomKey; + +typedef enum { + SNOM_LED_BACKLIGHT = 0, + SNOM_LED_MESSAGE = 6, + SNOM_LED_ONE = 13, + SNOM_LED_TWO = 15, + SNOM_LED_THREE = 9, + SNOM_LED_FOUR = 11, + SNOM_LED_FIVE = 5, + SNOM_LED_SIX = 7, + SNOM_LED_SEVEN = 1, + SNOM_LED_EIGHT = 4, + SNOM_LED_NINE = 12, + SNOM_LED_TEN = 14, + SNOM_LED_ELEVEN = 8, + SNOM_LED_TWELVE = 10 +} SnomLed; + +#define SNOM_KEY_PRESSED(x) (x & 0x80) +#define SNOM_KEY_RELEASED(x) !(x & 0x80) +#define SNOM_KEY_CODE(x) (x & 0x7f) + +void snom360_setup(); +void snom360_close(); + +void snom360_display_draw(unsigned char *buf); +void snom360_set_led(SnomLed led, int value); +int snom360_keyboard_read();