Changeset 7ba68aa in buchla-emu


Ignore:
Timestamp:
08/25/2017 07:04:14 PM (7 years ago)
Author:
Alexander Heinrich <alex.heinrich@…>
Branches:
master
Children:
43ea417
Parents:
657abdf
Message:

Basic text output for lcd

Basic text output for lcd, graphics drawing still needs to be done.

Location:
emu
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • emu/all.h

    r657abdf r7ba68aa  
    111111extern void lcd_write(uint32_t off, int32_t sz, uint32_t val);
    112112
     113extern void lcd_sdl(void);
     114
    113115extern void ser_init(void);
    114116extern void ser_quit(void);
  • emu/lcd.c

    r657abdf r7ba68aa  
    2222#define ver3(...) _ver(lcd_verbose, 2, __VA_ARGS__)
    2323
     24#define WIN_W (1520 * 2 / 3)
     25#define WIN_H (950 * 2 / 3)
     26
     27#define CON_W 86
     28#define CON_H 25
     29
     30#define CON_BGR 0x00000000
     31#define CON_BEL 0x00808080
     32#define CON_CUR 0x00e87000
     33#define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 })
     34
     35#define BEL_CYC 10000
     36
     37#define G_INIT          0x40
     38#define G_MWRITE        0x42
     39#define G_MREAD         0x43
     40#define G_SETSAD        0x44
     41#define G_CRSWR         0x46
     42#define G_CRSRD         0x47
     43#define G_CRSMRT        0x4C
     44#define G_CRSMLT        0x4D
     45#define G_CRSMUP        0x4E
     46#define G_CRSMDN        0x4F
     47#define G_ERASE         0x52
     48#define G_SLEEP         0x53
     49#define G_DSPCTL        0x58
     50#define G_HSCRL         0x5A
     51#define G_OVRLAY        0x5B
     52#define G_CGRAM         0x5C
     53#define G_CRSFRM        0x5D
     54
     55static uint8_t mem[CON_H][CON_W + 1];
     56
     57static SDL_Window *win;
     58static SDL_Renderer *ren;
     59static SDL_atomic_t frame;
     60
     61static TTF_Font *fon;
     62static int32_t fon_w, fon_h;
     63
     64static int32_t sur_w, sur_h;
     65static SDL_Surface *sur;
     66
     67static int32_t cur_x = 0, cur_y = 0;
     68static int32_t bel = 0;
     69
     70static int32_t current_op = 0x00;
     71static uint32_t cur_ad = 0;
     72static int32_t cur_ad_c = 0;
     73
    2474int32_t lcd_verbose = 0;
    2575
     76static void scroll(void)
     77{
     78        memmove(mem, mem + 1, (CON_H - 1) * (CON_W + 1));
     79        memset(mem + (CON_H - 1), ' ', CON_W);
     80}
     81
     82static void forw(void)
     83{
     84        if (cur_x < CON_W - 1) {
     85                ++cur_x;
     86                return;
     87        }
     88
     89        if (cur_y == CON_H - 1) {
     90                cur_x = 0;
     91                scroll();
     92                return;
     93        }
     94
     95        cur_x = 0;
     96        ++cur_y;
     97}
     98
     99static void back(void)
     100{
     101        if (cur_x > 0) {
     102                --cur_x;
     103                return;
     104        }
     105
     106        if (cur_y == 0) {
     107                return;
     108        }
     109
     110        cur_x = CON_W - 1;
     111        --cur_y;
     112}
     113
     114static void down(void)
     115{
     116        if (cur_y < CON_H - 1) {
     117                ++cur_y;
     118                return;
     119        }
     120
     121        scroll();
     122}
     123
     124static void mvcur(uint32_t cur_addr) {
     125        uint32_t n_cur_x = cur_addr % 85;
     126        uint32_t n_cur_y = cur_addr / 85;
     127
     128        printf("Cur x %u\n", n_cur_x);
     129        printf("Cur y %u\n", n_cur_y);
     130        if (n_cur_x < CON_W - 1) {
     131                cur_x = (int32_t) n_cur_x;
     132        }
     133        else {
     134                err("invalid x cursor pos in lcd %u:%d", n_cur_x, CON_W);
     135        }
     136
     137        if (n_cur_y < CON_H - 1) {
     138                cur_y = (int32_t) n_cur_y;
     139        }
     140        else {
     141                err("invalid y cursor pos in lcd %u:%d", n_cur_y, CON_H);
     142        }
     143}
     144
     145static void echo(uint8_t c)
     146{
     147        if (c < 32) {
     148                switch (c) {
     149                case '\r':
     150                        cur_x = 0;
     151                        break;
     152
     153                case '\n':
     154                        down();
     155                        break;
     156
     157                case '\b':
     158                        back();
     159                        break;
     160
     161                case '\a':
     162                        bel = BEL_CYC;
     163                        break;
     164
     165                case 0:
     166                        mem[cur_y][cur_x] = ' ';
     167                        forw();
     168                        break;
     169
     170                case 28:
     171                        // TODO
     172                        echo('^');
     173                        echo((uint8_t)(c + '@'));
     174                        break;
     175
     176                default:
     177                        echo('^');
     178                        echo((uint8_t)(c + '@'));
     179                        ver2("lcd default case echo %u", c);
     180                        return;
     181                }
     182        }
     183        else {
     184                mem[cur_y][cur_x] = c;
     185                forw();
     186        }
     187
     188        SDL_AtomicAdd(&frame, 1);
     189}
     190
     191void lcd_sdl(void)
     192{
     193        ver3("lcd_sdl()");
     194
     195        static int32_t last = 0;
     196        int32_t now = SDL_AtomicGet(&frame);
     197
     198        if (last == now) {
     199                ver3("no update");
     200                return;
     201        }
     202
     203        last = now;
     204
     205        if (SDL_FillRect(sur, NULL, bel == 0 ? CON_BGR : CON_BEL) < 0) {
     206                fail("SDL_FillRect() failed: %s", SDL_GetError());
     207        }
     208
     209        if (SDL_FillRect(sur, &(SDL_Rect){
     210                .x = cur_x * fon_w,
     211                .y = cur_y * fon_h,
     212                .w = fon_w,
     213                .h = fon_h
     214        }, CON_CUR) < 0) {
     215                fail("SDL_FillRect() failed: %s", SDL_GetError());
     216        }
     217
     218        for (int32_t y = 0; y < CON_H; ++y) {
     219                char line[CON_W + 1];
     220
     221                if (SDL_LockMutex(cpu_mutex) < 0) {
     222                        fail("SDL_LockMutex() failed: %s", SDL_GetError());
     223                }
     224
     225                memcpy(line, mem[y], CON_W + 1);
     226
     227                if (SDL_UnlockMutex(cpu_mutex) < 0) {
     228                        fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
     229                }
     230
     231                SDL_Surface *lin = TTF_RenderText_Blended(fon, line, CON_FGR);
     232
     233                if (lin == NULL) {
     234                        fail("TTF_RenderText_Blended() failed: %s", TTF_GetError());
     235                }
     236
     237                if (SDL_BlitSurface(lin, NULL, sur, &(SDL_Rect){
     238                        .x = 0,
     239                        .y = y * fon_h,
     240                        .w = CON_W * fon_w,
     241                        .h = fon_h
     242                })) {
     243                        fail("SDL_BlitSurface() failed: %s", SDL_GetError());
     244                }
     245
     246                SDL_FreeSurface(lin);
     247        }
     248
     249        SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, sur);
     250
     251        if (tex == NULL) {
     252                fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
     253        }
     254
     255        if (SDL_RenderCopy(ren, tex, NULL, NULL) < 0) {
     256                fail("SDL_RenderCopy() failed: %s", SDL_GetError());
     257        }
     258
     259        SDL_DestroyTexture(tex);
     260        SDL_RenderPresent(ren);
     261}
     262
     263
    26264void lcd_init(void)
    27265{
    28266        ver("lcd init");
     267
     268        win = SDL_CreateWindow("Front LCD", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
     269                        WIN_W, WIN_H, 0);
     270
     271        if (win == NULL) {
     272                fail("SDL_CreateWindow() failed: %s", SDL_GetError());
     273        }
     274
     275        ren = SDL_CreateRenderer(win, -1, 0);
     276
     277        if (ren == NULL) {
     278                fail("SDL_CreateRenderer() failed: %s", SDL_GetError());
     279        }
     280
     281        SDL_AtomicSet(&frame, 1);
     282
     283        SDL_RWops *ops = SDL_RWFromFile(font, "rb");
     284
     285        if (ops == NULL) {
     286                fail("error while opening font file %s: %s", font, SDL_GetError());
     287        }
     288
     289        fon = TTF_OpenFontRW(ops, 1, 32);
     290
     291        if (fon == NULL) {
     292                fail("error while loading font file %s: %s", font, TTF_GetError());
     293        }
     294
     295        fon_h = TTF_FontLineSkip(fon);
     296
     297        if (TTF_GlyphMetrics(fon, 'X', NULL, NULL, NULL, NULL, &fon_w) < 0) {
     298                fail("error while measuring font width: %s", TTF_GetError());
     299        }
     300
     301        sur_w = CON_W * fon_w;
     302        sur_h = CON_H * fon_h;
     303
     304        sur = SDL_CreateRGBSurface(0, sur_w, sur_h, 32, 0, 0, 0, 0);
     305
     306        if (sur == NULL) {
     307                fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
     308        }
     309
     310        for (int32_t y = 0; y < CON_H; ++y) {
     311                for (int32_t x = 0; x < CON_W; ++x) {
     312                        mem[y][x] = ' ';
     313                }
     314
     315                mem[y][CON_W] = 0;
     316        }
     317
    29318}
    30319
     
    32321{
    33322        ver("lcd quit");
     323
     324        SDL_FreeSurface(sur);
     325        TTF_CloseFont(fon);
     326
     327        SDL_DestroyRenderer(ren);
     328        SDL_DestroyWindow(win);
    34329}
    35330
     
    43338{
    44339        ver2("lcd rd %u:%d", off, sz * 8);
    45         return 0;
     340
     341        uint32_t rv;
     342
     343        switch (current_op) {
     344                case G_MREAD:
     345                        printf("current op: %d\n", current_op);
     346                        rv = mem[cur_y][cur_x];
     347                        break;
     348                default:
     349                        rv = 0x00;
     350                        break;
     351        }
     352        return rv;
    46353}
    47354
     
    49356{
    50357        ver2("lcd wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
    51 }
     358
     359        if (off == 0) {
     360                switch (current_op) {
     361                        case G_MWRITE:
     362                                        echo((uint8_t)val);
     363                                break;
     364                        case G_CRSWR:
     365                                if (cur_ad_c == 0) {
     366                                        cur_ad = val;
     367                                        cur_ad_c++;
     368                                } else if (cur_ad_c == 1) {
     369                                        cur_ad = cur_ad | (val << 8);
     370                                        mvcur(cur_ad);
     371                                        cur_ad_c = 0;
     372                                }
     373                                break;
     374                        default:
     375                                break;
     376                }
     377        }
     378        else {
     379                switch (val) {
     380                        case G_MWRITE:
     381                                current_op = G_MWRITE;
     382                                break;
     383                        case G_CRSMRT:
     384                                forw();
     385                                break;
     386                        case G_CRSWR:
     387                                current_op = G_CRSWR;
     388                                break;
     389                        case G_MREAD:
     390                                current_op = G_MREAD;
     391                                break;
     392                        default:
     393                                current_op = 0x00;
     394                                break;
     395                }
     396        }
     397}
  • emu/sdl.c

    r657abdf r7ba68aa  
    2727
    2828static sdl_func_t sdl_funcs[] = {
    29         ser_sdl, vid_sdl
     29        lcd_sdl, ser_sdl, vid_sdl
    3030};
    3131
Note: See TracChangeset for help on using the changeset viewer.