it works!

Dependencies:   SDFileSystem2 mbed

Fork of manworm_tv_raster by Bayley Wang

main.cpp

Committer:
dicarloj
Date:
2018-05-03
Revision:
11:537cde55b27f
Parent:
10:1163fb31b0a7
Child:
12:e99cc1e9d928

File content as of revision 11:537cde55b27f:

#include "mbed.h"
#include <math.h>
#include "lisp.h"
#include "main.h"
#include "gfx.h"

// Resolution, including porches
#define V_RES 200
#define H_RES 300


// old shit
#define SX_MIN 30
#define SX_MAX 95
#define SY_MIN 10
#define SY_MAX 48
#define BX_0 30
#define BY_0 (V_RES/4 - 15)
#define BX 42
#define BY 15
#define BY2 9

// good new stuff
#define X0 75  // start of image in X
#define Y0 30  // start of image in Y
#define XL 220 // 25 chars
#define YL 165 // 20 chars

#define TX 24  // number of characters in X
#define TY 18  // 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))

#define N_COLOR 16

uint8_t char_col = 0;  // current column counter
uint8_t char_row = 0;  // current row counter
uint8_t text_buffer_counter = 0; // current index in text buffer counter
char most_recent_char = '0';

char text_buffer[TX*TY]; // input text buffer for lisp

AnalogIn joy1(A0);
AnalogIn joy2(A1);

uint8_t want_gfx = 0;
uint8_t vsync = 0;

Serial pc(USBTX, USBRX);

// font
char vincent_data[128][8] = { 
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x3E, 0x41, 0x55, 0x41, 0x55, 0x49, 0x3E }, 
  { 0x00, 0x3E, 0x7F, 0x6B, 0x7F, 0x6B, 0x77, 0x3E }, 
  { 0x00, 0x22, 0x77, 0x7F, 0x7F, 0x3E, 0x1C, 0x08 }, 
  { 0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08 }, 
  { 0x00, 0x08, 0x1C, 0x2A, 0x7F, 0x2A, 0x08, 0x1C }, 
  { 0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x08, 0x1C }, 
  { 0x00, 0x00, 0x1C, 0x3E, 0x3E, 0x3E, 0x1C, 0x00 }, 
  { 0xFF, 0xFF, 0xE3, 0xC1, 0xC1, 0xC1, 0xE3, 0xFF }, 
  { 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00 }, 
  { 0xFF, 0xFF, 0xE3, 0xDD, 0xDD, 0xDD, 0xE3, 0xFF }, 
  { 0x00, 0x0F, 0x03, 0x05, 0x39, 0x48, 0x48, 0x30 }, 
  { 0x00, 0x08, 0x3E, 0x08, 0x1C, 0x22, 0x22, 0x1C }, 
  { 0x00, 0x18, 0x14, 0x10, 0x10, 0x30, 0x70, 0x60 }, 
  { 0x00, 0x0F, 0x19, 0x11, 0x13, 0x37, 0x76, 0x60 }, 
  { 0x00, 0x08, 0x2A, 0x1C, 0x77, 0x1C, 0x2A, 0x08 }, 
  { 0x00, 0x60, 0x78, 0x7E, 0x7F, 0x7E, 0x78, 0x60 }, 
  { 0x00, 0x03, 0x0F, 0x3F, 0x7F, 0x3F, 0x0F, 0x03 }, 
  { 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x2A, 0x1C, 0x08 }, 
  { 0x00, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66 }, 
  { 0x00, 0x3F, 0x65, 0x65, 0x3D, 0x05, 0x05, 0x05 }, 
  { 0x00, 0x0C, 0x32, 0x48, 0x24, 0x12, 0x4C, 0x30 }, 
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F }, 
  { 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x2A, 0x1C, 0x3E }, 
  { 0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x1C, 0x1C, 0x1C }, 
  { 0x00, 0x1C, 0x1C, 0x1C, 0x7F, 0x3E, 0x1C, 0x08 }, 
  { 0x00, 0x08, 0x0C, 0x7E, 0x7F, 0x7E, 0x0C, 0x08 }, 
  { 0x00, 0x08, 0x18, 0x3F, 0x7F, 0x3F, 0x18, 0x08 }, 
  { 0x00, 0x00, 0x00, 0x70, 0x70, 0x70, 0x7F, 0x7F }, 
  { 0x00, 0x00, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00 }, 
  { 0x00, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x7F }, 
  { 0x00, 0x7F, 0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08 }, 
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18 }, 
  { 0x00, 0x36, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36 }, 
  { 0x00, 0x08, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x08 }, 
  { 0x00, 0x60, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x06 }, 
  { 0x00, 0x3C, 0x66, 0x3C, 0x28, 0x65, 0x66, 0x3F }, 
  { 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60 }, 
  { 0x00, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06 }, 
  { 0x00, 0x00, 0x36, 0x1C, 0x7F, 0x1C, 0x36, 0x00 }, 
  { 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00 }, 
  { 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60 }, 
  { 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60 }, 
  { 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00 }, 
  { 0x00, 0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x3C }, 
  { 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7E }, 
  { 0x00, 0x3C, 0x66, 0x06, 0x0C, 0x30, 0x60, 0x7E }, 
  { 0x00, 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C }, 
  { 0x00, 0x0C, 0x1C, 0x2C, 0x4C, 0x7E, 0x0C, 0x0C }, 
  { 0x00, 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C }, 
  { 0x00, 0x3C, 0x66, 0x60, 0x7C, 0x66, 0x66, 0x3C }, 
  { 0x00, 0x7E, 0x66, 0x0C, 0x0C, 0x18, 0x18, 0x18 }, 
  { 0x00, 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C }, 
  { 0x00, 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C }, 
  { 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00 }, 
  { 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30 }, 
  { 0x00, 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06 }, 
  { 0x00, 0x00, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x00 }, 
  { 0x00, 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60 }, 
  { 0x00, 0x3C, 0x66, 0x06, 0x1C, 0x18, 0x00, 0x18 }, 
  { 0x00, 0x38, 0x44, 0x5C, 0x58, 0x42, 0x3C, 0x00 }, 
  { 0x00, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66 }, 
  { 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C }, 
  { 0x00, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C }, 
  { 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C }, 
  { 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E }, 
  { 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60 }, 
  { 0x00, 0x3C, 0x66, 0x60, 0x60, 0x6E, 0x66, 0x3C }, 
  { 0x00, 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66 }, 
  { 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C }, 
  { 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x6C, 0x6C, 0x38 }, 
  { 0x00, 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66 }, 
  { 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E }, 
  { 0x00, 0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63 }, 
  { 0x00, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63 }, 
  { 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C }, 
  { 0x00, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60 }, 
  { 0x00, 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x3C, 0x06 }, 
  { 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x78, 0x6C, 0x66 }, 
  { 0x00, 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C }, 
  { 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18 }, 
  { 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E }, 
  { 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18 }, 
  { 0x00, 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63 }, 
  { 0x00, 0x63, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x63 }, 
  { 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18 }, 
  { 0x00, 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E }, 
  { 0x00, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E }, 
  { 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00 }, 
  { 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78 }, 
  { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F }, 
  { 0x00, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E }, 
  { 0x00, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C }, 
  { 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C }, 
  { 0x00, 0x06, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E }, 
  { 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C }, 
  { 0x00, 0x1C, 0x36, 0x30, 0x30, 0x7C, 0x30, 0x30 }, 
  { 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C }, 
  { 0x00, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66 }, 
  { 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C }, 
  { 0x00, 0x0C, 0x00, 0x0C, 0x0C, 0x6C, 0x6C, 0x38 }, 
  { 0x00, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66 }, 
  { 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }, 
  { 0x00, 0x00, 0x00, 0x63, 0x77, 0x7F, 0x6B, 0x6B }, 
  { 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x66 }, 
  { 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C }, 
  { 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60 }, 
  { 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x3C, 0x0D, 0x0F }, 
  { 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x60, 0x60 }, 
  { 0x00, 0x00, 0x00, 0x3E, 0x40, 0x3C, 0x02, 0x7C }, 
  { 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18 }, 
  { 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E }, 
  { 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18 }, 
  { 0x00, 0x00, 0x00, 0x63, 0x6B, 0x6B, 0x6B, 0x3E }, 
  { 0x00, 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66 }, 
  { 0x00, 0x00, 0x00, 0x66, 0x66, 0x3E, 0x06, 0x3C }, 
  { 0x00, 0x00, 0x00, 0x3C, 0x0C, 0x18, 0x30, 0x3C }, 
  { 0x00, 0x0E, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0E }, 
  { 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18 }, 
  { 0x00, 0x70, 0x18, 0x18, 0x0C, 0x18, 0x18, 0x70 }, 
  { 0x00, 0x00, 0x00, 0x3A, 0x6C, 0x00, 0x00, 0x00 }, 
  { 0x00, 0x08, 0x1C, 0x36, 0x63, 0x41, 0x41, 0x7F }
};

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

// trigger horizontal line draw
Ticker t;

uint8_t draw_line_inv = 0;

// miters logo bitmap
uint8_t miters[] = {
1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,
1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,
1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,0,0,0,
1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,0,0,
1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,
1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,
1,1,1,1,1,0,1,0,0,1,1,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,1,1,1,1,1,
1,0,1,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,1,0,1,0,1,
1,0,1,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,1,0,0,1,1,0,1,1,0,1,0,0,0,0,1,0,1,0,1,
1,0,1,0,1,0,0,1,1,0,1,0,1,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,1,

};





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
uint8_t im_line_va_1[H_RES*V_RES];
uint8_t im_line_va_2[H_RES*V_RES];
uint8_t* im_line_va; // active image buff
//uint8_t im_line_va[H_RES*V_RES]; //image video buffer

uint16_t l=0; //current line of scan

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

// clear the text buffer
void clr_text_buff()
{
    text_buffer_counter = 0;
    for(int i = 0; i < TX*TY; i++)
        text_buffer[i] = 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;
            
    clr_text_buff();
    
}

// initialize video buffers
void init_buffers()
{
    clr(); // zero buffers
    for(int i = 0; i < H_RES; i++)
    {
        im_line_s[i] = 1;   
        bl_line_s[i] = 1;
        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] = 1;
    bl_line_s[1] = 0;
    vb_line_s[1] = 1;
    
    bl_line_s[3] = 0;
    vb_line_s[3] = 1;
    bl_line_s[2] = 0;
    vb_line_s[2] = 1;
}

// video interrupt
void isr()
{
    uint8_t nop = 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
    if(l < V_RES){ vptr = im_line_va + ((l)*H_RES); sptr = im_line_s; nop = 1; vsync = 0;} //pick line buffers
    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; }
    uint16_t lmax = nop?H_RES:12; //number of columns
    for(uint16_t i = 0; i < lmax; i++) //loop over each column
    {
        nop = 1;
        if(sptr[i])
            GPIOA->ODR |= (1 << 9);
        else
            GPIOA->ODR &= ~(1 << 9);
             
        if(vptr[i])
            GPIOA->ODR |= (1 << 8);
        else
            GPIOA->ODR &= ~(1 << 8);

        
        if(nop) //nop delay
        {
            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 {wait_us(1); if(i > 2) i+=1;} //wait delay 
    }
    //move to next line
    l++;
    if(l == V_RES) vsync = 1;
    if(l > 255) l = 0;
}

// draw checkerboard pattern
void write_test_pattern(int x_in, int y_in,int k)
{
    int x_max = MIN(H_RES,x_in);
    int y_max = MIN(V_RES,y_in);
    
    // x 50 to 245
    for(int x = 65; x < x_max; x++)
    {
        for(int y = 30; y < y_max; y++)
        {
            im_line_va[y*H_RES + x] = ((y/k)%2)^((x/k)%2);
        }
    }
}

// draw miters logo
void draw_miters_at(int xx, int yy)
{
           int bmi = 0;
        for(int y = yy; y < BY2+yy; y++)
    {
        for(int x = xx; x < BX+xx; x++)
        {
            im_line_va[H_RES*y + x] = miters[bmi];
            bmi++;
        }
    }
}

// draw vertical line
void draw_vert(int16_t y0, int16_t y1, int16_t x0)
{
    for(int16_t i = y0; i < y1; i++)
        im_line_va[H_RES*i + x0] = 1;
}

// draw horizonal line
void draw_horiz(int16_t x0, int16_t x1, int16_t y0)
{
    for(int16_t i = x0; i < x1; i++)
        im_line_va[H_RES*y0 + i] = 1;
}

// draw line between points
void draw_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1)
{
    if(x0 > x1){ x0 = x0 ^ x1; x1 = x1^x0; x0 = x0^x1;y0 = y0 ^ y1; y1 = y1^y0; y0 = y0^y1; }
    if(x0 == x1){draw_vert(y0,y1,x0);}
    if(y0 == y1){draw_horiz(x0,x1,y0);}
    int16_t dx = x1 - x0;
    int16_t dy = y1 - y0;
    float derr = fabs((float)(dy)/(float)(dx));
    float err = 0.f;
    int16_t y = y0;
    for(int16_t x = x0; x < x1; x++)
    {
        //plotxy
        im_line_va[H_RES*y + x] = !draw_line_inv;
        err += derr;
        while(err >= 0.5f)
        {
            y +=  sign(dy);
            im_line_va[H_RES*y + x] = !draw_line_inv;
            err -= 1.f;
        }   
    }
}

// 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);
        }
    }
}

// go to new line
void new_line()
{
    char_col = 0;
    char_row++;
    if(char_row >= TY)
    {
        char_row = 0;
    }
}

// draw string
void draw_vincent_string(char* str)
{
    for(int i = 0; i < strlen(str); i++)
    {
        if(str[i] == 0 || str[i] == EOF) 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 draw_text_buffer()
//{
//    for(int yc = 0; yc < TY; yc++)
//    {
//        for(int xc = 0; xc < TX; xc++)
//        {
//            draw_vincent(X0 + 10 + 8*xc, Y0 + 10 + 8*yc, 
//                text_buffer[TX*yc + xc]%128);
//        }
//    } 
//}

// should the lisp interpreter run?
int want_lisp = 0;

void backspace()
{
    text_buffer[text_buffer_counter] = 0;
    if(text_buffer_counter > 0)
        text_buffer_counter--;
        
    draw_vincent(X0 +2 + 8*char_col, Y0 + 14 + 8*char_row, ' ');
    if(char_col > 0)
        char_col--;
    else
    {
        char_row--;
        char_col = TX - 1;
    }
}

void clear_all_text()
{
    char_col = 0;
    char_row = 0;
    clr_text_buff();
    clr();   
        // startup animation
    int miter_x_final = XL/2 + 20*cos(.11f*MAX(XL,YL)) + 80;
    int miter_y_final = YL/2 + 20*sin(.11f*MAX(XL,YL)) + 80;
    
    int x_correct = -miter_x_final +  X0 + 6;
    int y_correct = -miter_y_final +  Y0;
        for(int i = MAX(XL,YL) - 1; i < MAX(XL,YL); i++)
    {
        wait_us(10000);
        clr();
        int xp = MIN(XL,i);
        int yp = MIN(YL,i);
        draw_line(X0, Y0, X0 + xp, Y0);
        draw_line(X0+xp,Y0,X0+xp,Y0+yp);
        
        draw_line(X0, Y0+yp, X0 +xp, Y0+yp);
        draw_line(X0,Y0,X0,Y0+yp);
        float phase = (float)(i) / (float)MAX(XL,YL); 
        draw_miters_at(xp/2 + 20*cos(.11f*i) + 80 + (x_correct * phase),yp/2 + 20*sin(.11f*i) + 80 + (y_correct * phase));
        //draw_vincent(100,100,15);
    }
    
    // draw prompt
    draw_vincent_string(">");
}

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;
}

// on each serial char received
void serial_callback()
{
    // get characeter and store in text_buffer
    char new_char = pc.getc();
    most_recent_char = new_char;
    
    if(new_char == '^')
    {
        want_gfx = 1;
        return;
    }
    //char cn[8];
    //sprintf(cn,"[%d]",new_char);
    //draw_vincent_string(cn);
    if(new_char == 127)
    {
        backspace();
        return;
    }
    
    text_buffer[text_buffer_counter++] = new_char;
    
    // if it's <enter>, request lisp
    if(new_char == 13)
    {
        want_lisp = 1;
        return;
    }

    
    // increment rows/cols as needed
    char_col++; 
    if(char_col >= TX)
    {
        char_col = 0;
        char_row++;
    }
    if(char_row >= TY)
    {
        char_row = 0;
    }

    // draw new character
    draw_vincent(X0 +2 + 8*char_col, Y0 + 14 + 8*char_row, 
        new_char%128);
            
}

void spin_for_a_while(volatile int a)
{
    volatile int k = a;
    for(int i = 0; i < k; i++)
    {
        for(int j = 0; j < k; j++)
        {
            a++;
        }
    }
}

uint8_t gfx_is_init = 0;

// screen goes from -.5 to .5 on both axes
void draw_gfx_line(float x0, float y0, float x1, float y1)
{
    float x_width = (XL);
    float y_height = (YL);
    
    // want to rescale to 0 to 1
    x0 += 0.5f;
    y0 += 0.5f;
    
    x1 += 0.5f;
    y1 += 0.5f;
    //printf("x0: %.3f, y0: %.3f\r\n",x0,y0);
    int xx = x0 * x_width + X0;
    if(xx > (X0 + XL)) xx = (X0 + XL);
    if(xx < X0) xx = X0;
    int yy = y0 * y_height + Y0;
    if(yy > (Y0 + YL)) yy = (Y0 + YL);
    if(yy < Y0) yy = Y0;   
    
    int xx1 = x1 * x_width + X0;
    if(xx1 > (X0 + XL)) xx1 = (X0 + XL);
    if(xx1 < X0) xx1 = X0;
    int yy1 = y1 * y_height + Y0;
    if(yy1 > (Y0 + YL)) yy1 = (Y0 + YL);
    if(yy1 < Y0) yy1 = Y0;   
    
    draw_line(xx,yy,xx1,yy1);
    
}
//void swap_buffers()
//{
//    if(im_line_va == im_line_va_1)
//        im_line_va = im_line_va_2;
//    else
//        im_line_va = im_line_va_1;
//}
int main()
{
    im_line_va = im_line_va_1;
    // init serial
    pc.baud(115200);
    pc.attach(&serial_callback);
    pc.printf("derp!\r\n");
 
    // init buffers
    init_buffers();
    // init timer
    t.attach_us(&isr,64);
    
    wait_us(200000);
    int miter_x_final = XL/2 + 20*cos(.11f*MAX(XL,YL)) + 80;
    int miter_y_final = YL/2 + 20*sin(.11f*MAX(XL,YL)) + 80;
    int x_correct = -miter_x_final +  X0 + 6;
    int y_correct = -miter_y_final +  Y0;
    
    for(int i = 0; i < MAX(XL,YL); i+=3)
    {
        char stat_buff[30];
        sprintf(stat_buff,"f: %d",i);
        set_status_string(stat_buff);
        //wait_us(10000);
        
        spin_for_a_while(200);
        clr();
        int xp = MIN(XL,i);
        int yp = MIN(YL,i);
        draw_line(X0, Y0, X0 + xp, Y0);
        draw_line(X0+xp,Y0,X0+xp,Y0+yp);
        
        draw_line(X0, Y0+yp, X0 +xp, Y0+yp);
        draw_line(X0,Y0,X0,Y0+yp);
        float phase = (float)(i) / (float)MAX(XL,YL); 
        draw_miters_at(xp/2 + 20*cos(.11f*i) + 80 + (x_correct * phase),yp/2 + 20*sin(.11f*i) + 80 + (y_correct * phase));
        //draw_vincent(100,100,15);
    }
    
    clear_all_text();
    draw_vincent_string("Welcome to LISP MACHINE");
    new_line();
    draw_vincent_string("Connect over USB serial");
    new_line();
    draw_vincent_string("115200 baud");
    new_line();
    draw_vincent_string("use 'clear' to clear");
    new_line();
    draw_vincent_string("use '^' to use 3D MODE");
    new_line();
    draw_vincent_string(">");
    // main loop
    want_gfx = 1;

    for(;;) 
    {
        if(want_lisp) 
        {
            new_line();
            // runs interpreter and prints answer
            run_lisp(text_buffer);
            want_lisp = 0;
            new_line();
            clr_text_buff();
            //draw_vincent_string(">");
        }
        
        if(want_gfx)
        {
            if(!vsync) continue;
            if(!gfx_is_init)
            {
                init_gfx();
                gfx_is_init = 1;
            }   
            clr();
            float j2 = joy1.read() - .5f;;
            float j1 = joy2.read() - .5f;
            new_frame(j1,j2);
            draw_line(X0, Y0, X0 + XL, Y0);
            draw_line(X0+XL,Y0,X0+XL,Y0+YL);
            draw_line(X0, Y0+YL, X0 +XL, Y0+YL);
            draw_line(X0,Y0,X0,Y0+YL);
            most_recent_char = '0';
            //spin_for_a_while(400);
            
            
            
//            if(color)
//            {
//            for(int i = 0; i <  XL; i++)
//                draw_line(X0+i,Y0,X0+i,Y0+YL);
//            color = 0;
//                }
//                else
//                color = 1;
            
            //color = !color;
            //draw_gfx_line(-0.01,-0.01,0.01,0.01);
            char joy_string[20];
            sprintf(joy_string,"1: %.2f 2: %.2f",joy1.read(),joy2.read());
            //set_status_string(joy_string);
            set_status_string(get_gfx_stat());
            vsync = 0;
            //swap_buffers();
            
        }
    }
}