1- // Emacs style mode select -*- C++ -*-
21//-----------------------------------------------------------------------------
32//
43// DOOM graphics renderer for OLED display on LiteX LiteOS
4+ // (not part of mc1-doom)
55//
66//-----------------------------------------------------------------------------
77
1717
1818static uint16_t s_palette [256 ] __attribute((section (".fastdata" )));
1919
20- static const uint8_t
21- oled_map_dx[OLED_WIDTH] /* __attribute((section(".fastdata"))) */ = {
22- 0 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,
23- 3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,
24- 3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3 ,4 ,3 ,3
25- };
26-
27- static const uint8_t
28- oled_map_dy[OLED_HEIGHT] /* __attribute((section(".fastdata"))) */ = {
29- 0 ,120 ,120 ,120 ,120 ,120 ,120 ,120 ,160 ,120 ,120 ,120 ,120 ,120 ,120 ,120 ,160 ,120 ,120 ,
30- 120 ,120 ,120 ,120 ,120 ,160 ,120 ,120 ,120 ,120 ,120 ,120 ,120 ,160 ,120 ,120 ,120 ,120 ,
31- 120 ,120 ,120 ,160 ,120 ,120 ,120 ,120 ,120 ,120 ,120 ,160 ,120 ,120 ,120 ,120 ,120 ,120 ,
32- 120 ,160 ,120 ,120 ,120 ,120 ,120 ,120 ,120
33- };
20+ /*
21+ 320x200 -> OLED_WIDTH x OLED_HEIGHT:
22+ framebuffer pointer increment for next pixel
23+ */
24+ static uint8_t oled_map_dx [OLED_WIDTH ] __attribute((section (".fastdata" )));
25+
26+ /*
27+ 320x200 -> OLED_WIDTH x OLED_HEIGHT:
28+ framebuffer pointer increment for next line divided by 8 (shifted >> 3)
29+ */
30+ static uint8_t oled_map_dy [OLED_HEIGHT ] __attribute((section (".fastdata" )));
31+
32+ static inline int map (int x , int in_max , int out_max ) {
33+ return x * in_max / out_max ;
34+ }
35+
36+ static inline int map_delta (int x , int in_max , int out_max ) {
37+ if (x == 0 ) {
38+ return 0 ;
39+ }
40+ return map (x , in_max , out_max ) - map (x - 1 , in_max , out_max );
41+ }
3442
3543void I_InitGraphics (void ) {
3644 // Only initialize once.
@@ -39,8 +47,15 @@ void I_InitGraphics (void) {
3947 return ;
4048 initialized = 1 ;
4149 screens [0 ] = (unsigned char * )malloc (SCREENWIDTH * SCREENHEIGHT );
42- if (screens[0 ] == NULL )
43- I_Error (" Couldn't allocate screen memory" );
50+ if (screens [0 ] == NULL )
51+ I_Error ("Couldn't allocate screen memory" );
52+ for (int x = 0 ; x < OLED_WIDTH ; ++ x ) {
53+ oled_map_dx [x ] = (uint8_t )(map_delta (x , 320 , OLED_WIDTH ));
54+ }
55+ for (int y = 0 ; y < OLED_HEIGHT ; ++ y ) {
56+ oled_map_dy [y ] = (uint8_t )((map_delta (y , 200 , OLED_HEIGHT )* 320 )>>3 );
57+ }
58+
4459 oled_init ();
4560}
4661
@@ -61,82 +76,64 @@ void I_StartTic (void) {
6176void I_UpdateNoBlit (void ) {
6277}
6378
79+
80+ //------------------------
81+
82+ #ifdef CSR_OLED_SPI_BASE
83+
84+ // Wait for SPI driver to have finished sending data
6485static inline void oled_wait (void ) {
65- #ifdef CSR_OLED_SPI_BASE
6686 while (oled_spi_status_read () != OLED_SPI_DONE );
67- #endif
6887}
6988
7089// Same as in lite_oled, but does not change CS and CMD/DAT
90+ // and does not wait for SPI to have finished sending data
7191static inline void oled_byte_raw (uint8_t b ) {
72- #ifdef CSR_OLED_SPI_BASE
7392 oled_spi_mosi_write (b );
7493 oled_spi_control_write (8 * OLED_SPI_LENGTH | OLED_SPI_START );
75- #endif
7694}
7795
7896// Same as in lite_oled, but does not change CS and CMD/DAT
97+ // and does not wait for SPI to have finished sending data
7998static inline void oled_data_uint16_raw (uint16_t RGB ) {
99+ // Unfortunately, in LiteX, the SPI driver can only send
100+ // 8 bits at a time (the shifter is only 8 bits wide)
80101 oled_byte_raw ((uint8_t )(RGB >>8 ));
81102 oled_wait ();
82103 oled_byte_raw ((uint8_t )(RGB ));
83104}
84105
106+ #endif
107+
108+ //------------------------
85109
86110void I_FinishUpdate (void ) {
87111
88112#ifdef CSR_OLED_SPI_BASE
89113 const unsigned char * src = (const unsigned char * )screens [0 ];
90- // Resolution / 4, a centered 80x50 window
91114 oled_write_window (0 ,0 ,OLED_WIDTH - 1 ,OLED_HEIGHT - 1 );
92115 const unsigned char * line_ptr = src ;
93116
94- oled_ctl_out_write (OLED_SPI_DAT);
117+ // sending DATA to the SPI
118+ oled_ctl_out_write (OLED_SPI_DAT );
119+ // chip select ON (LOW)
95120 oled_spi_cs_write (OLED_SPI_CS_LOW );
96121 for (int y = 0 ; y < OLED_HEIGHT ; ++ y ) {
97122 const unsigned char * pixel_ptr = line_ptr ;
98123 for (int x = 0 ; x < OLED_WIDTH ; ++ x ) {
99124 uint16_t pixelvalue = s_palette [* pixel_ptr ];
100- oled_data_uint16_raw (pixelvalue);
125+ // send pixel data to the SPI
126+ oled_data_uint16_raw (pixelvalue );
127+ // increment framebuffer pointer
101128 pixel_ptr += oled_map_dx [x ];
129+ // wait for SPI write dat to be finished
102130 oled_wait ();
103131 }
104132 line_ptr += (oled_map_dy [y ]<<3 );
105133 }
134+ // chip select OFF (HIGH)
106135 oled_spi_cs_write (OLED_SPI_CS_HIGH );
107136#endif
108-
109- /*
110- #ifdef CSR_OLED_SPI_BASE
111- const unsigned char* src = (const unsigned char*)screens[0];
112- // Resolution / 4, a centered 80x50 window
113- oled_write_window(8,7,87,56);
114- const unsigned char* line_ptr = src;
115-
116- oled_ctl_out_write(OLED_SPI_DAT);
117- oled_spi_cs_write(OLED_SPI_CS_LOW);
118- for(int y=0; y<200; y+=4) {
119- for(int x=0; x<320; x+=4) {
120- uint16_t pixelvalue = s_palette[line_ptr[x]];
121- oled_data_uint16_raw(pixelvalue);
122- }
123- line_ptr += 4*320;
124- }
125- oled_spi_cs_write(OLED_SPI_CS_HIGH);
126- #endif
127- */
128- /*
129- float scaleX = (float)SCREENWIDTH / OLED_WIDTH;
130- float scaleY = (float)SCREENHEIGHT / OLED_HEIGHT;
131- for (uint8_t y = 0; y < OLED_HEIGHT; ++y) {
132- int iy = (int)(y * scaleY);
133- for(uint8_t x = 0; x < OLED_WIDTH; ++x){
134- int ix = (int)(x * scaleX);
135- uint16_t pixelvalue = s_palette[src[iy*SCREENWIDTH+ix]];
136- oled_setpixel_uint16(x, y, pixelvalue);
137- }
138- }
139- */
140137}
141138
142139void I_ReadScreen (byte * scr ) {
0 commit comments