From 7e33567ba8943b098a5bb239fe81b828461a55cf Mon Sep 17 00:00:00 2001 From: "Haoran S. Diao" <0@hairydiode.xyz> Date: Fri, 8 Feb 2019 13:11:56 -0500 Subject: initial commit --- Makefile | 14 +++++ README | 7 +++ cbrll.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cbrll.h | 12 ++++ demo/Makefile | 6 ++ demo/README | 3 + demo/wsim.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 396 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 cbrll.c create mode 100644 cbrll.h create mode 100644 demo/Makefile create mode 100644 demo/README create mode 100644 demo/wsim.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ced6be0 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +libcbrll.a : cbrll.o + ar ru libcbrll.a cbrll.o + ranlib libcbrll.a +cbrll.o : cbrll.c cbrll.h + gcc -c cbrll.c +clean: + rm libcbrll.a cbrll.o +install: + cp libcbrll.a /usr/lib/libcbrll.a + cp cbrll.h /usr/include/cbrll.h +remove: + rm /usr/lib/libcbrll.a + rm /usr/include/cbrll.h + diff --git a/README b/README new file mode 100644 index 0000000..c6a685d --- /dev/null +++ b/README @@ -0,0 +1,7 @@ +Library for drawing graphics with braille characters. +By default, the screen is only 200x200 braille "pixels". +requires only standard C libraries. + +To install: + make + sudo make install diff --git a/cbrll.c b/cbrll.c new file mode 100644 index 0000000..0167ef0 --- /dev/null +++ b/cbrll.c @@ -0,0 +1,186 @@ +#include "cbrll.h" +/* this library stores the screen in a variable referred to in functions as map + * it takes the form of a 2 dimensional array of uint8_t + * takes char storing the on/off positions of 8 points, in braille encoding + * order, and prints the corresponding braille char + * maps maximum size is 200x200 pixels, which works out to a 50 by 100 array + */ + +void printbraille(uint8_t points) { + /* outputs braille characters, the encoding for braile is: + * 1 4 + * 2 5 + * 3 6 + * 7 8 + * with the block being in U+2800 to U+28FF + * in utf8 that's encoded + * 1110xxxx 10xxxxxx 10xxxxxx + * [1110](0010) [10](1000)87 [10]654321 + */ + printf("%c%c%c", + 0b11100010, + 0b10100000 | (points >> 6), + 0b10000000 | (points & 0b00111111)); +} +/* prints the map, clears output before aswell*/ +/*prints x1 to x2, y1 to y2 bytes of the map*/ +void printmap( uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2 ) { + uint8_t xi = x1; + uint8_t yi = y1; + /*terminal escape code to move the cursor to beginning of screen or 1,1*/ + printf("\033[1;1H"); + while (yi < y2) { + xi = 0; + while (xi < x2) { + printbraille(map[xi][yi]); + xi++; + } + printf("\n"); + yi++; + } +} +/* sets a pixel in the map, converts x,y coordinates to braille order + * if set is 0, then set it to 0 + * if 1, set to 1 + * if > 1, flip + * does not throw errors + */ +void setpixel(uint8_t x, uint8_t y,uint8_t set) { + /* anchor x and y coordinates, eg the index in map*/ + uint8_t ax; + uint8_t ay; + /*bitmask in braille order of the byte in mask*/ + uint8_t shift = 0x01; + /* check if out of bounds, since the arguments are unsigned, don't have + * to check below 0, doesn't throw errors + */ + if ( (x >= 200 ) || (y >= 200) ) { + return; + } + /* integer division rounds down, therefore dividing will always get the + * index + */ + ax = x/2; + ay = y/4; + /* + * maps to braille order based off of x and y offsets + * 1 4 + * 2 5 + * 3 6 + * 7 8 + */ + switch(x % 2) { + case 0: + switch (y % 4) { + case 0: + shift = shift << 0; + break; + case 1: + shift = shift << 1; + break; + case 2: + shift = shift << 2; + break; + case 3: + shift = shift << 6; + break; + } + break; + case 1: + switch (y % 4) { + case 0: + shift = shift << 3; + break; + case 1: + shift = shift << 4; + break; + case 2: + shift = shift << 5; + break; + case 3: + shift = shift << 7; + break; + } + break; + } + /* sets the bit based on set*/ + switch (set) { + case 0: + map[ax][ay] = map[ax][ay] & (~shift); + break; + case 1: + map[ax][ay] = map[ax][ay] | shift; + break; + default: + map[ax][ay] = ((~map[ax][ay]) & shift) | + ((~shift) & map[ax][ay]); + break; + } + return; +} +/*takes two points and draws a line between them, dot specifies that every nth x + * point be drawn, if dot != 1, then a dotted line is drawn + */ +void drawline(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t dot) { + /*temporary x and y for switching x1,y1 and x2,y1 if x1>x2*/ + uint8_t tv; + /*number of x values to translate*/ + uint8_t dx; + /*number of y values to translate*/ + uint8_t dy; + /* for whether dy should be positive or negative, 1 pos, 0 neg*/ + uint8_t dir; + /*drawin index*/ + uint8_t xi = 0; + /*makes sure that x1 < x2, otherwise switch them arround*/ + if (x1 > x2) { + tv = x1; + x1 = x2; + x2 = tv; + tv = y1; + y1 = y2; + y2 = tv; + } + dx = x2 - x1; + /*find absolute + * dir is used since i'm planning to port to a platform that may not + * have signed ints. + */ + if (y1 > y2) { + dir = 0; + dy = y1 - y2; + } else { + dir = 1; + dy = y2 - y1; + } + /* + *For vertical Lines + * Uses xi as a y index now + */ + if (x1 == x2) { + while (xi <= dy) { + if (dir) { + setpixel(x1, y1 + xi, 1); + } else { + setpixel(x1, y1 - xi, 1); + } + xi++; + } + } + /* + * loop through x and draws y in line, dots done with modulus. + */ + while (xi <= (dx)) { + if ((xi % dot) == 0) { + if (dir) { + setpixel(x1 + xi, y1 + ((dy/dx * xi)), 1); + } else { + setpixel(x1 + xi, y1 - ((dy/dx * xi)), 1); + } + } + xi++; + } + + return; +} + diff --git a/cbrll.h b/cbrll.h new file mode 100644 index 0000000..289cf58 --- /dev/null +++ b/cbrll.h @@ -0,0 +1,12 @@ +#ifndef CBRLL_H +#define CBRLL_H +#include +//for standard types +#include +//for printf +extern uint8_t map[100][50]; +void printbraille(uint8_t points); +void printmap( uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2 ); +void setpixel(uint8_t x, uint8_t y,uint8_t set); +void drawline(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t dot); +#endif diff --git a/demo/Makefile b/demo/Makefile new file mode 100644 index 0000000..870d2f4 --- /dev/null +++ b/demo/Makefile @@ -0,0 +1,6 @@ +wsim : wsim.o + gcc wsim.o -o wsim -lcbrll +wsim.o : wsim.c + gcc -c wsim.c +clean : + rm wsim.o wsim diff --git a/demo/README b/demo/README new file mode 100644 index 0000000..71d0d53 --- /dev/null +++ b/demo/README @@ -0,0 +1,3 @@ +Past attempt at +Simple Cellular Automata Like simulator using braille graphics. + diff --git a/demo/wsim.c b/demo/wsim.c new file mode 100644 index 0000000..78fdf77 --- /dev/null +++ b/demo/wsim.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include "cbrll.h" +/* map holding the pixels for a 200x200 pixel imagebuffer, [x][y] + * bits are in braille order within each byte + */ +uint8_t map[100][50]; +/* takes char storing the on/off positions of 8 points, in braille encoding + * order, and prints the corresponding braille char + */ + +/* global state bit switch */ +uint8_t state = 3; +#define STATE_LOOP 0x01 +#define STATE_DEJURE 0x02 + + +/*node, the thing being simulated + * 16 bytes each + */ +struct node { + /*culture to compare similatiry*/ + uint8_t culture; + /*strength to spread culture*/ + uint8_t memetic; + /*strength martial*/ + uint8_t martial; + /*state allegiance*/ + uint8_t dejure; + /*x and y positions*/ + uint8_t x; + uint8_t y; + /*connections to other nodes, 0 represents none*/ + uint8_t connections[10]; +}; +/*all the nodes, 0 is not used*/ +struct node nodes[256]; +/*makes a new random node*/ +struct node makenode() { + /*node to work on*/ + struct node rnode; + rnode.culture = (uint8_t)rand(); + rnode.memetic = (uint8_t)rand(); + rnode.martial = (uint8_t)rand(); + rnode.dejure = (uint8_t)rand(); + rnode.x = (uint8_t)rand(); + while (rnode.x >= 200) { + rnode.x = (uint8_t)rand(); + } + rnode.y = (uint8_t)rand(); + while (rnode.y >= 200) { + rnode.y = (uint8_t)rand(); + } + memset(rnode.connections, 0, 10*sizeof(uint8_t)); + return rnode; +} +/*draws nodes based on dejure or culture*/ +void drawnode(struct node drawn) { + /*which symbol to draw*/ + uint8_t symbol; + if (state & STATE_DEJURE) { + symbol = drawn.dejure; + } else { + symbol = drawn.culture; + } + /* draws symbol*/ + /*layout as follows + * 012 + * 7X3 + * 654 + */ + setpixel(drawn.x, drawn.y, 1); + setpixel(drawn.x-1, drawn.y-1, (symbol & (0x01 << 0)) && 1); + setpixel(drawn.x, drawn.y-1, (symbol & (0x01 << 1)) && 1); + setpixel(drawn.x+1, drawn.y-1, (symbol & (0x01 << 2)) && 1); + setpixel(drawn.x+1, drawn.y, (symbol & (0x01 << 3)) && 1); + setpixel(drawn.x+1, drawn.y+1, (symbol & (0x01 << 4)) && 1); + setpixel(drawn.x, drawn.y+1, (symbol & (0x01 << 5)) && 1); + setpixel(drawn.x-1, drawn.y+1, (symbol & (0x01 << 6)) && 1); + setpixel(drawn.x-1, drawn.y, (symbol & (0x01 << 7)) && 1); + /*draws memetic strenth*/ + /*Ma + *00123 Me + *1XXX4 + *2XOX5 + *3XXX6 + *45677 + */ + //a swich without breaks keeps executing + switch (drawn.memetic / 32) { + case 7: + setpixel(drawn.x+2,drawn.y+2,1); + case 6: + setpixel(drawn.x+2,drawn.y+1,1); + case 5: + setpixel(drawn.x+2,drawn.y,1); + case 4: + setpixel(drawn.x+2,drawn.y-1,1); + case 3: + setpixel(drawn.x+2,drawn.y-2,1); + case 2: + setpixel(drawn.x+1,drawn.y-2,1); + case 1: + setpixel(drawn.x,drawn.y-2,1); + case 0: + setpixel(drawn.x-1,drawn.y-2,1); + } + //martial strenth + switch (drawn.martial / 32) { + case 7: + setpixel(drawn.x+1,drawn.y+2,1); + case 6: + setpixel(drawn.x,drawn.y+2,1); + case 5: + setpixel(drawn.x-1,drawn.y+2,1); + case 4: + setpixel(drawn.x-2,drawn.y+2,1); + case 3: + setpixel(drawn.x-2,drawn.y+1,1); + case 2: + setpixel(drawn.x-2,drawn.y,1); + case 1: + setpixel(drawn.x-2,drawn.y-1,1); + case 0: + setpixel(drawn.x-2,drawn.y-2,1); + } + //draws connections + for (uint8_t i = 0; i < 10; i++) { + if (drawn.connections[i] != 0) { + drawline(drawn.x, drawn.y, + nodes[drawn.connections[i]].x, + nodes[drawn.connections[i]].y, + 1); + } + } +} + +int main (int argc, char * argv[]) { + /*holds keypress*/ + char input; + /*zeroing map*/ + memset(map, 0, sizeof(map[0][0]) * 100 * 50); + /*seeds random*/ + srand(696969); + for (int i = 0; i < 64; i++) { + nodes[i] = makenode(); + } + while (state & STATE_LOOP) { + for (int i = 1; i < 64; i++) { + drawnode(nodes[i]); + } + drawnode(nodes[0]); + printmap(0, 100, 0, 50); + + + /* checks input*/ + input = getc(stdin); + /*haven't set the terminal to raw mode so will still need + * space + */ + if (input == 'q') { + state = state & (~STATE_LOOP); + } + } + return 0; +} -- cgit v1.1