it works!

Dependencies:   SDFileSystem2 mbed

Fork of manworm_tv_raster by Bayley Wang

main.cpp

Committer:
bwang
Date:
2018-10-04
Revision:
16:1f728d08b3a7
Parent:
14:5ee7843f2805

File content as of revision 16:1f728d08b3a7:

#include "mbed.h"
#include <math.h>
#include "main.h"
#include "SDFileSystem.h"

#define TEXT_LEVEL 5

#define TX 24  // number of characters in X
#define TY 10  // number of characters in Y

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))


// DAC stuff
#define DAC_SYNC 2

uint8_t char_col = 0;  // current column counter
uint8_t char_row = 0;  // current row counter

Serial pc(USBTX, USBRX);

#include "vincent_data.h"

//DigitalOut sout(D8); //sync PA_9
//DigitalOut vout(D7); //video PA_8

DigitalOut dac0(PA_4);
DigitalOut dac1(PA_5);
DigitalOut dac2(PA_6);
DigitalOut dac3(PA_7);

DigitalOut user_led(PB_14);
int led_state = 1;

// trigger horizontal line draw
Ticker t;

uint8_t bl_line_s[H_RES]; //blank line sync buffer
uint8_t bl_line_v[H_RES]; //blank line video buffer
uint8_t vb_line_s[H_RES]; //vertical sync, sync buffer
uint8_t vb_line_v[H_RES]; //vertical sync, video buffer
uint8_t im_line_s[H_RES]; //image sync buffer

//buffers
uint8_t current_frame[YL][XL / 2];
uint8_t im_line_va_1[H_RES*V_RES];
uint8_t im_line_va_2[H_RES*V_RES];

//double buffered drawing
uint8_t* im_line_va;
uint8_t* im_back;

uint16_t l=0; //current line of scan
uint32_t tics = 0; //timer

// positive or negative?
int16_t sign(int16_t a)
{
    if(a > 0) return 1;
    if(a < 0) return -1;
    return 0;
}

// clear the screen and the text buffer
void clr()
{
    for(int i = 0; i < H_RES; i++)
        for(int j = 0; j < V_RES; j++)
            im_line_va[i+j*H_RES] = 0;    
}

// initialize video buffers
void init_buffers()
{
    clr(); // zero buffers
    for(int i = 0; i < H_RES; i++)
    {
        im_line_s[i] = DAC_SYNC;   
        bl_line_s[i] = DAC_SYNC;
        bl_line_v[i] = 0;
        vb_line_s[i] = 0;
        vb_line_v[i] = 0;
    }    
    im_line_s[0] = 0;
    im_line_s[1] = 0;
    im_line_s[2] = 0;
    im_line_s[3] = 0;
    
    for(int i = 0; i < 15; i++) im_line_s[i] = 0;
    
    bl_line_s[0] = 0;
    vb_line_s[0] = DAC_SYNC;
    bl_line_s[1] = 0;
    vb_line_s[1] = DAC_SYNC;
    
    bl_line_s[3] = 0;
    vb_line_s[3] = DAC_SYNC;
    bl_line_s[2] = 0;
    vb_line_s[2] = DAC_SYNC;
}

// video interrupt
void isr()
{
    uint8_t nop = 0, img = 0; //use nops or use wait_us
    uint8_t* sptr; //pointer to sync buffer for line
    uint8_t* vptr; //pointer to video buffer for line
    uint8_t* pptr; //porch
    
    if (l < V_PORCH_SIZE) {
        vptr = bl_line_v; 
        sptr = im_line_s;
        nop = 1;
    }
    else if (l < YL + V_PORCH_SIZE) {
        vptr = im_line_va + (l - 30) * H_RES; 
        sptr = im_line_s;
        nop = 1;
        img = 1;
    }
    else if (l < 254) { 
        vptr = bl_line_v; 
        sptr = bl_line_s; 
        nop = 0;
    } 
    else {
        vptr = vb_line_v;
        sptr = vb_line_s;
        nop = 1;
    }
    
    pptr = img ? bl_line_v : vptr;
    
    if (nop) {
        for (uint16_t i = 0; i < H_PORCH_SIZE; i++) {
            GPIOA->ODR = (pptr[i] + sptr[i]) << 4;
    
            asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
            asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
        }
        
        for (uint16_t i = 0; i < H_RES; i++) //loop over each column
        {
            GPIOA->ODR = (vptr[i] + sptr[i]) << 4;
    
            asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
            asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
        }
    } else {
        for(uint16_t i = 0; i < 12; i++) //loop over each column
        {
            GPIOA->ODR = sptr[i] << 4;
    
            asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
            asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
            asm("nop");asm("nop");asm("nop");asm("nop");
        }
    }
    
    //move to next line
    l++;
    tics++;
    if(l > 255) l = 0;
}

// draw letter
void draw_vincent(uint16_t x0, uint16_t y0, uint8_t c)
{
    if(c == 40) c = 41;
    else if(c == 41) c = 40;
    char* letter = vincent_data[c];
    for(uint16_t xp = 0; xp < 8; xp++)
    {
        for(uint16_t yp = 0; yp < 8; yp++)
        {
            im_line_va[H_RES*(yp+y0) + xp + x0] = CHECK_BIT(letter[yp],8-xp)?TEXT_LEVEL:0;
        }
    }
}

// draw string
void draw_vincent_string(char* str)
{
    for(int i = 0; i < strlen(str); i++)
    {
        if(str[i] == 0) return;
        char_col++; 
    if(char_col >= TX)
    {
        char_col = 0;
        char_row++;
    }
    if(char_row >= TY)
    {
        char_row = 0;
    }
    
    draw_vincent(X0 +2 + 8*char_col, Y0 + 14 + 8*char_row, 
        str[i]);
    }
}

void set_status_string(char* str)
{
    uint8_t char_col_backup = char_col;
    uint8_t char_row_backup = char_row;
    char_col = 0;
    char_row = TY - 1;
    
    draw_vincent_string(str);
    
    char_col = char_col_backup;
    char_row = char_row_backup;
}

int main()
{
    uint8_t *buf_swap_tmp;
    im_line_va = im_line_va_1;
    im_back = im_line_va_2;
    
    //init serial
    pc.baud(115200);
    pc.printf("derp!\r\n");
 
    //init buffers
    init_buffers();
    //init timer
    t.attach_us(&isr,64);
    
    /*init SD card, wait for card insertion*/ 
    SDFileSystem sd(DI, DO, SCK, CS, "sd");
    while (sd.disk_status()) {
        sd.disk_initialize();
        wait(0.5);
    }
    
    FILE *fp;
    
    fp = fopen("/sd/man.worm.starwars", "rb");
            
    uint32_t old_tics = tics;
    for(;;)
    { 
        if (feof(fp)) rewind(fp);
        fread(current_frame, 1, VIDEO_FRAME_SIZE, fp);
        for(int x = 0; x < XL; x += 2)
        {
            for(int y = 0; y < YL; y++)
            {
               im_back[H_RES*(y+Y0) + x + X0] = current_frame[YL - y][x >> 1] >> 4;
               im_back[H_RES*(y+Y0) + x + 1 + X0] = current_frame[YL - y][x >> 1];
            }
        }
        
        buf_swap_tmp = im_line_va;
        im_line_va = im_back;
        im_back = buf_swap_tmp;
        
        led_state = !led_state;
        user_led = led_state; 

        char status_string[20];
        sprintf(status_string, "%.1f", 15625.f / (float)(tics - old_tics));
        old_tics = tics;
        set_status_string(status_string);        
    }
}