├── .gitignore ├── docs ├── .gitignore ├── svg │ └── .gitignore ├── module_port_svg │ └── .gitignore ├── can.jpg ├── dell.jpg ├── lines.png ├── overview.png ├── lines-trace.png ├── sram-trace.png ├── arduino-start.png ├── fpga-i2c-read.png ├── i2c-read-fail.png ├── myStorm_1024w.jpg ├── wii_sensor_03.jpg ├── arduino-readbyte.png ├── arduino-fullframe.png ├── line.md ├── port_template.dot ├── verilog_module.py ├── ports_to_svg.py ├── line.py └── overview.svg ├── tests ├── bresenham_state_filter.txt ├── sram_state_filter.txt ├── state_filter.txt ├── write_buf_state_filter.txt ├── pix_buf_state_filter.txt ├── camera_states.txt ├── clockdiv_tb.v ├── camera_tb.v ├── pulse_tb.v ├── vga_tb.v ├── gtk-pulse.gtkw ├── bresenham_tb.v ├── gtk-map_cam.gtkw ├── xy_leds_tb.v ├── gtk-xy_leds.gtkw ├── map_cam_tb.v ├── gtk-vga.gtkw ├── gtk-master.gtkw ├── gtk-bresenham.gtkw ├── sram_tb.v ├── gtk-i2c.gtkw ├── gtk-sram.gtkw ├── i2c_master_tb.v ├── gtk-camera.gtkw ├── i2c_tb.v ├── gtk-vga-sram.gtkw ├── sram_vga_tb.v ├── gtk-sram_vga_line.gtkw └── sram_vga_line_tb.v ├── button-pcb ├── .gitignore ├── buttonpcb.sch └── buttonpcb.kicad_pcb ├── TODO.md ├── src ├── pulse.v ├── clockdiv.v ├── xy_leds.v ├── map_cam.v ├── icestick.pcf ├── pixel_buffer.v ├── bresenham.v ├── vga.v ├── sram.v ├── camera.v ├── write_buffer.v ├── blackice.pcf ├── dvid.v ├── top.v └── i2c_master.v ├── README.md └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | svg 2 | -------------------------------------------------------------------------------- /docs/svg/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/module_port_svg/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/bresenham_state_filter.txt: -------------------------------------------------------------------------------- 1 | 0 IDLE 2 | 1 PLOT 3 | -------------------------------------------------------------------------------- /docs/can.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/can.jpg -------------------------------------------------------------------------------- /docs/dell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/dell.jpg -------------------------------------------------------------------------------- /docs/lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/lines.png -------------------------------------------------------------------------------- /button-pcb/.gitignore: -------------------------------------------------------------------------------- 1 | *bak 2 | *.net 3 | *.pro 4 | *lib 5 | fp.pretty 6 | fp-lib-table 7 | fab 8 | -------------------------------------------------------------------------------- /docs/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/overview.png -------------------------------------------------------------------------------- /docs/lines-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/lines-trace.png -------------------------------------------------------------------------------- /docs/sram-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/sram-trace.png -------------------------------------------------------------------------------- /docs/arduino-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/arduino-start.png -------------------------------------------------------------------------------- /docs/fpga-i2c-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/fpga-i2c-read.png -------------------------------------------------------------------------------- /docs/i2c-read-fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/i2c-read-fail.png -------------------------------------------------------------------------------- /docs/myStorm_1024w.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/myStorm_1024w.jpg -------------------------------------------------------------------------------- /docs/wii_sensor_03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/wii_sensor_03.jpg -------------------------------------------------------------------------------- /docs/arduino-readbyte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/arduino-readbyte.png -------------------------------------------------------------------------------- /docs/arduino-fullframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattvenn/fpga-virtual-graf/HEAD/docs/arduino-fullframe.png -------------------------------------------------------------------------------- /tests/sram_state_filter.txt: -------------------------------------------------------------------------------- 1 | 0 IDLE 2 | 1 WRITE_SETUP 3 | 2 WRITE 4 | 3 WRITE_WAIT 5 | 4 READ_SETUP 6 | 5 READ 7 | 6 READ_WAIT 8 | -------------------------------------------------------------------------------- /tests/state_filter.txt: -------------------------------------------------------------------------------- 1 | 0 IDLE 2 | 1 START 3 | 2 ADDR 4 | 3 RW 5 | 4 WACK_1 6 | 5 DATA_READ 7 | 6 DATA_WRITE 8 | 7 WACK_2 9 | 8 STOP 10 | 9 DATA_REQ 11 | -------------------------------------------------------------------------------- /tests/write_buf_state_filter.txt: -------------------------------------------------------------------------------- 1 | 0 START 2 | 1 ERASE 3 | 2 START_LINE 4 | 3 WAIT_LINE 5 | 4 ERASE_WAIT 6 | 5 READ_SRAM 7 | 6 READ_SRAM_WAIT 8 | 7 WRITE_SRAM 9 | 8 WRITE_SRAM_WAIT 10 | -------------------------------------------------------------------------------- /tests/pix_buf_state_filter.txt: -------------------------------------------------------------------------------- 1 | 0 IDLE 2 | 1 READ 3 | 2 READ_WAIT 4 | 3 BUFF_WRITE 5 | 4 CAM_READ 6 | 5 CAM_READ_WAIT 7 | 6 CAM_WRITE 8 | 7 CAM_WRITE_WAIT 9 | 8 ERASE 10 | 9 ERASE_WAIT 11 | -------------------------------------------------------------------------------- /tests/camera_states.txt: -------------------------------------------------------------------------------- 1 | 0 START 2 | 1 STATE_CONF 3 | 2 STATE_CONF_WAIT 4 | 3 STATE_CONF_DELAY 5 | 4 STATE_REQ_DATA_1 6 | 5 STATE_REQ_DATA_2 7 | 6 STATE_REQ_DATA_3 8 | 7 STATE_REQ_DATA_4 9 | 8 STATE_REQ_DATA_5 10 | 9 STATE_PROCESS_DATA 11 | 10 STATE_WAIT 12 | 11 STATE_START_WAIT 13 | -------------------------------------------------------------------------------- /tests/clockdiv_tb.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module test; 3 | 4 | /* Make a reset that pulses once. */ 5 | initial begin 6 | 7 | $dumpfile("test.vcd"); 8 | $dumpvars(0,test); 9 | # 2000; 10 | $finish; 11 | end 12 | 13 | /* Make a regular pulsing clock. */ 14 | reg clk = 0; 15 | wire clk_out; 16 | always #1 clk = !clk; 17 | 18 | divM #(.M(500)) clockdiv(.clk_in(clk), .clk_out(clk_out)); 19 | 20 | endmodule // test 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/camera_tb.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module test; 3 | 4 | reg reset = 0; 5 | wire i2c_sda; 6 | wire i2c_scl; 7 | 8 | initial begin 9 | $dumpfile("test.vcd"); 10 | $dumpvars(0,test); 11 | # 2 reset = 0; 12 | # 4000; 13 | $finish; 14 | end 15 | 16 | // clock 17 | reg clk = 0; 18 | always #1 clk = !clk; 19 | 20 | camera cam(.clk_en(1), .clk (clk), .reset (reset), .i2c_scl(i2c_scl), .i2c_sda(i2c_sda) ); 21 | 22 | endmodule // test 23 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Todo 2 | 3 | * default cases for state machines 4 | * docs 5 | * svg overview - done 6 | * floorplan - done 7 | * simple module, verilog and svg (pulse.v) - done 8 | * medium module, verilog and svg (vga.v) - done 9 | * complex module, verilog and svg (bresenham.v) - done 10 | * coverpage - done 11 | * some kind of hand out with all the links - print a few README.md 12 | * output of yosys netlist? 13 | * lut definition of lattice - done 14 | * gtkwave signals 15 | * recut case 16 | -------------------------------------------------------------------------------- /src/pulse.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module pulse ( 3 | input wire clk, 4 | input wire in, 5 | input wire reset, 6 | output reg out 7 | ); 8 | 9 | reg last; 10 | always @(posedge clk) begin 11 | if(reset)begin 12 | last <= 0; 13 | out <= 0; 14 | end else begin 15 | last <= in; 16 | if(last == 0 && in == 1) 17 | out <= 1; 18 | else 19 | out <= 0; 20 | end 21 | end 22 | 23 | endmodule 24 | -------------------------------------------------------------------------------- /tests/pulse_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | reg clk = 0; 4 | reg reset = 1; 5 | reg in = 0; 6 | 7 | 8 | /* Make a reset that pulses once. */ 9 | initial begin 10 | $dumpfile("test.vcd"); 11 | $dumpvars(0, test); 12 | # 1 reset <= 0; 13 | # 5 in <= 1; 14 | # 5 in <= 0; 15 | # 6; 16 | # 5 in <= 0; 17 | # 5 in <= 1; 18 | # 5; 19 | $finish; 20 | end 21 | 22 | pulse pulse_test(.reset(reset), .clk(clk), .in(in)); 23 | 24 | /* Make a regular pulsing clock. */ 25 | always #1 clk = !clk; 26 | 27 | endmodule // test 28 | -------------------------------------------------------------------------------- /tests/vga_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | reg clk = 0; 4 | wire hsync; 5 | wire vsync; 6 | reg [7:0] pixels = 8'b00111100; 7 | reg reset = 1; 8 | 9 | /* Make a reset that pulses once. */ 10 | initial begin 11 | $dumpfile("test.vcd"); 12 | $dumpvars(0, test); 13 | # 1 reset <= 0; 14 | wait(vga_test.vcounter == 30); // border ends after 10 pixels 15 | # 1000; 16 | $finish; 17 | end 18 | 19 | vga vga_test(.reset(reset), .pixels(pixels), .clk(clk)); 20 | 21 | /* Make a regular pulsing clock. */ 22 | always #1 clk = !clk; 23 | 24 | endmodule // test 25 | -------------------------------------------------------------------------------- /src/clockdiv.v: -------------------------------------------------------------------------------- 1 | //- divM.v 2 | //With thanks to Obijuan 3 | //https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki/Cap%C3%ADtulo-15%3A-Divisor-de-frecuencias 4 | module divM(input wire clk_in, output wire clk_out); 5 | 6 | // default clock divider 7 | parameter M = 5; 8 | 9 | // number of bits necessary to count up to the divider 10 | localparam N = $clog2(M); 11 | 12 | reg [N-1:0] divcounter = 0; 13 | 14 | //-- Contador módulo M 15 | always @(posedge clk_in) 16 | if (divcounter == M - 1) 17 | divcounter <= 0; 18 | else 19 | divcounter <= divcounter + 1; 20 | 21 | //clock goes high when MSB is high 22 | assign clk_out = divcounter[N-1]; 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /tests/gtk-pulse.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Tue Oct 24 11:37:01 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/build/pulse.vcd" 6 | [dumpfile_mtime] "Tue Oct 24 11:36:40 2017" 7 | [dumpfile_size] 595 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/tests/gtk-pulse.gtkw" 9 | [timestart] 0 10 | [size] 1450 600 11 | [pos] -1 -1 12 | *-2.950369 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 80 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 155 18 | @28 19 | test.clk 20 | test.reset 21 | test.in 22 | @29 23 | test.pulse_test.out 24 | [pattern_trace] 1 25 | [pattern_trace] 0 26 | -------------------------------------------------------------------------------- /tests/bresenham_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 10 ns / 1 ns 2 | module test; 3 | 4 | reg clk = 0; 5 | reg reset = 0; 6 | 7 | reg [9:0] x1 = 640; 8 | reg [9:0] y1 = 480; 9 | 10 | reg [9:0] x0 = 0; 11 | reg [9:0] y0 = 0; 12 | 13 | wire done; 14 | reg start = 0; 15 | 16 | initial begin 17 | $dumpfile("test.vcd"); 18 | $dumpvars(0,test); 19 | $dumpon; 20 | # 2 reset = 1; 21 | # 2 reset = 0; 22 | # 2 start <= 1; 23 | # 2 start <= 0; 24 | # 1 25 | wait(done == 1); 26 | # 5 27 | $finish; 28 | end 29 | 30 | bresenham line (.clk(clk), .reset(reset), .x0(x0), .y0(y0), .x1(x1), .y1(y1), .done(done), .start(start), .clk_en(1'b1)); 31 | 32 | always #1 clk = !clk; 33 | 34 | endmodule 35 | -------------------------------------------------------------------------------- /src/xy_leds.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module xy_leds( 3 | input wire [9:0] x, 4 | input wire [9:0] y, 5 | input wire reset, 6 | output wire LED1, 7 | output wire LED2, 8 | output wire LED3, 9 | output wire LED4 10 | ); 11 | 12 | localparam MID_X = 1024 / 2 ; 13 | localparam MID_Y = 768 / 2; 14 | 15 | wire data_ok; 16 | assign data_ok = (y < 1023) && ~reset; // y is 1023 if no blob found 17 | 18 | /* 19 | 4 20 | 21 | 3 5 1 22 | 23 | 2 24 | */ 25 | 26 | assign LED1 = (x < MID_X ) ? data_ok : 0; 27 | assign LED2 = (x > MID_X ) ? data_ok : 0; 28 | 29 | assign LED3 = (y > MID_Y ) ? data_ok : 0; 30 | assign LED4 = (y < MID_Y ) ? data_ok : 0; 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /src/map_cam.v: -------------------------------------------------------------------------------- 1 | module map_cam( 2 | input wire reset, 3 | input wire clk, 4 | input wire [9:0]x_in, // range 1024 5 | input wire [9:0]y_in, // 768 6 | output reg valid, 7 | output reg [9:0]x_out, // 640 8 | output reg [8:0]y_out // 480 9 | ); 10 | 11 | reg [13:0] x_temp; 12 | reg [13:0] y_temp; 13 | 14 | 15 | always @(posedge clk) begin 16 | if(reset) 17 | valid <= 0; 18 | else begin 19 | x_temp = x_in * 10; // blocking 20 | y_temp = y_in * 10; 21 | x_out = x_temp >> 4; 22 | y_out = y_temp >> 4; 23 | end 24 | 25 | if(y_in == 1023) 26 | valid <= 0; 27 | else 28 | valid <= 1; 29 | end 30 | endmodule 31 | -------------------------------------------------------------------------------- /tests/gtk-map_cam.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Fri Sep 22 16:55:57 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/build/map_cam.vcd" 6 | [dumpfile_mtime] "Fri Sep 22 16:55:37 2017" 7 | [dumpfile_size] 13417 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/tests/gtk-map_cam.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-11.000000 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 130 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 155 18 | @22 19 | test.mc.x_in[9:0] 20 | test.mc.x_out[9:0] 21 | test.mc.y_in[9:0] 22 | @23 23 | test.mc.y_out[8:0] 24 | [pattern_trace] 1 25 | [pattern_trace] 0 26 | -------------------------------------------------------------------------------- /tests/xy_leds_tb.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module test; 3 | 4 | /* Make a reset that pulses once. */ 5 | reg reset = 1; 6 | reg [10:0] x; 7 | reg [10:0] y; 8 | integer i; 9 | integer j; 10 | initial begin 11 | 12 | $dumpfile("test.vcd"); 13 | $dumpvars(0,test); 14 | # 2 reset = 0; 15 | y <= 500; 16 | 17 | for (i=0; i < 1000; i=i+100) begin 18 | # 1; 19 | x <= i; 20 | end 21 | 22 | x <= 500; 23 | for (j=0; j < 1000; j=j+100) begin 24 | # 1; 25 | y <= j; 26 | end 27 | 28 | $finish; 29 | end 30 | 31 | /* Make a regular pulsing clock. */ 32 | reg clk = 0; 33 | always #1 clk = !clk; 34 | 35 | xy_leds leds(.x(x), .y(y)); 36 | 37 | endmodule // test 38 | 39 | 40 | -------------------------------------------------------------------------------- /tests/gtk-xy_leds.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Fri Sep 22 16:54:54 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/build/xy_leds.vcd" 6 | [dumpfile_mtime] "Fri Sep 22 16:53:29 2017" 7 | [dumpfile_size] 936 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/tests/gtk-xy_leds.gtkw" 9 | [timestart] 0 10 | [size] 1000 600 11 | [pos] -1 -1 12 | *-2.888969 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 90 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 155 18 | @28 19 | test.leds.LED1 20 | test.leds.LED2 21 | test.leds.LED3 22 | test.leds.LED4 23 | @22 24 | test.leds.x[9:0] 25 | test.leds.y[9:0] 26 | @29 27 | test.leds.reset 28 | [pattern_trace] 1 29 | [pattern_trace] 0 30 | -------------------------------------------------------------------------------- /tests/map_cam_tb.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module test; 3 | 4 | /* Make a reset that pulses once. */ 5 | reg reset = 1; 6 | reg [9:0] x = 0; 7 | reg [9:0] y = 0; 8 | 9 | integer i, j; 10 | 11 | initial begin 12 | 13 | $dumpfile("test.vcd"); 14 | $dumpvars(0,test); 15 | # 2 reset = 0; 16 | 17 | for (i=0; i < 1024; i=i+1) begin 18 | # 2; 19 | x <= i; 20 | end 21 | # 2 x <= 1023; 22 | 23 | for (j=0; j < 768; j=j+1) begin 24 | # 2; 25 | y <= j; 26 | end 27 | y <= 767; 28 | # 2 29 | y <= 1023; 30 | # 2 31 | $finish; 32 | end 33 | 34 | /* Make a regular pulsing clock. */ 35 | reg clk = 0; 36 | always #1 clk = !clk; 37 | 38 | map_cam mc(.clk(clk), .reset(reset), .x_in(x), .y_in(y)); 39 | 40 | endmodule // test 41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/gtk-vga.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Mon Sep 11 08:45:00 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/test.vcd" 6 | [dumpfile_mtime] "Mon Sep 11 08:43:33 2017" 7 | [dumpfile_size] 27926 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/gtk-vga.gtkw" 9 | [timestart] 0 10 | [size] 1600 1176 11 | [pos] -1 -1 12 | *-18.000000 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 170 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 357 18 | @28 19 | test.vga_test.clk 20 | test.vga_test.pixel 21 | test.vga_test.hsync 22 | test.vga_test.vsync 23 | test.vga_test.blank 24 | test.vga_test.blue[2:0] 25 | test.vga_test.red[2:0] 26 | test.vga_test.green[2:0] 27 | @25 28 | test.vga_test.hcounter[10:0] 29 | @22 30 | test.vga_test.vcounter[9:0] 31 | [pattern_trace] 1 32 | [pattern_trace] 0 33 | -------------------------------------------------------------------------------- /docs/line.md: -------------------------------------------------------------------------------- 1 | # Line drawing algorithm resources 2 | 3 | * https://github.com/kavinr/Bresenham-Line-Drawing-Algorithm 4 | * https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm 5 | * https://www.youtube.com/watch?v=IDFB5CDpLDE 6 | * http://www.cs.columbia.edu/~sedwards/classes/2015/4840/lines.pdf 7 | 8 | ![lines](lines.png) 9 | 10 | Drawn using Bresenham's algorithm, adapted for integer maths: [line.py](line.py) 11 | 12 | ![line strace](lines-trace.png) 13 | 14 | Shows simulation of algorithm using [bresenham.v](../bresenham.v). 15 | 16 | After initial calculation, each pixel takes one clock cycle to draw. SRAM takes 17 | about 10 clocks for a read then write for each pixel location. 18 | 19 | At 640 x 480, there is a region at the bottom of the screen where the SRAM is 20 | not being used. 45 blank lines @ 800 pix wide = 36k clocks. 21 | 22 | So 36k / 15 clocks per pixel of a line = 2400 pixels maximum line length before 23 | beginning to draw the screen again. Diagonal of the screen is 800px, so there is 24 | time to draw the longest line possible. 25 | -------------------------------------------------------------------------------- /tests/gtk-master.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Mon Dec 26 14:35:44 2016 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/ice-i2c/test.vcd" 6 | [dumpfile_mtime] "Mon Dec 26 14:35:25 2016" 7 | [dumpfile_size] 1164 8 | [savefile] "/home/mattvenn/work/fpga/ice-i2c/gtk-master.gtkw" 9 | [timestart] 151 10 | [size] 1440 876 11 | [pos] -1 -1 12 | *-3.044887 169 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 210 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 358 18 | @28 19 | test.clk 20 | @29 21 | test.data[7:0] 22 | @28 23 | test.reset 24 | test.i2c_addr[6:0] 25 | @22 26 | test.packets[4:0] 27 | @28 28 | test.rw 29 | test.i2c.ready 30 | test.i2c.start 31 | test.i2c.data_req 32 | @22 33 | test.i2c.data_out[7:0] 34 | test.i2c.count[7:0] 35 | @28 36 | test.i2c.saved_data[7:0] 37 | @2024 38 | ^1 /home/mattvenn/work/fpga/ice-i2c/state_filter.txt 39 | test.i2c.state[8:0] 40 | @28 41 | test.i2c.i2c_scl 42 | test.i2c.i2c_sda_tri 43 | [pattern_trace] 1 44 | [pattern_trace] 0 45 | -------------------------------------------------------------------------------- /tests/gtk-bresenham.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Sun Sep 17 15:25:53 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/test.vcd" 6 | [dumpfile_mtime] "Sun Sep 17 15:25:22 2017" 7 | [dumpfile_size] 4910 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/gtk-bresenham.gtkw" 9 | [timestart] 0 10 | [size] 1600 1176 11 | [pos] 0 24 12 | *-12.365406 4270 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 249 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 358 18 | @28 19 | test.line.clk 20 | test.line.reset 21 | test.line.start 22 | test.line.plot 23 | test.line.clk_en 24 | @200 25 | - 26 | @28 27 | test.line.done 28 | @2024 29 | ^1 /home/mattvenn/work/fpga/virtual-graffiti/bresenham_state_filter.txt 30 | test.line.state[2:0] 31 | @24 32 | test.line.x[9:0] 33 | test.line.y[9:0] 34 | test.line.x0[9:0] 35 | test.line.y0[9:0] 36 | test.line.x1[9:0] 37 | test.line.y1[9:0] 38 | @25 39 | test.line.counter[10:0] 40 | [pattern_trace] 1 41 | [pattern_trace] 0 42 | -------------------------------------------------------------------------------- /tests/sram_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | reg clk = 0; 4 | reg reset = 0; 5 | reg write = 0; 6 | reg read = 0; 7 | wire ready; 8 | reg [17:0] address; 9 | wire [15:0] data_read; 10 | reg [15:0] data_write; 11 | output [15:0] data_pins_out; 12 | input [15:0] data_pins_in; 13 | 14 | wire CS; 15 | wire OE; 16 | wire WE; 17 | 18 | reg set_data = 0; 19 | assign data_pins_in = set_data ? 16'h0A0A : 16'hzz; 20 | initial begin 21 | $dumpfile("test.vcd"); 22 | $dumpvars(0,test); 23 | $dumpon; 24 | # 1 reset = 1; 25 | # 2 reset = 0; 26 | // write 27 | # 1 address = 17'h0; 28 | # 1 data_write = 16'hAAAA; 29 | # 2 write = 1; 30 | # 2 write = 0; 31 | wait(ready == 1); 32 | // read 33 | # 1 set_data <= 1; 34 | # 2 read = 1; 35 | # 2 read = 0; 36 | # 20 37 | $finish; 38 | end 39 | 40 | sram sram_test(.clk(clk), .address(address), .data_read(data_read), .data_write(data_write), .write(write), .read(read), .reset(reset), .ready(ready), .data_pins_out(data_pins_out), .data_pins_in(data_pins_in), .OE(OE), .CS(CS), .WE(WE)); 41 | 42 | always #1 clk = !clk; 43 | 44 | endmodule // test 45 | -------------------------------------------------------------------------------- /src/icestick.pcf: -------------------------------------------------------------------------------- 1 | set_io LED1 99 # right 2 | set_io LED2 98 # bot 3 | set_io LED3 97 # left 4 | set_io LED4 96 # top 5 | set_io LED5 95 # centre green 6 | set_io clk 21 7 | 8 | set_io pixartclk 62 9 | set_io i2c_scl 61 10 | set_io i2c_sda 60 11 | set_io i2c_sda_in 56 12 | set_io button 44 13 | 14 | #set_io cam_reset 48 15 | #set_io clk_out 48 16 | 17 | # J1 18 | set_io PIO0[0] 112 # Pin 3 19 | set_io PIO0[1] 113 # Pin 4 20 | set_io PIO0[2] 114 # Pin 5 21 | set_io PIO0[3] 115 # Pin 6 22 | set_io PIO0[4] 116 # Pin 7 23 | set_io PIO0[5] 117 # Pin 8 24 | set_io PIO0[6] 118 # Pin 9 25 | set_io PIO0[7] 119 # Pin 10 MSB 26 | 27 | # Connector J3 28 | #set_io PIO2_17 62 # Pin 3 29 | #set_io PIO2_16 61 # Pin 4 30 | #set_io PIO2_15 60 # Pin 5 31 | #set_io PIO2_14 56 # Pin 6 32 | #set_io PIO2_13 48 # Pin 7 33 | #set_io PIO2_12 47 # Pin 8 34 | #set_io PIO2_11 45 # Pin 9 35 | #set_io PIO2_10 44 # Pin 10 36 | 37 | set_io --warn-no-port PMOD[0] 78 38 | set_io --warn-no-port PMOD[1] 79 39 | set_io --warn-no-port PMOD[2] 80 40 | set_io --warn-no-port PMOD[3] 81 41 | set_io --warn-no-port PMOD[4] 87 42 | set_io --warn-no-port PMOD[5] 88 43 | set_io --warn-no-port PMOD[6] 90 44 | set_io --warn-no-port PMOD[7] 91 45 | -------------------------------------------------------------------------------- /tests/gtk-i2c.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Mon Dec 26 18:59:09 2016 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/ice-i2c/test.vcd" 6 | [dumpfile_mtime] "Mon Dec 26 18:58:34 2016" 7 | [dumpfile_size] 2375 8 | [savefile] "/home/mattvenn/work/fpga/ice-i2c/gtk-i2c.gtkw" 9 | [timestart] 1643 10 | [size] 1440 876 11 | [pos] -1 -1 12 | *-9.023619 2017 -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 13 | [treeopen] test. 14 | [treeopen] test.cam. 15 | [sst_width] 263 16 | [signals_width] 365 17 | [sst_expanded] 1 18 | [sst_vpaned_height] 252 19 | @28 20 | test.LED1 21 | test.LED2 22 | test.LED3 23 | test.LED4 24 | test.LED5 25 | @24 26 | test.x[10:0] 27 | test.y[10:0] 28 | @28 29 | test.clk 30 | test.db1.button 31 | test.debounced 32 | test.deb1 33 | @2025 34 | ^1 /home/mattvenn/work/fpga/ice-i2c/camera_states.txt 35 | test.cam.state[8:0] 36 | @24 37 | test.cam.data_reads[4:0] 38 | test.cam.i2c.saved_packets[4:0] 39 | @28 40 | test.i2c_start 41 | @2024 42 | ^2 /home/mattvenn/work/fpga/ice-i2c/state_filter.txt 43 | test.cam.i2c.state[8:0] 44 | @22 45 | test.cam.i2c.count[7:0] 46 | @28 47 | test.cam.i2c.saved_rw 48 | test.i2c_scl 49 | test.cam.i2c.i2c_sda_in 50 | test.i2c_sda 51 | [pattern_trace] 1 52 | [pattern_trace] 0 53 | -------------------------------------------------------------------------------- /tests/gtk-sram.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Wed Sep 20 18:16:14 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/test.vcd" 6 | [dumpfile_mtime] "Wed Sep 20 18:13:01 2017" 7 | [dumpfile_size] 997 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/gtk-sram.gtkw" 9 | [timestart] 0 10 | [size] 1247 880 11 | [pos] -1 -1 12 | *-4.272297 17 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 343 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 255 18 | @28 19 | test.sram_test.clk 20 | test.sram_test.reset 21 | test.sram_test.ready 22 | @22 23 | test.sram_test.data_write[15:0] 24 | test.sram_test.data_read[15:0] 25 | test.sram_test.address[17:0] 26 | @28 27 | test.read 28 | test.sram_test.write 29 | test.sram_test.chip_select 30 | test.CS 31 | @200 32 | - 33 | @28 34 | test.sram_test.output_enable 35 | test.sram_test.data_pins_out_en 36 | @200 37 | - 38 | @2023 39 | ^2 /home/mattvenn/work/fpga/virtual-graffiti/sram_state_filter.txt 40 | test.sram_test.state[2:0] 41 | @28 42 | test.OE 43 | test.sram_test.write_enable 44 | test.WE 45 | @22 46 | test.sram_test.address_pins[17:0] 47 | test.sram_test.data_pins_out[15:0] 48 | test.sram_test.data_pins_in[15:0] 49 | [pattern_trace] 1 50 | [pattern_trace] 0 51 | -------------------------------------------------------------------------------- /tests/i2c_master_tb.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module test; 3 | 4 | /* Make a reset that pulses once. */ 5 | reg reset = 1; 6 | reg start = 0; 7 | reg [4:0] packets = 2; 8 | reg rw = 0; // write 9 | reg [7:0] data = 8'hA0; 10 | reg [6:0] i2c_addr = 7'h21; 11 | wire data_req; 12 | 13 | wire i2c_ready; 14 | integer i; 15 | initial begin 16 | /* 17 | $readmemh("i2cdata.txt", i2c_data); 18 | for (i=0; i < 3; i=i+1) begin 19 | $display("%d:%h",i,i2c_data[i]); 20 | flat_i2c_data[i*8 +: 8] = i2c_data[i]; 21 | end 22 | */ 23 | 24 | $dumpfile("test.vcd"); 25 | $dumpvars(0,test); 26 | # 2 reset = 0; 27 | # 4 start = 1; 28 | # 8 start = 0; 29 | wait (data_req == 1); 30 | data <= 8'hF0; 31 | wait (data_req == 1); 32 | data <= 8'h0F; 33 | wait (i2c_ready == 1); 34 | 35 | rw <= 1; 36 | packets <= 4; 37 | # 4 start = 1; 38 | # 8 start = 0; 39 | wait (i2c_ready == 1); 40 | # 20 41 | 42 | $finish; 43 | end 44 | 45 | /* Make a regular pulsing clock. */ 46 | reg clk = 0; 47 | always #1 clk = !clk; 48 | 49 | 50 | i2c_master i2c(.clk (clk), .addr(i2c_addr), .data(data), .reset (reset), .packets(packets), .rw(rw), .start(start), .ready(i2c_ready), .data_req(data_req)); 51 | 52 | endmodule // test 53 | 54 | -------------------------------------------------------------------------------- /tests/gtk-camera.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Wed Oct 11 16:32:30 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/build/camera.vcd" 6 | [dumpfile_mtime] "Wed Oct 11 16:30:13 2017" 7 | [dumpfile_size] 2190 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/tests/gtk-camera.gtkw" 9 | [timestart] 0 10 | [size] 1440 876 11 | [pos] -1 -1 12 | *-9.051907 199 -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 13 | [treeopen] test. 14 | [treeopen] test.cam. 15 | [sst_width] 263 16 | [signals_width] 428 17 | [sst_expanded] 1 18 | [sst_vpaned_height] 399 19 | @28 20 | test.clk 21 | test.reset 22 | test.cam.data_ready 23 | test.cam.data_req 24 | @22 25 | test.cam.i2c_data[7:0] 26 | @c00200 27 | -test.cam.state 28 | @1401200 29 | -group_end 30 | @24 31 | test.cam.config_byte[3:0] 32 | @2025 33 | ^1 /home/mattvenn/work/fpga/virtual-graffiti/tests/camera_states.txt 34 | test.cam.state[3:0] 35 | @22 36 | test.cam.delay_count[7:0] 37 | @20000 38 | - 39 | @28 40 | test.cam.i2c_start 41 | @24 42 | test.cam.i2c.saved_packets[4:0] 43 | @22 44 | test.cam.i2c.data_out[7:0] 45 | @28 46 | test.cam.i2c.data_req 47 | test.cam.i2c.data_ready 48 | @22 49 | test.cam.i2c.saved_data[7:0] 50 | test.cam.i2c.data[7:0] 51 | @28 52 | test.cam.i2c_ready 53 | @2024 54 | ^2 /home/mattvenn/work/fpga/virtual-graffiti/tests/state_filter.txt 55 | test.cam.i2c.state[8:0] 56 | @28 57 | test.cam.i2c.saved_rw 58 | test.i2c_scl 59 | test.i2c_sda 60 | [pattern_trace] 1 61 | [pattern_trace] 0 62 | -------------------------------------------------------------------------------- /docs/port_template.dot: -------------------------------------------------------------------------------- 1 | digraph test { 2 | 3 | // defaults 4 | graph [ rankdir = LR ]; 5 | node [shape=point style=invis]; 6 | 7 | // module 8 | mapcam [style="" shape=plaintext label=< 9 | 10 | 11 | 12 | 13 | 14 | 25 | 26 |
{{ module.name }}
15 | 16 | {% for in, out in module.zip_ports() %} 17 | 18 | // in ports 19 | // separator 20 | // out ports 21 | 22 | {% endfor %} 23 |
{{in.name}}{{out.name}}
24 |
27 | >, ]; 28 | 29 | // inputs 30 | edge [arrowhead="boxvee"] 31 | {% for in in module.get_in_ports() %} 32 | {{ in.name }} -> mapcam:{{ in.name }} [{% if in.type == "Reg" %}arrowhead="oboxvee"{% endif %} label = {{ in.width }}] 33 | {% endfor %} 34 | 35 | // outputs 36 | edge [dir=both arrowhead="vee" arrowtail="box"] 37 | {% for out in module.get_out_ports() %} 38 | mapcam:{{ out.name }} -> {{ out.name }} [{% if out.type == "Reg" %}arrowtail="obox"{% endif %} label = {{ out.width }}] 39 | {% endfor %} 40 | } 41 | 42 | -------------------------------------------------------------------------------- /docs/verilog_module.py: -------------------------------------------------------------------------------- 1 | import jinja2 2 | templateLoader = jinja2.FileSystemLoader( searchpath="./") 3 | templateEnv = jinja2.Environment( loader=templateLoader ) 4 | 5 | class module(): 6 | def __init__(self): 7 | self.ports = [] 8 | self.name = None 9 | 10 | def set_name(self, name): 11 | self.name = name 12 | 13 | def add_port(self, name, direction, type, width): 14 | print("adding port %s %s %s %s" % (name, direction, type, width)) 15 | self.ports.append({ 'direction' : direction, 'name': name, 'type' : type, 'width': width }) 16 | 17 | def get_in_ports(self): 18 | return [ p for p in self.ports if p['direction'] == 'Input' ] 19 | 20 | def get_out_ports(self): 21 | return [ p for p in self.ports if p['direction'] == 'Output' ] 22 | 23 | # provide zipped ports for jinja for loop 24 | def zip_ports(self): 25 | # equalize length of lists first 26 | len_diff = len(self.get_in_ports()) - len(self.get_out_ports()) 27 | print(len_diff) 28 | if len_diff > 0: 29 | return zip(self.get_in_ports(), self.get_out_ports() + [None] * len_diff) 30 | else: 31 | return zip(self.get_in_ports() + [None] * abs(len_diff), self.get_out_ports()) 32 | 33 | def render(self, template_file): 34 | template = templateEnv.get_template(template_file) 35 | return template.render(module=self) 36 | 37 | if __name__ == '__main__': 38 | 39 | mod = module('matts module') 40 | mod.add_port('clk', 'Input', 'wire', 1 ) 41 | mod.add_port('reset', 'Input', 'wire', 1 ) 42 | mod.add_port('x', 'Output', 'reg', 10 ) 43 | print(mod.render("port_template.dot")) 44 | -------------------------------------------------------------------------------- /tests/i2c_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | wire LED1; 4 | wire LED2; 5 | wire LED3; 6 | wire LED4; 7 | wire LED5; 8 | 9 | wire PIO0_02; 10 | wire PIO0_03; 11 | wire PIO0_04; 12 | wire PIO0_05; 13 | wire PIO0_06; 14 | wire PIO0_07; 15 | wire PIO0_08; 16 | wire PIO0_09; 17 | 18 | reg clk = 0; 19 | wire i2c_sda; 20 | wire i2c_scl; 21 | reg i2c_start = 0; 22 | reg reset = 0; 23 | reg button = 0; 24 | wire [8:0] pos; 25 | reg deb1 = 0; 26 | wire debounced; 27 | 28 | wire[10:0] x; 29 | wire[10:0] y; 30 | 31 | /* assign PIO0_02 = x[9]; 32 | assign PIO0_03 = x[8]; 33 | assign PIO0_04 = x[7]; 34 | assign PIO0_05 = x[6]; 35 | assign PIO0_06 = x[5]; 36 | assign PIO0_07 = x[4]; 37 | assign PIO0_08 = x[3]; 38 | assign PIO0_09 = x[2]; 39 | */ 40 | 41 | debounce db1(.clk (clk), .button (button), .debounced (debounced)); 42 | 43 | camera cam(.clk (clk), .reset (reset), .i2c_scl(i2c_scl), .i2c_sda(i2c_sda), .start(i2c_start) ); 44 | 45 | xy_leds leds(.x(x), .y(y), .LED1(LED1), .LED2(LED2),.LED3(LED3),.LED4(LED4),.LED5(LED5)); 46 | 47 | /* Make a reset that pulses once. */ 48 | initial begin 49 | $dumpfile("test.vcd"); 50 | $dumpvars(0,test); 51 | # 3 reset = 0; 52 | //wait (i2c_ready == 1); 53 | # 20 button = 0; 54 | # 21 button = 1; 55 | # 20 button = 0; 56 | # 3600; 57 | $finish; 58 | end 59 | 60 | always@(posedge clk) begin 61 | deb1 <= debounced; 62 | if(debounced & ~ deb1) 63 | i2c_start <= 1; 64 | else 65 | i2c_start <= 0; 66 | end 67 | 68 | /* Make a regular pulsing clock. */ 69 | always #1 clk = !clk; 70 | 71 | endmodule // test 72 | -------------------------------------------------------------------------------- /tests/gtk-vga-sram.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Sun Sep 17 12:41:05 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/test.vcd" 6 | [dumpfile_mtime] "Sun Sep 17 12:39:56 2017" 7 | [dumpfile_size] 4286 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/gtk-vga-sram.gtkw" 9 | [timestart] 0 10 | [size] 1600 1148 11 | [pos] 0 0 12 | *-4.000000 36 -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 13 | [treeopen] test. 14 | [treeopen] test.pb. 15 | [sst_width] 263 16 | [signals_width] 360 17 | [sst_expanded] 1 18 | [sst_vpaned_height] 348 19 | @28 20 | test.pb.reset 21 | test.pb.clk 22 | test.erase 23 | @24 24 | test.x[9:0] 25 | test.y[9:0] 26 | @200 27 | - 28 | -pix buf 29 | @22 30 | test.pb.pixels[7:0] 31 | test.pb.pixel_buf[7:0] 32 | @24 33 | test.pb.hcounter[10:0] 34 | test.pb.vcounter[9:0] 35 | @28 36 | test.vga_test.reset 37 | @22 38 | test.vga_test.hcounter[10:0] 39 | test.vga_test.vcounter[9:0] 40 | @24 41 | test.sram_test.address[17:0] 42 | @2023 43 | ^1 /home/mattvenn/work/fpga/virtual-graffiti/pix_buf_state_filter.txt 44 | test.pb.ram_state[1:0] 45 | @200 46 | - 47 | -sram 48 | @2022 49 | ^2 /home/mattvenn/work/fpga/virtual-graffiti/sram_state_filter.txt 50 | test.sram_test.state[2:0] 51 | @28 52 | test.sram_test.wait_count[1:0] 53 | @22 54 | test.sram_test.address_pins[17:0] 55 | @28 56 | test.sram_test.ready 57 | test.sram_test.read 58 | test.sram_test.write 59 | test.sram_test.write_enable 60 | test.sram_test.output_enable 61 | test.sram_test.data_pins_out_en 62 | @22 63 | test.sram_test.data_read_reg[15:0] 64 | test.sram_test.data_write_reg[15:0] 65 | @200 66 | - 67 | -vga 68 | @22 69 | test.vga_test.pixels[7:0] 70 | [pattern_trace] 1 71 | [pattern_trace] 0 72 | -------------------------------------------------------------------------------- /tests/sram_vga_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | reg clk = 0; 4 | reg vga_clk = 0; 5 | wire hsync; 6 | wire vsync; 7 | wire [7:0] pixels; 8 | reg reset = 1; 9 | 10 | wire [17:0] address; 11 | wire [15:0] data_read; 12 | wire [15:0] data_write; 13 | reg [9:0] x; 14 | reg [9:0] y; 15 | reg [15:0] data_pins_in; 16 | wire read; 17 | reg erase = 0; 18 | wire write; 19 | wire ready; 20 | 21 | wire [10:0] hcounter; 22 | wire [9:0] vcounter; 23 | wire [3:0] pb_state; 24 | 25 | initial begin 26 | $dumpfile("test.vcd"); 27 | $dumpvars(0, test); 28 | # 1 data_pins_in = 0; 29 | # 1 reset <= 1; 30 | # 8 reset <= 0; 31 | # 4000 32 | $dumpoff; 33 | 34 | // wait for camera write 35 | wait(vcounter == 479 && hcounter == 780); 36 | # 1 x <= 50; 37 | # 1 y <= 50; 38 | $dumpon; 39 | 40 | // press the erase button and skip to the end of the displayable screen 41 | wait(vcounter == 480 && hcounter == 780); 42 | # 1 erase <= 1; 43 | $dumpon; 44 | # 1000 45 | $finish; 46 | end 47 | 48 | 49 | wire [10:0] tester; 50 | assign tester = hcounter[3:0]; 51 | vga vga_test(.reset(reset), .pixels(pixels), .clk(vga_clk), .hsync(hsync), .vsync(vsync), .blank(blank), .hcounter(hcounter), .vcounter(vcounter)); 52 | 53 | sram sram_test(.clk(vga_clk), .address(address), .data_read(data_read), .data_write(data_write), .write(write), .read(read), .reset(reset), .ready(ready), .data_pins_in(data_pins_in), .OE(OE), .CS(CS), .WE(WE), .data_pins_out_en(data_pins_out_en)); 54 | 55 | pixel_buffer pb(.clk(vga_clk), .reset(reset), .address(address), .data_read(data_read), .read(read), .ready(ready), .pixels(pixels), .hcounter(hcounter), .vcounter(vcounter)); 56 | 57 | /* Make a regular pulsing clock. */ 58 | always #1 vga_clk = !vga_clk; // 25 mhz 59 | // always #1 clk = !clk; //100 mhz 60 | 61 | endmodule // test 62 | 63 | -------------------------------------------------------------------------------- /src/pixel_buffer.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module pixel_buffer( 3 | input wire clk, 4 | input wire reset, 5 | input wire ready, 6 | 7 | output reg [17:0] address, 8 | input wire [15:0] data_read, 9 | output reg read, 10 | 11 | output reg [7:0] pixels, 12 | input wire [10:0] hcounter, 13 | input wire [9:0] vcounter 14 | ); 15 | 16 | reg [1:0] ram_state = STATE_IDLE; 17 | reg [7:0] line_buffer_index; // offset into memory for each block of 8 pixels 18 | 19 | // SRAM buffer state machine // 7654 on the pmod tek adapter 20 | localparam STATE_IDLE = 0; // 0000 21 | localparam STATE_READ = 1; // 0001 22 | localparam STATE_READ_WAIT = 2; // 0010 23 | 24 | always @(posedge clk) begin 25 | if( reset == 1 ) begin 26 | ram_state <= STATE_IDLE; 27 | end 28 | else begin 29 | case(ram_state) 30 | STATE_IDLE: begin 31 | ram_state <= STATE_IDLE; 32 | read <= 0; 33 | address <= 0; 34 | 35 | if(hcounter == 0) 36 | line_buffer_index <= 0; // reset counter 37 | if(hcounter[2:0] == 4'b111) 38 | pixels <= data_read[7:0]; // update the output from the buffer - bit 13 is not working, so only use lower byte 39 | if(hcounter[2:0] == 4'b000 && vcounter < 480 && hcounter < 640) begin // at the end of the visible line 40 | ram_state <= STATE_READ; // read the next line of buffer from sram into bram 41 | end 42 | end 43 | STATE_READ: begin 44 | if(ready) begin 45 | line_buffer_index <= line_buffer_index + 1; 46 | address <= line_buffer_index + vcounter * 80; 47 | ram_state <= STATE_READ_WAIT; 48 | end 49 | end 50 | STATE_READ_WAIT: begin 51 | ram_state <= STATE_IDLE; 52 | read <= 1; 53 | end 54 | default: ram_state <= STATE_IDLE; 55 | endcase 56 | end 57 | end 58 | 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /src/bresenham.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module bresenham ( 3 | input wire clk, 4 | input wire clk_en, 5 | input wire reset, 6 | input wire start, 7 | input wire [9:0] x0, 8 | input wire [9:0] y0, 9 | input wire [9:0] x1, 10 | input wire [9:0] y1, 11 | output reg plot, 12 | output reg [9:0] x, 13 | output reg [9:0] y, 14 | output reg done); 15 | 16 | reg [2:0] state; 17 | reg signed [10:0] dx; // one more than input register for the sign bit 18 | reg signed [10:0] dy; 19 | reg signed [10:0] sx; 20 | reg signed [10:0] sy; 21 | reg signed [10:0] err; 22 | reg signed [11:0] err2; // has to be twice as large as err reg 23 | 24 | localparam STATE_IDLE = 0; 25 | localparam STATE_PLOT = 1; 26 | 27 | always @(posedge clk) begin 28 | if(reset) begin 29 | done <= 0; 30 | plot <= 0; 31 | state <= STATE_IDLE; 32 | end 33 | if(clk_en) case(state) 34 | STATE_IDLE: begin 35 | done <= 0; 36 | if(start) begin 37 | dx = x0 - x1; // blocking 38 | dy = y0 - y1; 39 | if(dx < 0) dx = -dx; 40 | if(dy < 0) dy = -dy; 41 | sx = x0 < x1 ? 1 : -1; 42 | sy = y0 < y1 ? 1 : -1; 43 | err = dx - dy; 44 | x <= x0; 45 | y <= y0; 46 | plot <= 1; 47 | state <= STATE_PLOT; 48 | end 49 | end 50 | STATE_PLOT: begin 51 | if(x == x1 && y == y1 ) begin 52 | done <= 1; 53 | state <= STATE_IDLE; 54 | end else begin 55 | err2 = err << 2; 56 | if(err2 > -dy) begin 57 | err = err - dy; 58 | x <= x + sx; 59 | end 60 | if (err2 < dx) begin 61 | err = err + dx; 62 | y <= y + sy; 63 | end 64 | end 65 | end 66 | default: 67 | state <= STATE_IDLE; 68 | endcase 69 | end 70 | 71 | endmodule 72 | -------------------------------------------------------------------------------- /tests/gtk-sram_vga_line.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI 3 | [*] Wed Oct 11 17:53:02 2017 4 | [*] 5 | [dumpfile] "/home/mattvenn/work/fpga/virtual-graffiti/build/sram_vga_line.vcd" 6 | [dumpfile_mtime] "Wed Oct 11 17:52:38 2017" 7 | [dumpfile_size] 3465 8 | [savefile] "/home/mattvenn/work/fpga/virtual-graffiti/tests/gtk-sram_vga_line.gtkw" 9 | [timestart] 767345 10 | [size] 1600 1148 11 | [pos] -1 -1 12 | *-8.000000 768229 -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 13 | [treeopen] test. 14 | [sst_width] 263 15 | [signals_width] 392 16 | [sst_expanded] 1 17 | [sst_vpaned_height] 348 18 | @28 19 | test.vga_clk 20 | test.reset 21 | test.lower_blank 22 | test.start_write 23 | test.read 24 | test.pb_read 25 | test.wb_read 26 | test.write_buf_clk_en 27 | @200 28 | - 29 | -line 30 | @2022 31 | ^1 /home/mattvenn/work/fpga/virtual-graffiti/tests/bresenham_state_filter.txt 32 | test.wb.line.state[2:0] 33 | @28 34 | test.wb.line.start 35 | test.wb.line.done 36 | @22 37 | test.wb.line.x0[9:0] 38 | test.wb.line.y0[9:0] 39 | @24 40 | test.wb.line.x[9:0] 41 | test.wb.line.y[9:0] 42 | test.wb.line.x1[9:0] 43 | test.wb.line.y1[9:0] 44 | @200 45 | - 46 | -pixel buf 47 | @2022 48 | ^2 /home/mattvenn/work/fpga/virtual-graffiti/tests/pix_buf_state_filter.txt 49 | test.pb.ram_state[1:0] 50 | @28 51 | test.pb.read 52 | @200 53 | - 54 | -write_buf 55 | @28 56 | test.wb.clk_en 57 | test.wb.clk 58 | test.wb.erase 59 | @24 60 | test.wb.address[17:0] 61 | @28 62 | test.wb.start 63 | @22 64 | test.wb.data_write[15:0] 65 | @28 66 | test.wb.cam_valid 67 | test.wb.last_invalid 68 | @2025 69 | ^3 /home/mattvenn/work/fpga/virtual-graffiti/tests/write_buf_state_filter.txt 70 | test.wb.state[4:0] 71 | @28 72 | test.wb.ram_read 73 | test.wb.ram_write 74 | test.wb.ram_ready 75 | @200 76 | - 77 | -vga 78 | @24 79 | test.vga_test.vcounter[9:0] 80 | @22 81 | test.vga_test.hcounter[10:0] 82 | test.vga_test.pixels[7:0] 83 | @200 84 | - 85 | -sram 86 | @22 87 | test.sram_test.data_write[15:0] 88 | test.sram_test.address[17:0] 89 | @2022 90 | ^4 /home/mattvenn/work/fpga/virtual-graffiti/tests/sram_state_filter.txt 91 | test.sram_test.state[2:0] 92 | @28 93 | test.sram_test.ready 94 | test.sram_test.read 95 | test.sram_test.write 96 | test.sram_test.CS 97 | test.sram_test.WE 98 | [pattern_trace] 1 99 | [pattern_trace] 0 100 | -------------------------------------------------------------------------------- /docs/ports_to_svg.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | import sys 4 | import os 5 | from optparse import OptionParser 6 | 7 | # verilog parsing 8 | import pyverilog.utils.version 9 | from pyverilog.vparser.parser import parse 10 | import verilog_module 11 | 12 | 13 | def main(): 14 | INFO = "Verilog code parser" 15 | VERSION = pyverilog.utils.version.VERSION 16 | USAGE = "Usage: python example_parser.py file ..." 17 | 18 | def showVersion(): 19 | print(INFO) 20 | print(VERSION) 21 | print(USAGE) 22 | sys.exit() 23 | 24 | optparser = OptionParser() 25 | optparser.add_option("-v","--version",action="store_true",dest="showversion", 26 | default=False,help="Show the version") 27 | optparser.add_option("-I","--include",dest="include",action="append", 28 | default=[],help="Include path") 29 | optparser.add_option("-D",dest="define",action="append", 30 | default=[],help="Macro Definition") 31 | (options, args) = optparser.parse_args() 32 | 33 | filelist = args 34 | if options.showversion: 35 | showVersion() 36 | 37 | for f in filelist: 38 | if not os.path.exists(f): raise IOError("file not found: " + f) 39 | 40 | if len(filelist) == 0: 41 | showVersion() 42 | 43 | ast, directives = parse(filelist, 44 | preprocess_include=options.include, 45 | preprocess_define=options.define) 46 | 47 | module = verilog_module.module() 48 | show(ast, module) 49 | with open('out.dot', 'w' ) as fh: 50 | fh.write(module.render("docs/port_template.dot")) 51 | 52 | 53 | def get_io_port(ch, module): 54 | children = ch.children() 55 | direction = children[0].__class__.__name__ 56 | name = children[0].name 57 | type = children[1].__class__.__name__ 58 | try: 59 | width = children[0].width.children()[0] 60 | except AttributeError: 61 | width = 1 62 | module.add_port(name, direction, type, width ) 63 | 64 | def show(ch, module): 65 | if(ch.__class__ == pyverilog.vparser.ast.Ioport): 66 | get_io_port(ch, module) 67 | if(ch.__class__ == pyverilog.vparser.ast.ModuleDef): 68 | module.set_name(ch.name) 69 | 70 | for i in ch.children(): 71 | show(i, module) 72 | 73 | if __name__ == '__main__': 74 | main() 75 | -------------------------------------------------------------------------------- /tests/sram_vga_line_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | reg clk = 0; 4 | reg vga_clk = 0; 5 | wire hsync; 6 | wire vsync; 7 | wire [7:0] pixels; 8 | reg reset = 1; 9 | 10 | reg [17:0] address; 11 | wire [15:0] data_read; 12 | wire [15:0] data_write; 13 | wire lower_blank; 14 | reg [9:0] cam_x; 15 | reg [9:0] cam_y; 16 | reg [15:0] data_pins_in; 17 | reg read; 18 | reg erase = 0; 19 | reg cam_valid = 0; 20 | wire write; 21 | wire ready; 22 | 23 | wire [10:0] hcounter; 24 | wire [9:0] vcounter; 25 | wire [1:0] pb_state; 26 | 27 | reg start = 0; 28 | 29 | initial begin 30 | $dumpfile("test.vcd"); 31 | $dumpvars(0, test); 32 | # 1 data_pins_in = 0; 33 | # 1 reset <= 1; 34 | # 8 reset <= 0; 35 | 36 | $dumpoff; 37 | // wait for screen blank 38 | //# 1 erase <= 1; 39 | wait(vcounter == 479 && hcounter == 790); 40 | $dumpon; 41 | # 1 cam_x <= 639; 42 | # 1 cam_y <= 479; 43 | # 1 cam_valid <= 1; 44 | wb.last_invalid <= 0; // don't want to have to wait for a screen redraw 45 | wait(start_write == 1); 46 | // wait(wb.line_done == 1); 47 | # 500 48 | $finish; 49 | end 50 | 51 | 52 | wire [10:0] tester; 53 | assign tester = hcounter[3:0]; 54 | vga vga_test(.reset(reset), .pixels(pixels), .clk(vga_clk), .hsync(hsync), .vsync(vsync), .blank(blank), .hcounter(hcounter), .vcounter(vcounter), .lower_blank(lower_blank)); 55 | 56 | sram sram_test(.clk(vga_clk), .address(address), .data_read(data_read), .data_write(data_write), .write(write), .read(read), .reset(reset), .ready(ready), .data_pins_in(data_pins_in), .OE(OE), .CS(CS), .WE(WE), .data_pins_out_en(data_pins_out_en)); 57 | 58 | pixel_buffer pb(.clk(vga_clk), .reset(reset), .address(pb_address), .data_read(data_read), .read(pb_read), .ready(ready), .pixels(pixels), .hcounter(hcounter), .vcounter(vcounter)); 59 | 60 | write_buffer wb(.clk(vga_clk), .cam_valid(cam_valid), .reset(reset), .address(wb_address), .data_read(data_read), .ram_read(wb_read), .ram_ready(ready), .data_write(data_write), .ram_write(write), .erase(erase), .cam_x(cam_x), .cam_y(cam_y), .start(start_write), .clk_en(write_buf_clk_en)); 61 | 62 | reg start_write; 63 | reg write_buf_clk_en; 64 | wire wb_read, pb_read; 65 | wire [17:0] pb_address; 66 | wire [17:0] wb_address; 67 | always @(posedge vga_clk) 68 | start_write <= vcounter == 480 && hcounter == 0; 69 | 70 | // mux 71 | always @(posedge vga_clk) begin 72 | if( vcounter > 479 ) begin 73 | read <= wb_read; 74 | address <= wb_address; 75 | write_buf_clk_en <= 1; 76 | end else begin 77 | read <= pb_read; 78 | address <= pb_address; 79 | write_buf_clk_en <= 0; 80 | end 81 | end 82 | 83 | /* Make a regular pulsing clock. */ 84 | always #1 vga_clk = !vga_clk; // 25 mhz 85 | // always #1 clk = !clk; //100 mhz 86 | 87 | endmodule // test 88 | 89 | -------------------------------------------------------------------------------- /docs/line.py: -------------------------------------------------------------------------------- 1 | #http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm#Python 2 | def get_line_1(start, end): 3 | """Bresenham's Line Algorithm 4 | Produces a list of tuples from start and end 5 | 6 | """ 7 | # Setup initial conditions 8 | x1, y1 = start 9 | x2, y2 = end 10 | dx = x2 - x1 11 | dy = y2 - y1 12 | 13 | # Determine how steep the line is 14 | is_steep = abs(dy) > abs(dx) 15 | 16 | # Rotate line 17 | if is_steep: 18 | x1, y1 = y1, x1 19 | x2, y2 = y2, x2 20 | 21 | # Swap start and end points if necessary and store swap state 22 | swapped = False 23 | if x1 > x2: 24 | x1, x2 = x2, x1 25 | y1, y2 = y2, y1 26 | swapped = True 27 | 28 | # Recalculate differentials 29 | dx = x2 - x1 30 | dy = y2 - y1 31 | 32 | # Calculate error 33 | error = int(dx / 2.0) 34 | ystep = 1 if y1 < y2 else -1 35 | 36 | # Iterate over bounding box generating points between start and end 37 | y = y1 38 | points = [] 39 | for x in range(x1, x2 + 1): 40 | coord = (y, x) if is_steep else (x, y) 41 | points.append(coord) 42 | error -= abs(dy) 43 | if error < 0: 44 | y += ystep 45 | error += dx 46 | 47 | # Reverse the list if the coordinates were swapped 48 | if swapped: 49 | points.reverse() 50 | return points 51 | 52 | ## integer version 53 | def get_line(start, end): 54 | points = [] 55 | 56 | # dx calc 57 | dx = abs(start[0] - end[0]) 58 | dy = abs(start[1] - end[1]) 59 | 60 | # slope calc 61 | if start[0] < end[0]: 62 | sx = 1 63 | else: 64 | sx = -1 65 | if start[1] < end[1]: 66 | sy = 1 67 | else: 68 | sy = -1 69 | 70 | err = dx - dy 71 | 72 | x = start[0] 73 | y = start[1] 74 | 75 | while True: 76 | points.append((x,y)) 77 | if x == end[0] and y == end[1]: 78 | break 79 | 80 | err2 = err << 2 # left shift faster than multiply by 2 81 | 82 | if err2 > -dy: 83 | err -= dy 84 | x += sx 85 | 86 | if err2 < dx: 87 | err += dx 88 | y += sy 89 | 90 | return points 91 | 92 | 93 | 94 | from PIL import Image, ImageDraw 95 | 96 | w= 500 97 | h= 500 98 | 99 | #create an image 100 | im = Image.new("RGB", (w,h), "white") 101 | 102 | num = 8 103 | 104 | y = 0 105 | for x in range(0, w-1, w/num): 106 | for point in get_line((w/2,h/2), (x, y)): 107 | im.putpixel(point, 255) 108 | 109 | y = h-1 110 | for x in range(0, w-1, w/num): 111 | for point in get_line((w/2,h/2), (x, y)): 112 | im.putpixel(point, 255) 113 | 114 | x = 0 115 | for y in range(0, h-1, h/num): 116 | for point in get_line((w/2,h/2), (x, y)): 117 | im.putpixel(point, 255) 118 | 119 | x = w -1 120 | for y in range(0, h-1, h/num): 121 | for point in get_line((w/2,h/2), (x, y)): 122 | im.putpixel(point, 255) 123 | 124 | #save the image 125 | im.save("lines.png", "PNG") 126 | 127 | -------------------------------------------------------------------------------- /src/vga.v: -------------------------------------------------------------------------------- 1 | /* 2 | generate test pattern at 640 x 480 @ 60Hz 3 | 4 | total pixels is 800 x 525 @ 60Hz = 25.2Mhz = 39.6ns 5 | 6 | Timings from : 7 | 8 | * http://hamsterworks.co.nz/mediawiki/index.php/VGA_timings 9 | * http://web.mit.edu/6.111/www/s2004/NEWKIT/vga.shtml 10 | 11 | code adapted from VHDL : 12 | 13 | * http://hamsterworks.co.nz/mediawiki/index.php/FPGA_VGA 14 | * http://hamsterworks.co.nz/mediawiki/index.php/Dvid_test#vga.vhd 15 | 16 | Horizontal Timing 17 | 640 h visible 18 | 16 front 19 | 96 sync 20 | 48 back 21 | 800 whole 22 | - hsync 23 | 24 | Vertical Timing 25 | 26 | 480 v visible 27 | 10 front 28 | 2 sync 29 | 33 back 30 | 525 whole 31 | - vsync 32 | 33 | 45 blank lines at the bottom, 800 pix wide = 36k clocks for other things 34 | 35 | */ 36 | `default_nettype none 37 | module vga ( 38 | input wire clk, 39 | input wire reset, 40 | input wire [7:0] pixels, 41 | output reg [2:0] red, 42 | output reg [2:0] green, 43 | output reg [2:0] blue, 44 | output reg [10:0] hcounter, 45 | output reg [9:0] vcounter, 46 | output reg hsync, 47 | output reg vsync, 48 | output reg blank, 49 | output reg lower_blank 50 | ); 51 | 52 | localparam border_w = 10; 53 | 54 | always@(hcounter or vcounter) begin // results in a note about combinatorial logic 55 | // black everywhere 56 | red <= 3'b000; 57 | green <= 3'b000; 58 | blue <= 3'b000; 59 | 60 | // sync 61 | hsync <= 1'b1; 62 | vsync <= 1'b1; 63 | blank <= 1'b0; 64 | lower_blank <= 1'b0; 65 | 66 | // sync pulses 67 | if(hcounter > 655 && hcounter < 751) 68 | hsync <= 1'b0; 69 | if(vcounter > 489 && vcounter < 491) 70 | vsync <= 1'b0; 71 | // blank is whenever outside of viewable area 72 | if(hcounter > 639 || vcounter > 479) 73 | blank <= 1'b1; 74 | if(vcounter > 479 ) 75 | lower_blank <= 1'b1; 76 | 77 | // top and bottom border 78 | if(vcounter < border_w || ( vcounter > 480 - border_w && vcounter < 480)) begin 79 | red <= 3'b111; 80 | green <= 3'b000; 81 | blue <= 3'b111; 82 | end else // left and right border 83 | if(hcounter < border_w || ( hcounter > 640 - border_w && hcounter < 640)) begin 84 | red <= 3'b111; 85 | green <= 3'b000; 86 | blue <= 3'b111; 87 | end else // data from pixel register 88 | if(pixels[hcounter]) begin 89 | red <= 3'b000; 90 | green <= 3'b111; 91 | blue <= 3'b111; 92 | end 93 | 94 | end 95 | 96 | // increment counters and wrap them 97 | always@(posedge clk) begin 98 | if(reset == 1) begin 99 | hcounter <= 0; 100 | vcounter <= 0; 101 | end else if(hcounter == 799) begin 102 | hcounter <= 0; 103 | if(vcounter == 524) begin 104 | vcounter <= 0; 105 | end else 106 | vcounter <= vcounter + 1; 107 | end 108 | else 109 | hcounter <= hcounter + 1; 110 | end 111 | endmodule 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPGA Virtual Graffiti 2 | 3 | ![overview](docs/overview.png) 4 | 5 | [videos and construction photos](https://photos.app.goo.gl/kivlfcmlp4oecVpu1) 6 | 7 | # Tools used 8 | 9 | * [icestorm](http://www.clifford.at/icestorm/) opensource FPGA tools. 10 | * [mystorm](https://mystorm.uk/) open hardware FPGA development board 11 | * [gtkwave](http://gtkwave.sourceforge.net/) for debugging. 12 | 13 | # Top resource tips 14 | 15 | * [Obijuan's FPGA tutorial](https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki) 16 | * [FPGAwars forum](https://groups.google.com/forum/#!forum/fpga-wars-explorando-el-lado-libre) 17 | * [Dan's FPGA blog](http://www.zipcpu.com/) 18 | 19 | # Documentation 20 | 21 | * [system overview diagram](docs/module_overview.svg) 22 | * Yosys can generate output graphs of the verilog with the [show](http://www.clifford.at/yosys/cmd_show.html) command. 23 | * [schematic for mystorm](https://gitlab.com/Folknology/mystorm/blob/BlackIce/BlackIce-schematic.pdf) 24 | * [ICEfloorplan](https://knielsen.github.io/ice40_viewer/ice40_viewer.html) can be used to show how the design is laid out on the FPGA 25 | * [All Verilog source](src) and [tests](tests) 26 | 27 | # Build notes 28 | 29 | ## Synthesis 30 | 31 | make 32 | 33 | To program the mystorm board, first start a terminal listening on /dev/ttyUSBX 34 | at 115200 baud, and reset the board. Then type: 35 | 36 | make prog 37 | 38 | ## Tests 39 | 40 | many test benches are in [tests](tests). They can be simulated and outputs 41 | viewed with gtkwave: 42 | 43 | make debug-[name of verilog file] 44 | 45 | eg 46 | 47 | make debug-bresenham 48 | 49 | ## Storing configuration on the board 50 | 51 | [Instructions 52 | here](https://forum.mystorm.uk/t/config-from-non-voltatile-memory/242/2) 53 | 54 | ## SRAM video buffer 55 | 56 | Using the SRAM on the back of the board for persistant graffitis. This caused 2 57 | major issues: 58 | 59 | * [PLL and SRAM pins collide on the board layout](https://forum.mystorm.uk/t/placement-conflict-between-sb-io-for-ram-and-pll/224/12) 60 | * [switching the SB_IO pins and SRAM pins at the same time](https://forum.mystorm.uk/t/fpga-unreliability-crashing-hanging/252/19) caused instability. 61 | 62 | ## Wiimote Camera 63 | 64 | * (breakout board)[https://github.com/mattvenn/kicad/tree/master/wiimote-fpga) 65 | * 25mhz supplied on clock pin 66 | * reset high to run 67 | * wiimote camera PCB was tested with branch wii-pcb 68 | 69 | ## I2C reader / writer 70 | 71 | ![fpga read](docs/fpga-i2c-read.png) 72 | 73 | Started off with this youtube series:https://www.youtube.com/watch?v=rWzB5hZlqBA 74 | by Tom Briggs. 75 | 76 | In Tom's design, the I2C clock is assigned to the state machine's !clk. 77 | 78 | Writing and requesting data was easy, but reading the data was difficult to 79 | synchronize the clock. I then tried 2 different approaches: 80 | 81 | * separating the I2C clock and state machine clock to give more time for reading 82 | data (4 state machine clocks for 1 I2C clock) 83 | * generating the clock within the state machine itself. 84 | 85 | Option 2 proved much easier to write. I also found this [brief Q&A on reddit on 86 | the same topic](https://m.reddit.com/r/FPGA/comments/4oltue/when_writing_communication_protocols_spi_i2c_etc/) 87 | 88 | ## DVI output 89 | 90 | based on [Hamster's minimal DVI-D 91 | VHDL](http://hamsterworks.co.nz/mediawiki/index.php/Minimal_DVI-D) 92 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEVICE = hx8k 2 | SRC_DIR = src 3 | TEST_DIR = tests 4 | DOCS_DIR = docs 5 | SVG_DIR = $(DOCS_DIR)/svg 6 | SVG_PORT_DIR = $(DOCS_DIR)/module_port_svg 7 | BUILD_DIR = build 8 | PROJ = $(BUILD_DIR)/vgraf 9 | PIN_DEF = $(SRC_DIR)/blackice.pcf 10 | SHELL := /bin/bash # Use bash syntax 11 | 12 | MODULES = i2c_master.v camera.v xy_leds.v dvid.v vga.v clockdiv.v sram.v pixel_buffer.v write_buffer.v bresenham.v map_cam.v pulse.v 13 | VERILOG = top.v $(MODULES) 14 | SRC = $(addprefix $(SRC_DIR)/, $(VERILOG)) 15 | 16 | all: $(PROJ).bin $(PROJ).rpt 17 | mod_svg: $(patsubst %.v,$(SVG_DIR)/%.svg,$(MODULES)) 18 | port_svg: $(patsubst %.v,$(SVG_PORT_DIR)/%.svg,$(MODULES)) 19 | 20 | # $@ The file name of the target of the rule.rule 21 | # $< first pre requisite 22 | # $^ names of all preerquisites 23 | 24 | # A3 = 297 x 420mm. 300dpi ~ 12 pix per mm. size in pixels is 3500 x 4960 25 | %.png: %.svg 26 | convert -density 300 -resize 4960 $< $@ 27 | 28 | # export ps from vim: :hardcopy > file.ps 29 | # split multipage ps: gs -dBATCH -dNOPAUSE -sDEVICE=ps2write -sOutputFile=vga%03d.ps vga.ps 30 | %.png: %.ps 31 | convert -background "#FFFFFF" -flatten -density 300 -resize 4960x3500 $< $@ 32 | 33 | # rule for building svg graphs of the modules 34 | $(SVG_DIR)/%.svg: $(SRC_DIR)/%.v 35 | yosys -p "read_verilog $<; proc; opt; show -colors 2 -width -signed -format svg -prefix $(basename $@)" 36 | 37 | # rule for building svg version of module ports 38 | $(SVG_PORT_DIR)/%.svg: $(SRC_DIR)/%.v 39 | python $(DOCS_DIR)/ports_to_svg.py $^ 40 | dot -Tsvg out.dot -o $@ 41 | # rm out.dot 42 | 43 | # rules for building the blif file 44 | $(BUILD_DIR)/%.blif: $(SRC) 45 | yosys -p "synth_ice40 -top top -blif $@" $^ 46 | 47 | # asc 48 | $(BUILD_DIR)/%.asc: $(PIN_DEF) $(BUILD_DIR)/%.blif 49 | arachne-pnr --device 8k --package tq144:4k -o $@ -p $^ 50 | 51 | # bin, for programming 52 | $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.asc 53 | icepack $< $@ 54 | 55 | # timing 56 | $(BUILD_DIR)/%.rpt: $(BUILD_DIR)/%.asc 57 | icetime -d $(DEVICE) -mtr $@ $< 58 | 59 | # rules for simple tests with one verilog module per test bench 60 | $(BUILD_DIR)/%.out: $(TEST_DIR)/%_tb.v $(SRC_DIR)/%.v 61 | iverilog -o $(basename $@).out $^ 62 | 63 | $(BUILD_DIR)/%.vcd: $(BUILD_DIR)/%.out 64 | vvp $< -fst 65 | mv test.vcd $@ 66 | 67 | debug-%: $(BUILD_DIR)/%.vcd $(TEST_DIR)/gtk-%.gtkw 68 | gtkwave $^ 69 | 70 | # more complicated tests that need multiple modules per test 71 | $(BUILD_DIR)/camera.out: $(TEST_DIR)/camera_tb.v $(SRC_DIR)/camera.v $(SRC_DIR)/i2c_master.v 72 | iverilog -o $(basename $@).out $^ 73 | 74 | $(BUILD_DIR)/sram_vga_line.out: $(TEST_DIR)/sram_vga_line_tb.v $(SRC_DIR)/sram.v $(SRC_DIR)/vga.v $(SRC_DIR)/bresenham.v $(SRC_DIR)/pixel_buffer.v $(SRC_DIR)/write_buffer.v 75 | iverilog -o $(basename $@).out $^ 76 | 77 | debug-sram-vga: 78 | iverilog -o vga-sram sram_vga_tb.v sram.v vga.v pixel_buffer.v 79 | vvp vga-sram -fst 80 | gtkwave test.vcd gtk-vga-sram.gtkw 81 | 82 | debug-i2c: 83 | iverilog -o i2c i2c_tb.v camera.v i2c_master.v button.v xy_leds.v 84 | vvp i2c -fst 85 | gtkwave test.vcd gtk-i2c.gtkw 86 | 87 | debug-master: 88 | iverilog -o i2c i2c_master_tb.v i2c_master.v 89 | vvp i2c -fst 90 | gtkwave test.vcd gtk-master.gtkw 91 | 92 | 93 | $(PROJ).size: $(PROJ).bin 94 | du -b $< | cut -f1 > $@ 95 | 96 | $(PROJ)-even.bin: $(PROJ).size $(PROJ).bin 97 | cp $(PROJ).bin $(PROJ)-even.bin 98 | size=`cat $(PROJ).size`; truncate -s $$(echo $$size + 4 - $$size % 4 | bc) $(PROJ)-even.bin 99 | 100 | perma-prog: $(PROJ)-even.bin 101 | read -p "plug central USB, remove link between 14&16, press reset on board, then press enter" 102 | sudo dfu-util -d 0483:df11 -s 0x0801F000 -D $(PROJ)-even.bin --alt 0 -t 1024 103 | read -p "replace link and reset" 104 | 105 | prog: $(PROJ).bin 106 | bash -c "cat $< > /dev/ttyUSB1" 107 | 108 | clean: 109 | rm -f $(BUILD_DIR)/* 110 | rm -f $(SVG_DIR)/*svg 111 | rm -f $(SVG_PORT_DIR)/*svg 112 | 113 | .SECONDARY: 114 | .PHONY: all prog clean svg 115 | -------------------------------------------------------------------------------- /src/sram.v: -------------------------------------------------------------------------------- 1 | /* 2 | mystorm blackice has 0.5MByte SRAM on the back of the board 3 | From datasheet: ISSI IS62WV25616DALL and IS62/65WV25616DBLL are high-speed, low power, 4M bit SRAMs organized as 256K words by 16 bits. 4 | The part on the board appears to be the 10ns variant. 5 | 6 | a problem with the blackice board is that the PLL lines interfere with the SRAM data lines. 7 | 8 | https://github.com/cseed/arachne-pnr/issues/64#issuecomment-310877601 9 | 10 | hence reading/writing to data[13] will not work. 11 | 12 | Also thanks to David on the mystorm forum: 13 | https://forum.mystorm.uk/t/fpga-unreliability-crashing-hanging/252/6?u=mattvenn 14 | 15 | */ 16 | `default_nettype none 17 | module sram ( 18 | input wire reset, 19 | // 10ns max for data read/write. 20 | // At 100MHz, each clock cycle is 10ns, so write should be fine in 2 cycles 21 | // At 25Mhz, each clock cycle is 40ns, so write should be fine in 1 cycle 22 | input wire clk, 23 | input wire write, 24 | input wire read, 25 | input wire [15:0] data_write, // the data to write 26 | output wire [15:0] data_read, // the data that's been read 27 | input wire [17:0] address, // address to write to 28 | output reg ready, // high when ready for next operation 29 | output reg data_pins_out_en, // when to switch between in and out on data pins 30 | 31 | // SRAM pins 32 | output wire [17:0] address_pins, // address pins of the SRAM 33 | input wire [15:0] data_pins_in, 34 | output wire [15:0] data_pins_out, 35 | output wire OE, // ~output enable - low to enable 36 | output wire WE, // ~write enable - low to enable 37 | output wire CS // ~chip select - low to enable 38 | ); 39 | 40 | localparam STATE_IDLE = 0; 41 | localparam STATE_WRITE_SETUP = 1; 42 | localparam STATE_WRITE = 2; 43 | localparam STATE_WRITE_WAIT = 3; 44 | localparam STATE_READ_SETUP = 4; 45 | localparam STATE_READ = 5; 46 | localparam STATE_READ_WAIT = 6; 47 | 48 | reg output_enable; 49 | reg write_enable; 50 | reg chip_select; 51 | 52 | reg [1:0] wait_count; 53 | reg [2:0] state; 54 | reg [15:0] data_read_reg; 55 | reg [15:0] data_write_reg; 56 | reg [17:0] address_reg; 57 | 58 | assign address_pins = address_reg; 59 | assign data_pins_out = data_write_reg; 60 | assign data_read = data_read_reg; 61 | assign OE = !output_enable; 62 | assign WE = !write_enable; 63 | assign CS = !chip_select; 64 | 65 | 66 | initial begin 67 | state <= STATE_IDLE; 68 | output_enable <= 0; 69 | chip_select <= 0; 70 | write_enable <= 0; 71 | data_pins_out_en <= 0; 72 | end 73 | 74 | always@(posedge clk) begin 75 | if( reset == 1 ) begin 76 | state <= STATE_IDLE; 77 | output_enable <= 1; 78 | data_read_reg <= 0; 79 | chip_select <= 0; 80 | write_enable <= 0; 81 | ready <= 1; 82 | end 83 | else begin 84 | case(state) 85 | STATE_IDLE: begin 86 | write_enable <= 0; 87 | output_enable <= 0; 88 | chip_select <= 0; 89 | data_pins_out_en <= 0; 90 | wait_count <= 0; 91 | 92 | address_reg <= address; 93 | data_write_reg <= data_write; 94 | 95 | if(write) begin 96 | ready <= 0; 97 | state <= STATE_WRITE_SETUP; 98 | output_enable <= 0; 99 | chip_select <= 1; 100 | end 101 | else if(read) begin 102 | ready <= 0; 103 | state <= STATE_READ_SETUP; 104 | output_enable <= 1; 105 | chip_select <= 1; 106 | end 107 | end 108 | 109 | STATE_WRITE_SETUP: begin 110 | data_pins_out_en <= 1; 111 | write_enable <= 1; 112 | state <= STATE_WRITE; 113 | end 114 | STATE_WRITE: begin 115 | state <= STATE_IDLE; 116 | ready <= 1; 117 | data_pins_out_en <= 0; 118 | write_enable <= 0; 119 | end 120 | 121 | STATE_READ_SETUP: begin 122 | state <= STATE_READ; 123 | data_read_reg <= data_pins_in; 124 | ready <= 1; 125 | state <= STATE_IDLE; 126 | end 127 | endcase 128 | end 129 | end 130 | 131 | 132 | endmodule 133 | -------------------------------------------------------------------------------- /src/camera.v: -------------------------------------------------------------------------------- 1 | /* probably needs to use a loop in the state to deal with all the config (6 paris of bytes) 2 | 3 | camera is 1024 x 768 4 | 5 | * details on camera data format: http://wiibrew.org/wiki/Wiimote#Data_Formats 6 | * http://procrastineering.blogspot.com.es/2008/09/working-with-pixart-camera-directly.html 7 | 8 | */ 9 | `default_nettype none 10 | module camera( 11 | input wire clk, 12 | input wire clk_en, 13 | input wire reset, 14 | output wire i2c_sda, 15 | input wire i2c_sda_in, 16 | output wire i2c_sda_dir, 17 | output wire i2c_scl, 18 | output reg[9:0] x, 19 | output reg[9:0] y 20 | ); 21 | localparam [8*6-1:0] config_data = 48'h300130083333; // 3 pairs of 2 config bytes 22 | reg [3:0] config_byte = 5; 23 | reg [2:0] data_byte = 0; 24 | reg [4:0] packets; 25 | reg [3:0] state = STATE_START; 26 | reg i2c_start = 0; 27 | wire i2c_ready; 28 | reg [7:0] i2c_data; 29 | wire [7:0] i2c_data_in; 30 | reg rw = 1; // read 31 | localparam i2c_addr = 7'h58; 32 | wire data_ready; 33 | wire data_req; 34 | reg [7:0] delay_count = 0; 35 | // array makes synthesis much more efficient 36 | reg [7:0] pos_data [3:0]; // only need first 3 bytes 37 | 38 | localparam STATE_START = 0; 39 | localparam STATE_START_WAIT = 11; 40 | localparam STATE_CONF = 1; 41 | localparam STATE_CONF_WAIT = 2; 42 | localparam STATE_CONF_DELAY = 3; 43 | localparam STATE_REQ_DATA_1 = 4; 44 | localparam STATE_REQ_DATA_2 = 5; 45 | localparam STATE_REQ_DATA_3 = 6; 46 | localparam STATE_REQ_DATA_4 = 7; 47 | localparam STATE_REQ_DATA_5 = 8; 48 | localparam STATE_PROCESS_DATA = 9; 49 | localparam STATE_WAIT = 10; 50 | 51 | i2c_master i2c(.clk_en(clk_en), .i2c_sda_dir(i2c_sda_dir), .clk (clk), .addr(i2c_addr), .data(i2c_data), .reset (reset), .rw(rw), .start(i2c_start), .ready(i2c_ready), .i2c_sda(i2c_sda), .i2c_sda_in(i2c_sda_in), .i2c_scl(i2c_scl), .data_out(i2c_data_in), .packets(packets), .data_ready(data_ready), .data_req(data_req)); 52 | 53 | always@(posedge clk) begin 54 | if( reset == 1 ) begin 55 | state <= STATE_START; 56 | end 57 | else if ( clk_en )begin 58 | case(state) 59 | STATE_START: begin 60 | if(i2c_ready) begin 61 | state <= STATE_START_WAIT; 62 | packets <= 2; 63 | rw <= 0; 64 | delay_count <= 0; 65 | end 66 | end 67 | STATE_START_WAIT: begin 68 | delay_count <= delay_count + 1; 69 | if(delay_count > 200) 70 | state <= STATE_CONF; 71 | end 72 | STATE_CONF: begin 73 | i2c_start <= 1; 74 | if(i2c_ready == 0) begin 75 | state = STATE_CONF_WAIT; 76 | end 77 | end 78 | STATE_CONF_WAIT: begin 79 | i2c_start <= 0; 80 | if(data_req) begin 81 | config_byte <= config_byte - 1; 82 | i2c_data <= config_data[(config_byte+1)*8-1 -: 8]; 83 | end 84 | if(i2c_ready) state <= STATE_CONF_DELAY; 85 | delay_count <= 0; 86 | end 87 | STATE_CONF_DELAY: begin 88 | delay_count <= delay_count + 1; 89 | if(delay_count > 100) begin 90 | state <= STATE_CONF; 91 | if(config_byte == 15) state <= STATE_REQ_DATA_1; 92 | end 93 | end 94 | STATE_REQ_DATA_1: begin 95 | i2c_start <= 1; 96 | // request data 97 | i2c_data <= 8'h36; 98 | packets <= 1; 99 | rw <= 0; 100 | delay_count <= 0; 101 | state <= STATE_REQ_DATA_2; 102 | end 103 | STATE_REQ_DATA_2: begin 104 | i2c_start <= 0; 105 | if(i2c_start == 0 && i2c_ready) 106 | state <= STATE_REQ_DATA_3; 107 | end 108 | STATE_REQ_DATA_3: begin 109 | packets <= 16; 110 | rw <= 1; 111 | i2c_start <= 1; 112 | data_byte = 0; 113 | state <= STATE_REQ_DATA_4; 114 | end 115 | STATE_REQ_DATA_4: begin 116 | i2c_start <= 0; 117 | if(i2c_ready) state <= STATE_REQ_DATA_5; 118 | end 119 | STATE_REQ_DATA_5: begin 120 | if(data_ready) begin 121 | if(data_byte <= 3) begin 122 | pos_data[data_byte+1] <= i2c_data_in; 123 | data_byte <= data_byte + 1; 124 | end 125 | end 126 | // after data transfer complete, move on to process data 127 | if(i2c_ready) state <= STATE_PROCESS_DATA; 128 | end 129 | STATE_PROCESS_DATA: begin 130 | // update the camera position 131 | //http://wiibrew.org/wiki/Wiimote#Data_Formats 132 | // + has precedence over << 133 | x <= pos_data[2] + ((pos_data[4] & 8'b00110000) <<4); 134 | y <= pos_data[3] + ((pos_data[4] & 8'b11000000) <<2); 135 | state <= STATE_WAIT; 136 | delay_count <= 0; 137 | end 138 | STATE_WAIT: begin 139 | delay_count <= delay_count + 1; 140 | if(delay_count > 100) 141 | state <= STATE_REQ_DATA_1; 142 | end 143 | endcase 144 | end 145 | end 146 | 147 | endmodule 148 | 149 | -------------------------------------------------------------------------------- /src/write_buffer.v: -------------------------------------------------------------------------------- 1 | module write_buffer( 2 | input wire clk, 3 | input wire clk_en, 4 | input wire reset, 5 | input wire erase, 6 | input wire start, 7 | 8 | output reg [17:0] address, 9 | input wire [15:0] data_read, 10 | output reg [15:0] data_write, 11 | input wire ram_ready, 12 | output reg ram_read, 13 | output reg ram_write, 14 | 15 | input wire [9:0] cam_x, 16 | input wire [9:0] cam_y, 17 | input wire cam_valid 18 | ); 19 | 20 | reg line_start = 0; 21 | reg line_clk_en = 0; 22 | wire line_plot; 23 | wire line_done; 24 | 25 | // these are outputs from line drawing alg 26 | wire [9:0] x; 27 | wire [9:0] y; 28 | 29 | // beginning and ends of the line 30 | reg [9:0] x0; 31 | reg [9:0] y0; 32 | reg [9:0] x1; 33 | reg [9:0] y1; 34 | 35 | reg [4:0] state = STATE_START; 36 | 37 | localparam STATE_START = 0; 38 | localparam STATE_ERASE = 1; 39 | localparam STATE_START_LINE = 2; 40 | localparam STATE_WAIT_LINE = 3; 41 | localparam STATE_ERASE_WAIT = 4; 42 | localparam STATE_READ_SRAM = 5; 43 | localparam STATE_READ_SRAM_WAIT = 6; 44 | localparam STATE_WRITE_SRAM = 7; 45 | localparam STATE_WRITE_SRAM_WAIT = 8; 46 | 47 | localparam NUM_LINES = 10; 48 | 49 | 50 | bresenham line (.clk(clk), .clk_en(line_clk_en), .reset(reset), .y(y), .x(x), .x0(x0), .y0(y0), .x1(x1), .y1(y1), .done(line_done), .start(line_start), .plot(line_plot)); 51 | 52 | reg last_invalid = 0; 53 | reg [3:0] num_lines = 0; 54 | 55 | always @(posedge clk) begin 56 | if(reset) begin 57 | address <= 0; 58 | state <= STATE_START; 59 | line_start <= 0; 60 | line_clk_en <= 0; 61 | ram_write <= 0; 62 | ram_read <= 0; 63 | x0 <= 0; 64 | y0 <= 0; 65 | x1 <= 0; 66 | y1 <= 0; 67 | last_invalid <= 1; // at reset, don't have a last value 68 | num_lines <= 0; 69 | 70 | end else if (clk_en) case(state) 71 | STATE_START: begin 72 | ram_write <= 0; 73 | address <= 0; 74 | if(start) begin 75 | if(erase) state <= STATE_ERASE; 76 | else if (cam_valid) begin // cam valid 77 | //register the line variables so they can't change while drawing the line 78 | x0 <= x1 - NUM_LINES; // need to either store the original x1, y1, or subtract the added pixels that make lines fatter 79 | y0 <= y1; // - NUM_LINES; 80 | x1 <= cam_x; 81 | y1 <= cam_y; 82 | last_invalid <= 0; 83 | num_lines <= 0; 84 | 85 | // only start drawing the line if the last camera value wasn't invalid 86 | if(!last_invalid) 87 | state <= STATE_START_LINE; 88 | 89 | end else 90 | last_invalid <= 1; 91 | end 92 | end 93 | 94 | // untested in this setting 95 | STATE_ERASE: begin 96 | data_write <= 16'h0000; 97 | if(ram_ready) begin 98 | state <= STATE_ERASE_WAIT; 99 | ram_write <= 1; 100 | address <= address + 1; 101 | end 102 | end 103 | STATE_ERASE_WAIT: begin 104 | ram_write <= 0; 105 | if(address > 38400) begin 106 | state <= STATE_START; 107 | end else 108 | state <= STATE_ERASE; 109 | end 110 | 111 | STATE_START_LINE: begin // start line drawing 112 | line_clk_en <= 1; 113 | line_start <= 1; 114 | if(line_plot) state <= STATE_WAIT_LINE; 115 | end 116 | 117 | STATE_WAIT_LINE: begin 118 | line_start <= 0; 119 | line_clk_en <= 0; // stop line algorithm while write to SRAM 120 | if(ram_ready) state <= STATE_READ_SRAM; 121 | end 122 | 123 | STATE_READ_SRAM: begin // read what's there first 124 | // x >> 3 divides x by 8 - using a / broke timing requirements 125 | address <= ( x >> 3 ) + y * 80; 126 | ram_read <= 1; 127 | if(!ram_ready) 128 | state <= STATE_READ_SRAM_WAIT; 129 | end 130 | 131 | STATE_READ_SRAM_WAIT: begin 132 | ram_read <= 0; 133 | if(ram_ready) 134 | state <= STATE_WRITE_SRAM; 135 | end 136 | 137 | STATE_WRITE_SRAM: begin // so we can add the new point 138 | ram_read <= 0; 139 | ram_write <= 1; 140 | data_write <= data_read[7:0] | (1 << x[2:0]); 141 | if(!ram_ready) 142 | state <= STATE_WRITE_SRAM_WAIT; 143 | end 144 | 145 | STATE_WRITE_SRAM_WAIT: begin 146 | ram_write <= 0; 147 | if(line_done && num_lines == NUM_LINES) begin 148 | state <= STATE_START; 149 | end else if(line_done) begin // fatten the line 150 | state <= STATE_START_LINE; 151 | x0 <= x0 + 1; 152 | // y0 <= y0 + 1; 153 | x1 <= x1 + 1; 154 | // y1 <= y1 + 1; 155 | num_lines <= num_lines + 1; 156 | end else if(ram_ready) begin 157 | line_clk_en <= 1; // let line algorithm take another step 158 | state <= STATE_WAIT_LINE; 159 | end 160 | end 161 | 162 | default: state <= STATE_START; 163 | 164 | endcase 165 | end 166 | 167 | endmodule 168 | -------------------------------------------------------------------------------- /src/blackice.pcf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## # 3 | ## Copyright 2016 myStorm Copyright and related # 4 | ## rights are licensed under the Solderpad Hardware License, Version 0.51 # 5 | ## (the “License”); you may not use this file except in compliance with # 6 | ## the License. You may obtain a copy of the License at # 7 | ## http://solderpad.org/licenses/SHL-0.51. Unless required by applicable # 8 | ## law or agreed to in writing, software, hardware and materials # 9 | ## distributed under this License is distributed on an “AS IS” BASIS, # 10 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # 11 | ## implied. See the License for the specific language governing # 12 | ## permissions and limitations under the License. # 13 | ## # 14 | ################################################################################ 15 | # 16 | ## User Constraint File for myStorm 17 | # 18 | ##pmod 1 lvds pairs 2 & 5 19 | # 20 | set_io --warn-no-port PMOD[0] 94 # rd6 21 | set_io --warn-no-port PMOD[1] 91 # rd4 22 | set_io --warn-no-port PMOD[2] 88 # rd2 23 | set_io --warn-no-port PMOD[3] 85 # rd0 24 | 25 | #pmod 2 lvds pairs 3 & 4 26 | set_io --warn-no-port PMOD[4] 95 # rd7 27 | set_io --warn-no-port PMOD[5] 93 # rd5 28 | set_io --warn-no-port PMOD[6] 90 # rd3 29 | set_io --warn-no-port PMOD[7] 87 # rd1 30 | 31 | #pmod 3 GPIO 32 | #set_io --warn-no-port PMOD[8] 105 # c5 33 | #set_io --warn-no-port PMOD[9] 102 # c3 34 | #set_io --warn-no-port PMOD[10] 99 # c1 35 | #set_io --warn-no-port PMOD[11] 97 # i_tx 36 | 37 | 38 | set_io --warn-no-port i2c_sda 105 39 | set_io --warn-no-port i2c_scl 102 40 | set_io --warn-no-port pixartclk 99 41 | set_io --warn-no-port pixart_reset 97 42 | #set_io --warn-no-port i2c_sda_dir 104 43 | #set_io pixartclk 62 44 | #set_io button 44 45 | 46 | #pmod 4 47 | set_io --warn-no-port reset_button 104 # c4 48 | set_io --warn-no-port erase_button 101 # c2 49 | set_io --warn-no-port status_led 98 # c0 50 | set_io --warn-no-port cam_led 96 # i_rx 51 | # 52 | ##pmod 5 GPIO (top level of pins) 53 | set_io --warn-no-port PMOD[16] 143 #g2 54 | set_io --warn-no-port PMOD[17] 114 #c11 55 | set_io --warn-no-port PMOD[18] 112 #c9 56 | set_io --warn-no-port PMOD[19] 107 #c7 57 | # 58 | ##pmod 6 GPIO 59 | set_io --warn-no-port PMOD[20] 144 #G1 60 | set_io --warn-no-port PMOD[21] 113 #C10 61 | set_io --warn-no-port PMOD[22] 110 #C8 62 | set_io --warn-no-port PMOD[23] 106 #C6 63 | # 64 | ##pmod 7 65 | set_io --warn-no-port PMOD[24] 10 # 5b 66 | set_io --warn-no-port PMOD[25] 9 # 5a 67 | set_io --warn-no-port PMOD[26] 2 # 2b 68 | set_io --warn-no-port PMOD[27] 1 # 2a 69 | # 70 | ##pmod 8 71 | set_io --warn-no-port PMOD[28] 8 # 4b 72 | set_io --warn-no-port PMOD[29] 7 # 4a 73 | set_io --warn-no-port PMOD[30] 4 # 3b 74 | set_io --warn-no-port PMOD[31] 3 # 3a 75 | # 76 | ##pmod 9 lvds pairs 10 & 13 77 | #set_io --warn-no-port PMOD[32] 20 # 13b 78 | #set_io --warn-no-port PMOD[33] 19 # 13a 79 | #set_io --warn-no-port PMOD[34] 16 # 10b 80 | #set_io --warn-no-port PMOD[35] 15 # 10a 81 | # 82 | ##pmod 10 lvds pairs 8 & 12 83 | #set_io --warn-no-port PMOD[36] 18 # 12b 84 | #set_io --warn-no-port PMOD[37] 17 # 12a 85 | #set_io --warn-no-port PMOD[38] 12 # 8b 86 | #set_io --warn-no-port PMOD[39] 11 # 8a 87 | # 88 | ##pmod 11 lvds pairs 14 & 25 89 | #set_io --warn-no-port PMOD[40] 34 # 25b 90 | #set_io --warn-no-port PMOD[41] 33 # 25a 91 | #set_io --warn-no-port PMOD[42] 22 # 14B 92 | #set_io --warn-no-port PMOD[43] 21 # 14a 93 | # 94 | ##pmod 12 lvds pairs 18 & 24 95 | #set_io --warn-no-port PMOD[44] 32 # 24b 96 | #set_io --warn-no-port PMOD[45] 31 # 24a 97 | #set_io --warn-no-port PMOD[46] 26 # 18b 98 | #set_io --warn-no-port PMOD[47] 25 # 18a 99 | # 100 | ##pmod 13 lvds pairs 17 & 23 101 | #set_io --warn-no-port PMOD[48] 29 # 23b 102 | #set_io --warn-no-port PMOD[49] 28 # 23a 103 | #set_io --warn-no-port PMOD[50] 24 # 17b 104 | #set_io --warn-no-port PMOD[51] 23 # 17a 105 | # 106 | 107 | set_io --warn-no-port BUTTON[0] 63 108 | set_io --warn-no-port BUTTON[1] 64 109 | 110 | # 111 | # SRAM 112 | set_io --warn-no-port ADR[0] 137 113 | set_io --warn-no-port ADR[1] 138 114 | set_io --warn-no-port ADR[2] 139 115 | set_io --warn-no-port ADR[3] 141 116 | set_io --warn-no-port ADR[4] 142 117 | set_io --warn-no-port ADR[5] 42 118 | set_io --warn-no-port ADR[6] 43 119 | set_io --warn-no-port ADR[7] 44 120 | set_io --warn-no-port ADR[8] 73 121 | set_io --warn-no-port ADR[9] 74 122 | set_io --warn-no-port ADR[10] 75 123 | set_io --warn-no-port ADR[11] 76 124 | set_io --warn-no-port ADR[12] 115 125 | set_io --warn-no-port ADR[13] 116 126 | set_io --warn-no-port ADR[14] 117 127 | set_io --warn-no-port ADR[15] 118 128 | set_io --warn-no-port ADR[16] 119 129 | set_io --warn-no-port ADR[17] 78 130 | #set_io --warn-no-port ADR[18] 62 131 | 132 | set_io --warn-no-port DAT[0] 135 133 | set_io --warn-no-port DAT[1] 134 134 | set_io --warn-no-port DAT[2] 130 135 | set_io --warn-no-port DAT[3] 128 136 | set_io --warn-no-port DAT[4] 125 137 | set_io --warn-no-port DAT[5] 124 138 | set_io --warn-no-port DAT[6] 122 139 | set_io --warn-no-port DAT[7] 121 140 | set_io --warn-no-port DAT[8] 61 141 | set_io --warn-no-port DAT[9] 60 142 | set_io --warn-no-port DAT[10] 56 143 | set_io --warn-no-port DAT[11] 55 144 | set_io --warn-no-port DAT[12] 52 145 | # can't use this IO 146 | # https://github.com/cseed/arachne-pnr/issues/64#issuecomment-310877601 147 | #set_io --warn-no-port DAT[13] 49 148 | set_io --warn-no-port DAT[14] 48 149 | set_io --warn-no-port DAT[15] 47 150 | 151 | set_io --warn-no-port RAMOE 45 152 | set_io --warn-no-port RAMWE 120 153 | set_io --warn-no-port RAMCS 136 154 | 155 | ## Onboard 100Mhz oscillator 156 | set_io --warn-no-port clk 129 157 | set_io --warn-no-port LED[0] 71 #LD4,!SS,p14_1 158 | set_io --warn-no-port LED[1] 67 #LD3,MISO,p14_2 159 | set_io --warn-no-port LED[2] 68 #LD2,MOSI,p14_3 160 | set_io --warn-no-port LED[3] 70 #LD1,SCL,p14_4 161 | # 162 | -------------------------------------------------------------------------------- /src/dvid.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | `define enable_output 3 | module dvid ( 4 | input wire clkx5, 5 | input wire clk, 6 | input wire hsync, 7 | input wire vsync, 8 | input wire blank, 9 | input wire [2:0] red, 10 | input wire [2:0] green, 11 | input wire [2:0] blue, 12 | 13 | output wire [3:0] hdmi_p, 14 | output wire [3:0] hdmi_n 15 | ); 16 | 17 | wire [1:0] ctls [2:0]; 18 | wire [2:0] colours [2:0]; 19 | 20 | reg [9:0] symbols [3:0]; 21 | reg [9:0] high_speed_sr [3:0]; 22 | reg [4:0] high_speed_latch = 5'b00001; 23 | reg [1:0] output_bits [3:0]; 24 | 25 | assign ctls[0] = { vsync, hsync }; 26 | assign colours[0] = red; 27 | assign colours[1] = green; 28 | assign colours[2] = blue; 29 | 30 | initial begin 31 | // clock 32 | symbols[3] = 10'b0000011111; 33 | end 34 | 35 | integer i; 36 | always@(posedge clk) begin 37 | for(i=0; i<=2; i=i+1) begin 38 | if(blank == 1'b1) begin 39 | case(ctls[i]) 40 | // these are output LSB first so are the reverse as to what is in the spec 41 | // hsync and vsync are only sent on blue channel 42 | 2'b00: symbols[i] <= 10'b1101010100; 43 | 2'b01: symbols[i] <= 10'b0010101011; // hsync 44 | 2'b10: symbols[i] <= 10'b0101010100; // vsync 45 | default: symbols[i] <= 10'b1010101011; 46 | endcase 47 | end else begin 48 | case(colours[i]) 49 | 3'b000: symbols[i] <= 10'b0111110000; // 0x10 50 | 3'b001: symbols[i] <= 10'b0001001111; // 0x2F 51 | 3'b010: symbols[i] <= 10'b0111001100; // 0x54 52 | 3'b011: symbols[i] <= 10'b0010001111; // 0x6F 53 | 3'b100: symbols[i] <= 10'b0000101111; // 0x8F 54 | 3'b101: symbols[i] <= 10'b1000111001; // 0xB4 55 | 3'b110: symbols[i] <= 10'b1000011011; // 0xD2 56 | default: symbols[i] <= 10'b1011110000; // 0xEF 57 | endcase 58 | end 59 | end 60 | end 61 | 62 | // from hamster's work, this is missing the output buffer and the 2bit output_bits for each channel 63 | always@(posedge clkx5) begin 64 | for(i = 0; i <= 3; i = i + 1) begin 65 | // 2 bits at a time for DDR 66 | output_bits[i] <= { high_speed_sr[i][0],high_speed_sr[i][1] }; //, [1:0]; 67 | if(high_speed_latch[0] == 1'b1) 68 | high_speed_sr[i] <= symbols[i]; 69 | else 70 | high_speed_sr[i] <= { 2'b00, high_speed_sr[i][9:2] }; 71 | end 72 | high_speed_latch <= { high_speed_latch[0], high_speed_latch[4:1] }; 73 | end 74 | 75 | // ddr details: http://www.latticesemi.com/view_document?document_id=47960 76 | `ifdef enable_output 77 | defparam hdmip0.PIN_TYPE = 6'b010000; 78 | defparam hdmip0.IO_STANDARD = "SB_LVCMOS" ; 79 | SB_IO hdmip0 ( 80 | .PACKAGE_PIN(hdmi_p[0]), 81 | .CLOCK_ENABLE (1'b1 ), 82 | .OUTPUT_CLK ( clkx5 ), 83 | .OUTPUT_ENABLE (1'b1 ), 84 | .D_OUT_0 (output_bits[0][0]), // Non-inverted 85 | .D_OUT_1 (output_bits[0][1]), // Non-inverted 86 | ); 87 | 88 | 89 | // Inverting, N-side of pair 90 | defparam hdmin0.PIN_TYPE = 6'b010000 ; 91 | defparam hdmin0.IO_STANDARD = "SB_LVCMOS" ; 92 | SB_IO hdmin0 ( 93 | .PACKAGE_PIN(hdmi_n[0]), 94 | .CLOCK_ENABLE ( 1'b1), 95 | .OUTPUT_CLK (clkx5), 96 | .OUTPUT_ENABLE (1'b1 ), 97 | .D_OUT_0 (~output_bits[0][0]), // Inverted 98 | .D_OUT_1 (~output_bits[0][1]), // Inverted 99 | ); 100 | 101 | // green 102 | defparam hdmip1.PIN_TYPE = 6'b010000; 103 | defparam hdmip1.IO_STANDARD = "SB_LVCMOS" ; 104 | SB_IO hdmip1 ( 105 | .PACKAGE_PIN(hdmi_p[1]), 106 | .CLOCK_ENABLE (1'b1 ), 107 | .OUTPUT_CLK ( clkx5 ), 108 | .OUTPUT_ENABLE (1'b1 ), 109 | .D_OUT_0 (output_bits[1][0]), // Non-inverted 110 | .D_OUT_1 (output_bits[1][1]), // Non-inverted 111 | ); 112 | 113 | // Inverting, N-side of pair 114 | defparam hdmin1.PIN_TYPE = 6'b010000 ; 115 | defparam hdmin1.IO_STANDARD = "SB_LVCMOS" ; 116 | SB_IO hdmin1 ( 117 | .PACKAGE_PIN(hdmi_n[1]), 118 | .CLOCK_ENABLE ( 1'b1), 119 | .OUTPUT_CLK (clkx5), 120 | .OUTPUT_ENABLE (1'b1 ), 121 | .D_OUT_0 (~output_bits[1][0]), // Inverted 122 | .D_OUT_1 (~output_bits[1][1]), // Inverted 123 | ); 124 | 125 | 126 | // blue 127 | defparam hdmip2.PIN_TYPE = 6'b010000; 128 | defparam hdmip2.IO_STANDARD = "SB_LVCMOS" ; 129 | SB_IO hdmip2 ( 130 | .PACKAGE_PIN(hdmi_p[2]), 131 | .CLOCK_ENABLE (1'b1 ), 132 | .OUTPUT_CLK ( clkx5 ), 133 | .OUTPUT_ENABLE (1'b1 ), 134 | .D_OUT_0 (output_bits[2][0]), // Non-inverted 135 | .D_OUT_1 (output_bits[2][1]), // Non-inverted 136 | ); 137 | 138 | // Inverting, N-side of pair 139 | defparam hdmin2.PIN_TYPE = 6'b010000 ; 140 | defparam hdmin2.IO_STANDARD = "SB_LVCMOS" ; 141 | SB_IO hdmin2 ( 142 | .PACKAGE_PIN(hdmi_n[2]), 143 | .CLOCK_ENABLE ( 1'b1), 144 | .OUTPUT_CLK (clkx5), 145 | .OUTPUT_ENABLE (1'b1 ), 146 | .D_OUT_0 (~output_bits[2][0]), // Inverted 147 | .D_OUT_1 (~output_bits[2][1]), // Inverted 148 | ); 149 | 150 | // clock 151 | defparam hdmip3.PIN_TYPE = 6'b010000; 152 | defparam hdmip3.IO_STANDARD = "SB_LVCMOS" ; 153 | SB_IO hdmip3 ( 154 | .PACKAGE_PIN(hdmi_p[3]), 155 | .CLOCK_ENABLE (1'b1 ), 156 | .OUTPUT_CLK ( clkx5 ), 157 | .OUTPUT_ENABLE (1'b1 ), 158 | .D_OUT_0 (output_bits[3][0]), // Non-inverted 159 | .D_OUT_1 (output_bits[3][1]), // Non-inverted 160 | ); 161 | 162 | // Inverting, N-side of pair 163 | defparam hdmin3.PIN_TYPE = 6'b010000 ; 164 | defparam hdmin3.IO_STANDARD = "SB_LVCMOS" ; 165 | SB_IO hdmin3 ( 166 | .PACKAGE_PIN(hdmi_n[3]), 167 | .CLOCK_ENABLE ( 1'b1), 168 | .OUTPUT_CLK (clkx5), 169 | .OUTPUT_ENABLE (1'b1 ), 170 | .D_OUT_0 (~output_bits[3][0]), // Inverted 171 | .D_OUT_1 (~output_bits[3][1]), // Inverted 172 | ); 173 | 174 | `endif 175 | 176 | endmodule 177 | 178 | -------------------------------------------------------------------------------- /button-pcb/buttonpcb.sch: -------------------------------------------------------------------------------- 1 | EESchema Schematic File Version 2 2 | LIBS:power 3 | LIBS:device 4 | LIBS:transistors 5 | LIBS:conn 6 | LIBS:linear 7 | LIBS:regul 8 | LIBS:74xx 9 | LIBS:cmos4000 10 | LIBS:adc-dac 11 | LIBS:memory 12 | LIBS:xilinx 13 | LIBS:microcontrollers 14 | LIBS:dsp 15 | LIBS:microchip 16 | LIBS:analog_switches 17 | LIBS:motorola 18 | LIBS:texas 19 | LIBS:intel 20 | LIBS:audio 21 | LIBS:interface 22 | LIBS:digital-audio 23 | LIBS:philips 24 | LIBS:display 25 | LIBS:cypress 26 | LIBS:siliconi 27 | LIBS:opto 28 | LIBS:atmel 29 | LIBS:contrib 30 | LIBS:valves 31 | LIBS:buttonpcb-cache 32 | EELAYER 26 0 33 | EELAYER END 34 | $Descr A4 11693 8268 35 | encoding utf-8 36 | Sheet 1 1 37 | Title "" 38 | Date "" 39 | Rev "" 40 | Comp "" 41 | Comment1 "" 42 | Comment2 "" 43 | Comment3 "" 44 | Comment4 "" 45 | $EndDescr 46 | $Comp 47 | L CONN_01X06 Pmod1 48 | U 1 1 59BFFE46 49 | P 5900 3000 50 | F 0 "Pmod1" H 5978 3041 50 0000 L CNN 51 | F 1 "CONN_01X06" H 5978 2950 50 0000 L CNN 52 | F 2 "Pin_Headers:Pin_Header_Straight_1x06" H 5900 3000 50 0001 C CNN 53 | F 3 "" H 5900 3000 50 0000 C CNN 54 | 1 5900 3000 55 | 1 0 0 -1 56 | $EndComp 57 | $Comp 58 | L Earth #PWR01 59 | U 1 1 59BFFED8 60 | P 5500 3150 61 | F 0 "#PWR01" H 5500 2900 50 0001 C CNN 62 | F 1 "Earth" H 5500 3000 50 0001 C CNN 63 | F 2 "" H 5500 3150 50 0000 C CNN 64 | F 3 "" H 5500 3150 50 0000 C CNN 65 | 1 5500 3150 66 | 1 0 0 -1 67 | $EndComp 68 | $Comp 69 | L VCC #PWR02 70 | U 1 1 59BFFF12 71 | P 5250 3250 72 | F 0 "#PWR02" H 5250 3100 50 0001 C CNN 73 | F 1 "VCC" H 5267 3423 50 0000 C CNN 74 | F 2 "" H 5250 3250 50 0000 C CNN 75 | F 3 "" H 5250 3250 50 0000 C CNN 76 | 1 5250 3250 77 | 1 0 0 -1 78 | $EndComp 79 | Wire Wire Line 80 | 5250 3250 5700 3250 81 | Wire Wire Line 82 | 5500 3150 5700 3150 83 | $Comp 84 | L SW_PUSH SW1 85 | U 1 1 59BFFF76 86 | P 6950 2550 87 | F 0 "SW1" H 6950 2805 50 0000 C CNN 88 | F 1 "SW_PUSH" H 6950 2714 50 0000 C CNN 89 | F 2 "fp:CHERRY_MX" H 6950 2550 50 0001 C CNN 90 | F 3 "" H 6950 2550 50 0000 C CNN 91 | 1 6950 2550 92 | 1 0 0 -1 93 | $EndComp 94 | $Comp 95 | L SW_PUSH SW2 96 | U 1 1 59BFFFF6 97 | P 6950 2950 98 | F 0 "SW2" H 6950 3205 50 0000 C CNN 99 | F 1 "SW_PUSH" H 6950 3114 50 0000 C CNN 100 | F 2 "fp:CHERRY_MX" H 6950 2950 50 0001 C CNN 101 | F 3 "" H 6950 2950 50 0000 C CNN 102 | 1 6950 2950 103 | 1 0 0 -1 104 | $EndComp 105 | $Comp 106 | L Earth #PWR03 107 | U 1 1 59C00069 108 | P 7250 2550 109 | F 0 "#PWR03" H 7250 2300 50 0001 C CNN 110 | F 1 "Earth" H 7250 2400 50 0001 C CNN 111 | F 2 "" H 7250 2550 50 0000 C CNN 112 | F 3 "" H 7250 2550 50 0000 C CNN 113 | 1 7250 2550 114 | 1 0 0 -1 115 | $EndComp 116 | $Comp 117 | L Earth #PWR04 118 | U 1 1 59C00081 119 | P 7250 2950 120 | F 0 "#PWR04" H 7250 2700 50 0001 C CNN 121 | F 1 "Earth" H 7250 2800 50 0001 C CNN 122 | F 2 "" H 7250 2950 50 0000 C CNN 123 | F 3 "" H 7250 2950 50 0000 C CNN 124 | 1 7250 2950 125 | 1 0 0 -1 126 | $EndComp 127 | $Comp 128 | L VCC #PWR05 129 | U 1 1 59C00092 130 | P 6450 2250 131 | F 0 "#PWR05" H 6450 2100 50 0001 C CNN 132 | F 1 "VCC" H 6467 2423 50 0000 C CNN 133 | F 2 "" H 6450 2250 50 0000 C CNN 134 | F 3 "" H 6450 2250 50 0000 C CNN 135 | 1 6450 2250 136 | 1 0 0 -1 137 | $EndComp 138 | $Comp 139 | L R R2 140 | U 1 1 59C000FB 141 | P 6450 2400 142 | F 0 "R2" H 6520 2446 50 0000 L CNN 143 | F 1 "R" H 6520 2355 50 0000 L CNN 144 | F 2 "Resistors_SMD:R_1206_HandSoldering" V 6380 2400 50 0001 C CNN 145 | F 3 "" H 6450 2400 50 0000 C CNN 146 | 1 6450 2400 147 | 1 0 0 -1 148 | $EndComp 149 | $Comp 150 | L R R3 151 | U 1 1 59C00139 152 | P 6450 2800 153 | F 0 "R3" H 6520 2846 50 0000 L CNN 154 | F 1 "R" H 6520 2755 50 0000 L CNN 155 | F 2 "Resistors_SMD:R_1206_HandSoldering" V 6380 2800 50 0001 C CNN 156 | F 3 "" H 6450 2800 50 0000 C CNN 157 | 1 6450 2800 158 | 1 0 0 -1 159 | $EndComp 160 | $Comp 161 | L VCC #PWR06 162 | U 1 1 59C00178 163 | P 6450 2650 164 | F 0 "#PWR06" H 6450 2500 50 0001 C CNN 165 | F 1 "VCC" V 6468 2777 50 0000 L CNN 166 | F 2 "" H 6450 2650 50 0000 C CNN 167 | F 3 "" H 6450 2650 50 0000 C CNN 168 | 1 6450 2650 169 | 0 -1 -1 0 170 | $EndComp 171 | Wire Wire Line 172 | 6450 2550 6650 2550 173 | Wire Wire Line 174 | 6450 2950 6650 2950 175 | Text Label 6650 2950 0 60 ~ 0 176 | b1 177 | Text Label 6650 2550 0 60 ~ 0 178 | b2 179 | $Comp 180 | L LED D1 181 | U 1 1 59C001F0 182 | P 7900 2400 183 | F 0 "D1" V 7946 2292 50 0000 R CNN 184 | F 1 "LED" V 7855 2292 50 0000 R CNN 185 | F 2 "LEDs:LED-1206" H 7900 2400 50 0001 C CNN 186 | F 3 "" H 7900 2400 50 0000 C CNN 187 | 1 7900 2400 188 | 0 -1 -1 0 189 | $EndComp 190 | $Comp 191 | L R R1 192 | U 1 1 59C002CF 193 | P 7900 2050 194 | F 0 "R1" H 7970 2096 50 0000 L CNN 195 | F 1 "R" H 7970 2005 50 0000 L CNN 196 | F 2 "Resistors_SMD:R_1206_HandSoldering" V 7830 2050 50 0001 C CNN 197 | F 3 "" H 7900 2050 50 0000 C CNN 198 | 1 7900 2050 199 | 1 0 0 -1 200 | $EndComp 201 | $Comp 202 | L Earth #PWR07 203 | U 1 1 59C0032F 204 | P 7900 2600 205 | F 0 "#PWR07" H 7900 2350 50 0001 C CNN 206 | F 1 "Earth" H 7900 2450 50 0001 C CNN 207 | F 2 "" H 7900 2600 50 0000 C CNN 208 | F 3 "" H 7900 2600 50 0000 C CNN 209 | 1 7900 2600 210 | 1 0 0 -1 211 | $EndComp 212 | Text Label 7900 1900 0 60 ~ 0 213 | led 214 | Text Label 5700 3050 2 60 ~ 0 215 | led 216 | Text Label 5700 2850 2 60 ~ 0 217 | b1 218 | Text Label 5700 2750 2 60 ~ 0 219 | b2 220 | $Comp 221 | L LED D2 222 | U 1 1 59C00512 223 | P 8350 2350 224 | F 0 "D2" V 8396 2242 50 0000 R CNN 225 | F 1 "LED" V 8305 2242 50 0000 R CNN 226 | F 2 "LEDs:LED-1206" H 8350 2350 50 0001 C CNN 227 | F 3 "" H 8350 2350 50 0000 C CNN 228 | 1 8350 2350 229 | 0 -1 -1 0 230 | $EndComp 231 | $Comp 232 | L R R4 233 | U 1 1 59C00518 234 | P 8350 2000 235 | F 0 "R4" H 8420 2046 50 0000 L CNN 236 | F 1 "R" H 8420 1955 50 0000 L CNN 237 | F 2 "Resistors_SMD:R_1206_HandSoldering" V 8280 2000 50 0001 C CNN 238 | F 3 "" H 8350 2000 50 0000 C CNN 239 | 1 8350 2000 240 | 1 0 0 -1 241 | $EndComp 242 | $Comp 243 | L Earth #PWR08 244 | U 1 1 59C0051E 245 | P 8350 2550 246 | F 0 "#PWR08" H 8350 2300 50 0001 C CNN 247 | F 1 "Earth" H 8350 2400 50 0001 C CNN 248 | F 2 "" H 8350 2550 50 0000 C CNN 249 | F 3 "" H 8350 2550 50 0000 C CNN 250 | 1 8350 2550 251 | 1 0 0 -1 252 | $EndComp 253 | Text Label 8350 1850 0 60 ~ 0 254 | led2 255 | Text Label 5700 2950 2 60 ~ 0 256 | led2 257 | $EndSCHEMATC 258 | -------------------------------------------------------------------------------- /src/top.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | `define video 3 | `define camera 4 | //`define xyleds 5 | `define statusleds 6 | `define sram 7 | `define pixbuf 8 | 9 | module top ( 10 | input clk, 11 | output [0:3] LED, 12 | input [0:1] BUTTON, 13 | input reset_button, 14 | input erase_button, 15 | output status_led, 16 | output cam_led, 17 | output pixartclk, 18 | output pixart_reset, 19 | inout i2c_sda, 20 | output i2c_scl, 21 | `ifdef sram 22 | output [17:0] ADR, 23 | inout [15:0] DAT, 24 | output RAMOE, 25 | output RAMWE, 26 | output RAMCS, 27 | `endif 28 | output [31:0] PMOD 29 | ); 30 | 31 | 32 | // flashing status light 33 | always @(posedge clk) begin 34 | if(reset) 35 | led_counter <= 0; 36 | else 37 | led_counter <= led_counter + 1; 38 | end 39 | 40 | // led assignments 41 | `ifdef statusleds 42 | assign LED[0] = reset; 43 | assign LED[1] = cam_valid; 44 | assign LED[2] = led_counter[26]; // flash slowly 45 | assign cam_led = cam_valid; // cam valid repeat 46 | assign status_led = led_counter[26]; // system flash repeat 47 | `endif 48 | 49 | `ifdef xyleds 50 | xy_leds leds(.reset(reset), .x(x), .y(y), .LED1(LED[0]), .LED2(LED[1]),.LED3(LED[2]),.LED4(LED[3])); 51 | `endif 52 | 53 | // button wires 54 | wire erase; 55 | wire reset; 56 | 57 | assign erase = ~BUTTON[0] | ~erase_button; 58 | assign reset = ~BUTTON[1] | ~reset_button; 59 | 60 | reg [26:0] led_counter; 61 | 62 | wire cam_valid; 63 | reg cam_clk; 64 | 65 | // wiimote camera is 1024 x 768 66 | reg[9:0] x_cam; 67 | reg[9:0] y_cam; 68 | reg[9:0] x; 69 | reg[9:0] y; // could be [8:0] 70 | 71 | 72 | // pixart clock is 25MHz, reset low to reset 73 | assign pixart_reset = !reset; 74 | assign pixartclk = vga_clk; 75 | 76 | wire i2c_sda_out; 77 | wire i2c_sda_in; 78 | 79 | // i2c clock enable generator, vga clk is ~25Mhz, so clk enable is 500k, i2c clk will be 250k 80 | wire i2c_clk_en; 81 | divM #(.M(50)) clockdiv_cam(.clk_in(vga_clk), .clk_out(cam_clk)); 82 | pulse i2c_clk_en_pulse (.clk(vga_clk), .in(cam_clk), .out(i2c_clk_en)); 83 | 84 | `ifdef camera 85 | camera cam(.i2c_sda_dir(i2c_sda_dir), .clk_en(i2c_clk_en), .clk (vga_clk), .reset (reset), .i2c_scl(i2c_scl), .i2c_sda_in(i2c_sda_in), .i2c_sda(i2c_sda_out), .x(x_cam), .y(y_cam)); 86 | 87 | /* 88 | assign PMOD[24] = i2c_clk_en; 89 | assign PMOD[26] = i2c_sda_in; 90 | assign PMOD[27] = i2c_scl; 91 | assign PMOD[28] = reset; 92 | assign PMOD[29] = i2c_sda_dir; 93 | */ 94 | 95 | // remap from 1024 x 768 -> 640 x 480 96 | map_cam mc(.clk(vga_clk), .reset(reset), .x_in(x_cam), .y_in(y_cam), .x_out(x), .y_out(y), .valid(cam_valid)); 97 | 98 | `endif 99 | 100 | 101 | 102 | wire i2c_sda_dir; 103 | 104 | SB_IO #( 105 | .PIN_TYPE(6'b 1010_01), 106 | ) i2c_sda_pin ( 107 | .PACKAGE_PIN(i2c_sda), 108 | .OUTPUT_ENABLE(i2c_sda_dir), 109 | .D_OUT_0(i2c_sda_out), 110 | .D_IN_0(i2c_sda_in), 111 | ); 112 | `ifdef sram 113 | SB_IO #( 114 | .PIN_TYPE(6'b 1010_01), 115 | ) sram_data_pins [15:0] ( 116 | .PACKAGE_PIN(DAT), 117 | .OUTPUT_ENABLE(data_pins_out_en), 118 | .D_OUT_0(data_pins_out), 119 | .D_IN_0(data_pins_in), 120 | ); 121 | `endif 122 | 123 | //PLL details http://www.latticesemi.com/view_document?document_id=47778 124 | //vga clock freq is 25.2MHz (see vga.v) 125 | //need 5 times this for dvi output = 126MHz, so this PLL input is 100MHz (blackice clock), output is 126MHz. 126 | SB_PLL40_CORE #( 127 | .FEEDBACK_PATH("SIMPLE"), 128 | .PLLOUT_SELECT("GENCLK"), 129 | .DIVR(4'b1001), 130 | .DIVF(7'b1100100), 131 | .DIVQ(3'b011), 132 | .FILTER_RANGE(3'b001) 133 | ) uut ( 134 | // .LOCK(lock), 135 | .RESETB(1'b1), 136 | .BYPASS(1'b0), 137 | .REFERENCECLK(clk), 138 | .PLLOUTCORE(clkx5) 139 | ); 140 | 141 | wire clkx5; 142 | wire hsync; 143 | wire vsync; 144 | wire blank; 145 | wire [2:0] red; 146 | wire [2:0] green; 147 | wire [2:0] blue; 148 | wire vga_clk; 149 | divM #(.M(5)) clockdiv(.clk_in(clkx5), .clk_out(vga_clk)); // vga clock used for global clock 150 | 151 | `ifdef video 152 | wire [7:0] pixels; 153 | vga vga_test(.reset(reset), .pixels(pixels), .clk(vga_clk), .hsync(hsync), .vsync(vsync), .blank(blank), .red(red), .green(green), .blue(blue), .hcounter(hcounter), .vcounter(vcounter)); 154 | 155 | dvid dvid_test(.clk(vga_clk), .clkx5(clkx5), .hsync(hsync), .vsync(vsync), .blank(blank), .red(red), .green(green), .blue(blue), .hdmi_p(PMOD[0:3]), .hdmi_n(PMOD[4:7])); 156 | 157 | assign PMOD[16] = hsync; // 0 158 | assign PMOD[17] = vsync; // 1 159 | assign PMOD[18] = blank; // 2 160 | assign PMOD[19] = vga_clk; // 3 161 | `endif 162 | 163 | `ifdef sram 164 | 165 | reg [17:0] address; 166 | wire [15:0] data_read; 167 | reg [15:0] data_write; 168 | reg read; 169 | reg write; 170 | reg ready; 171 | 172 | wire [10:0] hcounter; 173 | wire [9:0] vcounter; 174 | 175 | wire [15:0] data_pins_in; 176 | wire [15:0] data_pins_out; 177 | wire data_pins_out_en; 178 | 179 | sram sram_test(.clk(vga_clk), .address(address), .data_read(data_read), .data_write(data_write), .write(write), .read(read), .reset(reset), .ready(ready), 180 | .data_pins_in(data_pins_in), 181 | .data_pins_out(data_pins_out), 182 | .data_pins_out_en(data_pins_out_en), 183 | .address_pins(ADR), 184 | .OE(RAMOE), .WE(RAMWE), .CS(RAMCS) 185 | ); 186 | 187 | `endif 188 | 189 | `ifdef pixbuf 190 | // pixel buffer reads video buffer from SRAM during a line 191 | pixel_buffer pb(.clk(vga_clk), .reset(reset), .address(pb_address), .data_read(data_read), .read(pb_read), .ready(ready), .pixels(pixels), .hcounter(hcounter), .vcounter(vcounter)); 192 | 193 | // write buffer writes pixels to the SRAM at the end of the screen 194 | write_buffer wb(.clk(vga_clk), .reset(reset), .address(wb_address), .data_read(data_read), .ram_read(wb_read), .ram_ready(ready), .data_write(data_write), .ram_write(write), .erase(erase), .cam_x(x), .cam_y(y), .cam_valid(cam_valid), .start(start_write), .clk_en(write_buf_clk_en)); 195 | 196 | reg start_write; 197 | reg write_buf_clk_en; 198 | wire wb_read, pb_read; 199 | wire [17:0] pb_address; 200 | wire [17:0] wb_address; 201 | 202 | // start signal for capturing camera position and drawing next line 203 | always @(posedge vga_clk) 204 | start_write <= vcounter == 480 && hcounter == 0; 205 | 206 | // mux for SRAM address lines 207 | always @(posedge vga_clk) begin 208 | if( vcounter > 479 ) begin 209 | read <= wb_read; 210 | address <= wb_address; 211 | write_buf_clk_en <= 1; 212 | end else begin 213 | read <= pb_read; 214 | address <= pb_address; 215 | write_buf_clk_en <= 0; 216 | end 217 | end 218 | `endif 219 | 220 | endmodule 221 | 222 | -------------------------------------------------------------------------------- /src/i2c_master.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | module i2c_master( 3 | input wire clk, 4 | input wire clk_en, 5 | input wire reset, 6 | input wire [6:0] addr, 7 | input wire [7:0] data, 8 | input wire [4:0] packets, 9 | input wire start, 10 | input wire rw, // 1 for read, 0 for write 11 | output wire i2c_sda, 12 | output wire i2c_sda_dir, 13 | input wire i2c_sda_in, 14 | output wire i2c_scl, 15 | output wire ready, 16 | output reg data_ready, // flag to say data is ready to read 17 | output reg data_req, // flag to request more data to write 18 | output reg [7:0] data_out // msb (pin 10) is index 7 19 | ); 20 | localparam STATE_IDLE = 0; // no clock 21 | localparam STATE_START = 1;// no clock 22 | localparam STATE_START_BIT = 12;// no clock 23 | localparam STATE_ADDR = 2; 24 | localparam STATE_ADDR_BIT = 10; 25 | localparam STATE_RW = 3; 26 | localparam STATE_RW_BIT = 11; 27 | localparam STATE_WACK_1 = 4; 28 | localparam STATE_WACK_1_BIT = 13; 29 | localparam STATE_DATA_READ = 5; 30 | localparam STATE_DATA_READ_BIT = 17; 31 | localparam STATE_DATA_REQ = 9; 32 | localparam STATE_DATA_WRITE = 6; 33 | localparam STATE_DATA_WRITE_BIT = 14; 34 | localparam STATE_WACK_2 = 7; 35 | localparam STATE_WACK_2_BIT = 15; 36 | localparam STATE_STOP = 8; // no clock 37 | localparam STATE_STOP_BIT_1 = 16; // no clock 38 | localparam STATE_STOP_BIT_2 = 18; // no clock 39 | 40 | reg [8:0] state; 41 | reg [7:0] count; 42 | reg i2c_sda_tri; 43 | reg i2c_scl_enable = 0; 44 | 45 | assign i2c_sda_dir = ~ i2c_sda_tri; 46 | 47 | reg [6:0] saved_addr; 48 | reg [7:0] saved_data; // 16 bytes of data max 49 | reg [4:0] saved_packets; 50 | reg saved_rw; 51 | reg i2c_scl_reg; 52 | 53 | initial begin 54 | state = STATE_IDLE; 55 | data_req = 0; 56 | i2c_sda_tri <= 1; 57 | i2c_scl_reg <= 1; 58 | end 59 | assign ready = (reset == 0) && (state == STATE_IDLE) ? 1 : 0; 60 | // assign i2c_scl = (i2c_scl_enable == 0) ? 1 : ~clk; 61 | assign i2c_sda = (i2c_sda_tri == 1) ? 'bz : 0; 62 | assign i2c_scl = i2c_scl_reg; 63 | 64 | /* always@(negedge clk) begin 65 | if( reset == 1 ) begin 66 | i2c_scl_enable <= 0; 67 | end else begin 68 | if ((state == STATE_IDLE) || (state == STATE_START) || (state == STATE_DATA_REQ)) begin 69 | i2c_scl_enable <= 0; 70 | end 71 | else begin 72 | i2c_scl_enable <= 1; 73 | end 74 | end 75 | end 76 | */ 77 | 78 | always@(posedge clk) begin 79 | if( reset == 1 ) begin 80 | state <= STATE_IDLE; 81 | data_ready <= 0; 82 | data_req <= 0; 83 | i2c_sda_tri <= 1; 84 | i2c_scl_reg <= 1; 85 | end 86 | else if (clk_en) begin 87 | case(state) 88 | STATE_IDLE: begin 89 | i2c_sda_tri <= 1; 90 | i2c_scl_reg <= 1; 91 | if (start) begin 92 | saved_addr <= addr; 93 | saved_rw <= rw; 94 | saved_packets <= packets; 95 | state <= STATE_START; 96 | end 97 | else state <= STATE_IDLE; 98 | end 99 | // start condition is sda going low while scl is high 100 | STATE_START: begin 101 | i2c_sda_tri <= 0; 102 | state <= STATE_START_BIT; 103 | count <= 6; 104 | end 105 | STATE_START_BIT: begin 106 | i2c_scl_reg <= 0; 107 | state <= STATE_ADDR; 108 | end 109 | STATE_ADDR: begin // send saved_address 7 bits, MSB 110 | // clock in the data to send 111 | i2c_scl_reg <= 0; 112 | i2c_sda_tri <= saved_addr[count]; 113 | state <= STATE_ADDR_BIT; 114 | end 115 | STATE_ADDR_BIT: begin 116 | i2c_scl_reg <= 1; 117 | count <= count - 1; 118 | if(count == 0) state <= STATE_RW; 119 | else state <= STATE_ADDR; 120 | end 121 | STATE_RW: begin 122 | i2c_scl_reg <= 0; 123 | i2c_sda_tri <= saved_rw; 124 | state <= STATE_RW_BIT; 125 | end 126 | STATE_RW_BIT: begin 127 | i2c_scl_reg <= 1; 128 | state <= STATE_WACK_1; 129 | end 130 | STATE_WACK_1: begin 131 | i2c_sda_tri <= 1; // allow slave to ack 132 | i2c_scl_reg <= 0; 133 | state <= STATE_WACK_1_BIT; 134 | data_req <= 1; 135 | end 136 | STATE_WACK_1_BIT: begin 137 | i2c_scl_reg <= 1; 138 | count <= 7; 139 | if(saved_rw) begin 140 | state <= STATE_DATA_READ; 141 | end 142 | else begin 143 | saved_data <= data; 144 | data_req <= 0; 145 | if(data_req == 0) 146 | state <= STATE_DATA_WRITE; 147 | end 148 | end 149 | STATE_DATA_WRITE: begin 150 | i2c_scl_reg <= 0; 151 | i2c_sda_tri <= saved_data[count]; 152 | state <= STATE_DATA_WRITE_BIT; 153 | end 154 | STATE_DATA_WRITE_BIT: begin 155 | i2c_scl_reg <= 1; 156 | if(count == 0) begin 157 | state <= STATE_WACK_2; 158 | saved_packets <= saved_packets - 1; 159 | end 160 | else state <= STATE_DATA_WRITE; 161 | count <= count - 1; 162 | end 163 | STATE_DATA_READ: begin 164 | i2c_sda_tri <= 1; 165 | i2c_scl_reg <= 0; 166 | state <= STATE_DATA_READ_BIT; 167 | end 168 | STATE_DATA_READ_BIT: begin 169 | saved_data[count] <= i2c_sda_in; 170 | i2c_scl_reg <= 1; 171 | if(count == 0) begin 172 | state <= STATE_WACK_2; 173 | saved_packets <= saved_packets - 1; 174 | end 175 | else state <= STATE_DATA_READ; 176 | count <= count - 1; 177 | end 178 | STATE_WACK_2: begin 179 | i2c_scl_reg <= 0; 180 | if(saved_rw) begin // read 181 | // if we're reading, we have to do the ack 182 | i2c_sda_tri <= 0; 183 | // set the data ready pin 184 | data_ready <= 1; 185 | data_out <= saved_data; 186 | end else begin // write 187 | // allow slave to do ack 188 | if(saved_packets > 0) 189 | data_req <= 1; 190 | i2c_sda_tri <= 1; 191 | end 192 | state <= STATE_WACK_2_BIT; 193 | end 194 | STATE_WACK_2_BIT: begin 195 | i2c_scl_reg <= 1; 196 | count <= 7; 197 | data_ready <= 0; 198 | data_req <= 0; 199 | 200 | if(saved_packets == 0) begin 201 | state <= STATE_STOP; 202 | end 203 | else begin 204 | if(saved_rw) begin 205 | state <= STATE_DATA_READ; 206 | end else begin 207 | saved_data <= data; 208 | if(data_req == 0) 209 | state <= STATE_DATA_WRITE; 210 | end 211 | end 212 | end 213 | // stop is sda low to high while clock is high 214 | STATE_STOP: begin 215 | i2c_scl_reg <= 0; 216 | i2c_sda_tri <= 0; 217 | state <= STATE_STOP_BIT_1; 218 | end 219 | STATE_STOP_BIT_1: begin 220 | i2c_scl_reg <= 1; 221 | state <= STATE_STOP_BIT_2; 222 | end 223 | STATE_STOP_BIT_2: begin 224 | i2c_sda_tri <= 1; 225 | state <= STATE_IDLE; 226 | end 227 | endcase 228 | end 229 | end 230 | endmodule 231 | -------------------------------------------------------------------------------- /docs/overview.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 31 | 37 | 38 | 41 | 48 | 49 | 52 | 59 | 60 | 67 | 73 | 74 | 81 | 87 | 88 | 89 | 107 | 114 | 115 | 117 | 118 | 120 | image/svg+xml 121 | 123 | 124 | 125 | 126 | 127 | 132 | FPGA 144 | 154 | 162 | 172 | Infra red can 184 | 195 | IR camera 207 | 215 | Display 237 | 248 | DVI 260 | I2C 272 | 277 | FPGA Virtual Graffiti 289 | Matt Venn 2016-2017matt@mattvenn.nethttp://bit.ly/fpga-vg 311 | 326 | 327 | 328 | -------------------------------------------------------------------------------- /button-pcb/buttonpcb.kicad_pcb: -------------------------------------------------------------------------------- 1 | (kicad_pcb (version 20170123) (host pcbnew no-vcs-found-7475836~58~ubuntu14.04.1) 2 | 3 | (general 4 | (links 14) 5 | (no_connects 1) 6 | (area 155.8285 64.892 181.258334 130.24376) 7 | (thickness 1.6) 8 | (drawings 12) 9 | (tracks 93) 10 | (zones 0) 11 | (modules 11) 12 | (nets 9) 13 | ) 14 | 15 | (page A4) 16 | (layers 17 | (0 F.Cu signal hide) 18 | (31 B.Cu signal) 19 | (32 B.Adhes user) 20 | (33 F.Adhes user) 21 | (34 B.Paste user) 22 | (35 F.Paste user) 23 | (36 B.SilkS user) 24 | (37 F.SilkS user) 25 | (38 B.Mask user) 26 | (39 F.Mask user) 27 | (40 Dwgs.User user) 28 | (41 Cmts.User user) 29 | (42 Eco1.User user) 30 | (43 Eco2.User user) 31 | (44 Edge.Cuts user) 32 | (45 Margin user) 33 | (46 B.CrtYd user) 34 | (47 F.CrtYd user) 35 | (48 B.Fab user) 36 | (49 F.Fab user) 37 | ) 38 | 39 | (setup 40 | (last_trace_width 0.35) 41 | (trace_clearance 0.35) 42 | (zone_clearance 0.6) 43 | (zone_45_only no) 44 | (trace_min 0.2) 45 | (segment_width 0.2) 46 | (edge_width 0.15) 47 | (via_size 1.2) 48 | (via_drill 0.6) 49 | (via_min_size 0.4) 50 | (via_min_drill 0.3) 51 | (uvia_size 0.3) 52 | (uvia_drill 0.1) 53 | (uvias_allowed no) 54 | (uvia_min_size 0.2) 55 | (uvia_min_drill 0.1) 56 | (pcb_text_width 0.3) 57 | (pcb_text_size 1.5 1.5) 58 | (mod_edge_width 0.15) 59 | (mod_text_size 1 1) 60 | (mod_text_width 0.15) 61 | (pad_size 1.524 1.524) 62 | (pad_drill 0.762) 63 | (pad_to_mask_clearance 0.2) 64 | (aux_axis_origin 0 0) 65 | (visible_elements FFFFEF7F) 66 | (pcbplotparams 67 | (layerselection 0x00000_fffffffe) 68 | (usegerberextensions false) 69 | (excludeedgelayer true) 70 | (linewidth 0.100000) 71 | (plotframeref false) 72 | (viasonmask false) 73 | (mode 1) 74 | (useauxorigin false) 75 | (hpglpennumber 1) 76 | (hpglpenspeed 20) 77 | (hpglpendiameter 15) 78 | (psnegative false) 79 | (psa4output false) 80 | (plotreference true) 81 | (plotvalue true) 82 | (plotinvisibletext false) 83 | (padsonsilk false) 84 | (subtractmaskfromsilk false) 85 | (outputformat 5) 86 | (mirror false) 87 | (drillshape 1) 88 | (scaleselection 1) 89 | (outputdirectory fab/)) 90 | ) 91 | 92 | (net 0 "") 93 | (net 1 Earth) 94 | (net 2 "Net-(D1-Pad2)") 95 | (net 3 /b2) 96 | (net 4 /b1) 97 | (net 5 /led) 98 | (net 6 VCC) 99 | (net 7 "Net-(D2-Pad2)") 100 | (net 8 /led2) 101 | 102 | (net_class Default "This is the default net class." 103 | (clearance 0.35) 104 | (trace_width 0.35) 105 | (via_dia 1.2) 106 | (via_drill 0.6) 107 | (uvia_dia 0.3) 108 | (uvia_drill 0.1) 109 | (add_net /b1) 110 | (add_net /b2) 111 | (add_net /led) 112 | (add_net /led2) 113 | (add_net Earth) 114 | (add_net "Net-(D1-Pad2)") 115 | (add_net "Net-(D2-Pad2)") 116 | (add_net VCC) 117 | ) 118 | 119 | (module Mounting_Holes:MountingHole_3mm (layer F.Cu) (tedit 0) (tstamp 59CA68A5) 120 | (at 168 124) 121 | (descr "Mounting hole, Befestigungsbohrung, 3mm, No Annular, Kein Restring,") 122 | (tags "Mounting hole, Befestigungsbohrung, 3mm, No Annular, Kein Restring,") 123 | (fp_text reference REF** (at 0 -4.0005) (layer F.SilkS) 124 | (effects (font (size 1 1) (thickness 0.15))) 125 | ) 126 | (fp_text value MountingHole_3mm (at 1.00076 5.00126) (layer F.Fab) 127 | (effects (font (size 1 1) (thickness 0.15))) 128 | ) 129 | (fp_circle (center 0 0) (end 3 0) (layer Cmts.User) (width 0.381)) 130 | (pad 1 thru_hole circle (at 0 0) (size 3 3) (drill 3) (layers)) 131 | ) 132 | 133 | (module Mounting_Holes:MountingHole_3mm (layer F.Cu) (tedit 0) (tstamp 59CA68A3) 134 | (at 168 70) 135 | (descr "Mounting hole, Befestigungsbohrung, 3mm, No Annular, Kein Restring,") 136 | (tags "Mounting hole, Befestigungsbohrung, 3mm, No Annular, Kein Restring,") 137 | (fp_text reference REF** (at 0 -4.0005) (layer F.SilkS) 138 | (effects (font (size 1 1) (thickness 0.15))) 139 | ) 140 | (fp_text value MountingHole_3mm (at 1.00076 5.00126) (layer F.Fab) 141 | (effects (font (size 1 1) (thickness 0.15))) 142 | ) 143 | (fp_circle (center 0 0) (end 3 0) (layer Cmts.User) (width 0.381)) 144 | (pad 1 thru_hole circle (at 0 0) (size 3 3) (drill 3) (layers)) 145 | ) 146 | 147 | (module Pin_Headers:Pin_Header_Straight_1x06 (layer F.Cu) (tedit 0) (tstamp 59C6FC75) 148 | (at 176 90.88) 149 | (descr "Through hole pin header") 150 | (tags "pin header") 151 | (path /59BFFE46) 152 | (fp_text reference Pmod1 (at 0 -5.1) (layer F.SilkS) 153 | (effects (font (size 1 1) (thickness 0.15))) 154 | ) 155 | (fp_text value CONN_01X06 (at 0 -3.1) (layer F.Fab) 156 | (effects (font (size 1 1) (thickness 0.15))) 157 | ) 158 | (fp_line (start -1.75 -1.75) (end -1.75 14.45) (layer F.CrtYd) (width 0.05)) 159 | (fp_line (start 1.75 -1.75) (end 1.75 14.45) (layer F.CrtYd) (width 0.05)) 160 | (fp_line (start -1.75 -1.75) (end 1.75 -1.75) (layer F.CrtYd) (width 0.05)) 161 | (fp_line (start -1.75 14.45) (end 1.75 14.45) (layer F.CrtYd) (width 0.05)) 162 | (fp_line (start 1.27 1.27) (end 1.27 13.97) (layer F.SilkS) (width 0.15)) 163 | (fp_line (start 1.27 13.97) (end -1.27 13.97) (layer F.SilkS) (width 0.15)) 164 | (fp_line (start -1.27 13.97) (end -1.27 1.27) (layer F.SilkS) (width 0.15)) 165 | (fp_line (start 1.55 -1.55) (end 1.55 0) (layer F.SilkS) (width 0.15)) 166 | (fp_line (start 1.27 1.27) (end -1.27 1.27) (layer F.SilkS) (width 0.15)) 167 | (fp_line (start -1.55 0) (end -1.55 -1.55) (layer F.SilkS) (width 0.15)) 168 | (fp_line (start -1.55 -1.55) (end 1.55 -1.55) (layer F.SilkS) (width 0.15)) 169 | (pad 1 thru_hole rect (at 0 0) (size 2.032 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS) 170 | (net 3 /b2)) 171 | (pad 2 thru_hole oval (at 0 2.54) (size 2.032 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS) 172 | (net 4 /b1)) 173 | (pad 3 thru_hole oval (at 0 5.08) (size 2.032 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS) 174 | (net 8 /led2)) 175 | (pad 4 thru_hole oval (at 0 7.62) (size 2.032 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS) 176 | (net 5 /led)) 177 | (pad 5 thru_hole oval (at 0 10.16) (size 2.032 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS) 178 | (net 1 Earth)) 179 | (pad 6 thru_hole oval (at 0 12.7) (size 2.032 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS) 180 | (net 6 VCC)) 181 | (model Pin_Headers.3dshapes/Pin_Header_Straight_1x06.wrl 182 | (at (xyz 0 -0.25 0)) 183 | (scale (xyz 1 1 1)) 184 | (rotate (xyz 0 0 90)) 185 | ) 186 | ) 187 | 188 | (module Resistors_SMD:R_1206_HandSoldering (layer B.Cu) (tedit 5418A20D) (tstamp 59C6FC81) 189 | (at 168 102 180) 190 | (descr "Resistor SMD 1206, hand soldering") 191 | (tags "resistor 1206") 192 | (path /59C002CF) 193 | (attr smd) 194 | (fp_text reference R1 (at 0 2.3 180) (layer B.SilkS) 195 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 196 | ) 197 | (fp_text value R (at 0 -2.3 180) (layer B.Fab) 198 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 199 | ) 200 | (fp_line (start -3.3 1.2) (end 3.3 1.2) (layer B.CrtYd) (width 0.05)) 201 | (fp_line (start -3.3 -1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 202 | (fp_line (start -3.3 1.2) (end -3.3 -1.2) (layer B.CrtYd) (width 0.05)) 203 | (fp_line (start 3.3 1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 204 | (fp_line (start 1 -1.075) (end -1 -1.075) (layer B.SilkS) (width 0.15)) 205 | (fp_line (start -1 1.075) (end 1 1.075) (layer B.SilkS) (width 0.15)) 206 | (pad 1 smd rect (at -2 0 180) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 207 | (net 5 /led)) 208 | (pad 2 smd rect (at 2 0 180) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 209 | (net 2 "Net-(D1-Pad2)")) 210 | (model Resistors_SMD.3dshapes/R_1206_HandSoldering.wrl 211 | (at (xyz 0 0 0)) 212 | (scale (xyz 1 1 1)) 213 | (rotate (xyz 0 0 0)) 214 | ) 215 | ) 216 | 217 | (module Resistors_SMD:R_1206_HandSoldering (layer B.Cu) (tedit 5418A20D) (tstamp 59C6FC8D) 218 | (at 168 91.5) 219 | (descr "Resistor SMD 1206, hand soldering") 220 | (tags "resistor 1206") 221 | (path /59C000FB) 222 | (attr smd) 223 | (fp_text reference R2 (at 0 2.3 -90) (layer B.SilkS) 224 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 225 | ) 226 | (fp_text value R (at 0 -2.3) (layer B.Fab) 227 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 228 | ) 229 | (fp_line (start -3.3 1.2) (end 3.3 1.2) (layer B.CrtYd) (width 0.05)) 230 | (fp_line (start -3.3 -1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 231 | (fp_line (start -3.3 1.2) (end -3.3 -1.2) (layer B.CrtYd) (width 0.05)) 232 | (fp_line (start 3.3 1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 233 | (fp_line (start 1 -1.075) (end -1 -1.075) (layer B.SilkS) (width 0.15)) 234 | (fp_line (start -1 1.075) (end 1 1.075) (layer B.SilkS) (width 0.15)) 235 | (pad 1 smd rect (at -2 0) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 236 | (net 6 VCC)) 237 | (pad 2 smd rect (at 2 0) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 238 | (net 3 /b2)) 239 | (model Resistors_SMD.3dshapes/R_1206_HandSoldering.wrl 240 | (at (xyz 0 0 0)) 241 | (scale (xyz 1 1 1)) 242 | (rotate (xyz 0 0 0)) 243 | ) 244 | ) 245 | 246 | (module Resistors_SMD:R_1206_HandSoldering (layer B.Cu) (tedit 5418A20D) (tstamp 59C6FC99) 247 | (at 168 95) 248 | (descr "Resistor SMD 1206, hand soldering") 249 | (tags "resistor 1206") 250 | (path /59C00139) 251 | (attr smd) 252 | (fp_text reference R3 (at 0 2.3) (layer B.SilkS) 253 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 254 | ) 255 | (fp_text value R (at 0 -2.3) (layer B.Fab) 256 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 257 | ) 258 | (fp_line (start -1 1.075) (end 1 1.075) (layer B.SilkS) (width 0.15)) 259 | (fp_line (start 1 -1.075) (end -1 -1.075) (layer B.SilkS) (width 0.15)) 260 | (fp_line (start 3.3 1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 261 | (fp_line (start -3.3 1.2) (end -3.3 -1.2) (layer B.CrtYd) (width 0.05)) 262 | (fp_line (start -3.3 -1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 263 | (fp_line (start -3.3 1.2) (end 3.3 1.2) (layer B.CrtYd) (width 0.05)) 264 | (pad 2 smd rect (at 2 0) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 265 | (net 4 /b1)) 266 | (pad 1 smd rect (at -2 0) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 267 | (net 6 VCC)) 268 | (model Resistors_SMD.3dshapes/R_1206_HandSoldering.wrl 269 | (at (xyz 0 0 0)) 270 | (scale (xyz 1 1 1)) 271 | (rotate (xyz 0 0 0)) 272 | ) 273 | ) 274 | 275 | (module fp:CHERRY_MX (layer F.Cu) (tedit 5852AEB5) (tstamp 59C6FCB2) 276 | (at 168 82) 277 | (path /59BFFF76) 278 | (fp_text reference SW1 (at 0 3.175) (layer F.SilkS) 279 | (effects (font (size 1.27 1.524) (thickness 0.2032))) 280 | ) 281 | (fp_text value SW_PUSH (at 0 5.08) (layer F.SilkS) hide 282 | (effects (font (size 1.27 1.524) (thickness 0.2032))) 283 | ) 284 | (fp_line (start -6.35 -6.35) (end 6.35 -6.35) (layer Cmts.User) (width 0.1524)) 285 | (fp_line (start 6.35 -6.35) (end 6.35 6.35) (layer Cmts.User) (width 0.1524)) 286 | (fp_line (start 6.35 6.35) (end -6.35 6.35) (layer Cmts.User) (width 0.1524)) 287 | (fp_line (start -6.35 6.35) (end -6.35 -6.35) (layer Cmts.User) (width 0.1524)) 288 | (fp_line (start -6.35 -6.35) (end -4.572 -6.35) (layer F.SilkS) (width 0.381)) 289 | (fp_line (start 4.572 -6.35) (end 6.35 -6.35) (layer F.SilkS) (width 0.381)) 290 | (fp_line (start 6.35 -6.35) (end 6.35 -4.572) (layer F.SilkS) (width 0.381)) 291 | (fp_line (start 6.35 4.572) (end 6.35 6.35) (layer F.SilkS) (width 0.381)) 292 | (fp_line (start 6.35 6.35) (end 4.572 6.35) (layer F.SilkS) (width 0.381)) 293 | (fp_line (start -4.572 6.35) (end -6.35 6.35) (layer F.SilkS) (width 0.381)) 294 | (fp_line (start -6.35 6.35) (end -6.35 4.572) (layer F.SilkS) (width 0.381)) 295 | (fp_line (start -6.35 -4.572) (end -6.35 -6.35) (layer F.SilkS) (width 0.381)) 296 | (fp_line (start -6.985 -6.985) (end 6.985 -6.985) (layer Eco2.User) (width 0.1524)) 297 | (fp_line (start 6.985 -6.985) (end 6.985 6.985) (layer Eco2.User) (width 0.1524)) 298 | (fp_line (start 6.985 6.985) (end -6.985 6.985) (layer Eco2.User) (width 0.1524)) 299 | (fp_line (start -6.985 6.985) (end -6.985 -6.985) (layer Eco2.User) (width 0.1524)) 300 | (pad 1 thru_hole circle (at 2.54 -5.08) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.SilkS *.Mask) 301 | (net 3 /b2)) 302 | (pad 2 thru_hole circle (at -3.81 -2.54) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.SilkS *.Mask) 303 | (net 1 Earth)) 304 | (pad "" np_thru_hole circle (at 0 0) (size 3.9878 3.9878) (drill 3.9878) (layers *.Cu *.Mask F.SilkS)) 305 | (pad "" np_thru_hole circle (at -5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask F.SilkS)) 306 | (pad "" np_thru_hole circle (at 5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask F.SilkS)) 307 | ) 308 | 309 | (module fp:CHERRY_MX (layer F.Cu) (tedit 5852AEB5) (tstamp 59C6FCCB) 310 | (at 168 112) 311 | (path /59BFFFF6) 312 | (fp_text reference SW2 (at 0 3.175) (layer F.SilkS) 313 | (effects (font (size 1.27 1.524) (thickness 0.2032))) 314 | ) 315 | (fp_text value SW_PUSH (at 0 5.08) (layer F.SilkS) hide 316 | (effects (font (size 1.27 1.524) (thickness 0.2032))) 317 | ) 318 | (fp_line (start -6.985 6.985) (end -6.985 -6.985) (layer Eco2.User) (width 0.1524)) 319 | (fp_line (start 6.985 6.985) (end -6.985 6.985) (layer Eco2.User) (width 0.1524)) 320 | (fp_line (start 6.985 -6.985) (end 6.985 6.985) (layer Eco2.User) (width 0.1524)) 321 | (fp_line (start -6.985 -6.985) (end 6.985 -6.985) (layer Eco2.User) (width 0.1524)) 322 | (fp_line (start -6.35 -4.572) (end -6.35 -6.35) (layer F.SilkS) (width 0.381)) 323 | (fp_line (start -6.35 6.35) (end -6.35 4.572) (layer F.SilkS) (width 0.381)) 324 | (fp_line (start -4.572 6.35) (end -6.35 6.35) (layer F.SilkS) (width 0.381)) 325 | (fp_line (start 6.35 6.35) (end 4.572 6.35) (layer F.SilkS) (width 0.381)) 326 | (fp_line (start 6.35 4.572) (end 6.35 6.35) (layer F.SilkS) (width 0.381)) 327 | (fp_line (start 6.35 -6.35) (end 6.35 -4.572) (layer F.SilkS) (width 0.381)) 328 | (fp_line (start 4.572 -6.35) (end 6.35 -6.35) (layer F.SilkS) (width 0.381)) 329 | (fp_line (start -6.35 -6.35) (end -4.572 -6.35) (layer F.SilkS) (width 0.381)) 330 | (fp_line (start -6.35 6.35) (end -6.35 -6.35) (layer Cmts.User) (width 0.1524)) 331 | (fp_line (start 6.35 6.35) (end -6.35 6.35) (layer Cmts.User) (width 0.1524)) 332 | (fp_line (start 6.35 -6.35) (end 6.35 6.35) (layer Cmts.User) (width 0.1524)) 333 | (fp_line (start -6.35 -6.35) (end 6.35 -6.35) (layer Cmts.User) (width 0.1524)) 334 | (pad "" np_thru_hole circle (at 5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask F.SilkS)) 335 | (pad "" np_thru_hole circle (at -5.08 0) (size 1.7018 1.7018) (drill 1.7018) (layers *.Cu *.Mask F.SilkS)) 336 | (pad "" np_thru_hole circle (at 0 0) (size 3.9878 3.9878) (drill 3.9878) (layers *.Cu *.Mask F.SilkS)) 337 | (pad 2 thru_hole circle (at -3.81 -2.54) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.SilkS *.Mask) 338 | (net 1 Earth)) 339 | (pad 1 thru_hole circle (at 2.54 -5.08) (size 2.286 2.286) (drill 1.4986) (layers *.Cu *.SilkS *.Mask) 340 | (net 4 /b1)) 341 | ) 342 | 343 | (module Resistors_SMD:R_1206_HandSoldering (layer B.Cu) (tedit 5418A20D) (tstamp 59CA67D5) 344 | (at 168 98.5 180) 345 | (descr "Resistor SMD 1206, hand soldering") 346 | (tags "resistor 1206") 347 | (path /59C00518) 348 | (attr smd) 349 | (fp_text reference R4 (at 0 2.3 180) (layer B.SilkS) 350 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 351 | ) 352 | (fp_text value R (at 0 -2.3 180) (layer B.Fab) 353 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 354 | ) 355 | (fp_line (start -3.3 1.2) (end 3.3 1.2) (layer B.CrtYd) (width 0.05)) 356 | (fp_line (start -3.3 -1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 357 | (fp_line (start -3.3 1.2) (end -3.3 -1.2) (layer B.CrtYd) (width 0.05)) 358 | (fp_line (start 3.3 1.2) (end 3.3 -1.2) (layer B.CrtYd) (width 0.05)) 359 | (fp_line (start 1 -1.075) (end -1 -1.075) (layer B.SilkS) (width 0.15)) 360 | (fp_line (start -1 1.075) (end 1 1.075) (layer B.SilkS) (width 0.15)) 361 | (pad 1 smd rect (at -2 0 180) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 362 | (net 8 /led2)) 363 | (pad 2 smd rect (at 2 0 180) (size 2 1.7) (layers B.Cu B.Paste B.Mask) 364 | (net 7 "Net-(D2-Pad2)")) 365 | (model Resistors_SMD.3dshapes/R_1206_HandSoldering.wrl 366 | (at (xyz 0 0 0)) 367 | (scale (xyz 1 1 1)) 368 | (rotate (xyz 0 0 0)) 369 | ) 370 | ) 371 | 372 | (module LEDs:LED-5MM (layer B.Cu) (tedit 5570F7EA) (tstamp 59CC2088) 373 | (at 161 125.12014 90) 374 | (descr "LED 5mm round vertical") 375 | (tags "LED 5mm round vertical") 376 | (path /59C001F0) 377 | (fp_text reference D1 (at 1.524 -4.064 90) (layer B.SilkS) 378 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 379 | ) 380 | (fp_text value LED (at 1.524 3.937 90) (layer B.Fab) 381 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 382 | ) 383 | (fp_line (start -1.5 1.55) (end -1.5 -1.55) (layer B.CrtYd) (width 0.05)) 384 | (fp_arc (start 1.3 0) (end -1.5 -1.55) (angle 302) (layer B.CrtYd) (width 0.05)) 385 | (fp_arc (start 1.27 0) (end -1.23 1.5) (angle -297.5) (layer B.SilkS) (width 0.15)) 386 | (fp_line (start -1.23 -1.5) (end -1.23 1.5) (layer B.SilkS) (width 0.15)) 387 | (fp_circle (center 1.27 0) (end 0.97 2.5) (layer B.SilkS) (width 0.15)) 388 | (fp_text user K (at -1.905 -1.905 90) (layer B.SilkS) 389 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 390 | ) 391 | (pad 1 thru_hole rect (at 0 0) (size 2 1.9) (drill 1.00076) (layers *.Cu *.Mask B.SilkS) 392 | (net 1 Earth)) 393 | (pad 2 thru_hole circle (at 2.54 0 90) (size 1.9 1.9) (drill 1.00076) (layers *.Cu *.Mask B.SilkS) 394 | (net 2 "Net-(D1-Pad2)")) 395 | (model LEDs.3dshapes/LED-5MM.wrl 396 | (at (xyz 0.05 0 0)) 397 | (scale (xyz 1 1 1)) 398 | (rotate (xyz 0 0 90)) 399 | ) 400 | ) 401 | 402 | (module LEDs:LED-5MM (layer B.Cu) (tedit 5570F7EA) (tstamp 59CC2093) 403 | (at 175 125 90) 404 | (descr "LED 5mm round vertical") 405 | (tags "LED 5mm round vertical") 406 | (path /59C00512) 407 | (fp_text reference D2 (at 1.524 -4.064 90) (layer B.SilkS) 408 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 409 | ) 410 | (fp_text value LED (at 1.524 3.937 90) (layer B.Fab) 411 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 412 | ) 413 | (fp_text user K (at -1.905 -1.905 90) (layer B.SilkS) 414 | (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) 415 | ) 416 | (fp_circle (center 1.27 0) (end 0.97 2.5) (layer B.SilkS) (width 0.15)) 417 | (fp_line (start -1.23 -1.5) (end -1.23 1.5) (layer B.SilkS) (width 0.15)) 418 | (fp_arc (start 1.27 0) (end -1.23 1.5) (angle -297.5) (layer B.SilkS) (width 0.15)) 419 | (fp_arc (start 1.3 0) (end -1.5 -1.55) (angle 302) (layer B.CrtYd) (width 0.05)) 420 | (fp_line (start -1.5 1.55) (end -1.5 -1.55) (layer B.CrtYd) (width 0.05)) 421 | (pad 2 thru_hole circle (at 2.54 0 90) (size 1.9 1.9) (drill 1.00076) (layers *.Cu *.Mask B.SilkS) 422 | (net 7 "Net-(D2-Pad2)")) 423 | (pad 1 thru_hole rect (at 0 0) (size 2 1.9) (drill 1.00076) (layers *.Cu *.Mask B.SilkS) 424 | (net 1 Earth)) 425 | (model LEDs.3dshapes/LED-5MM.wrl 426 | (at (xyz 0.05 0 0)) 427 | (scale (xyz 1 1 1)) 428 | (rotate (xyz 0 0 90)) 429 | ) 430 | ) 431 | 432 | (gr_text bot (at 174 70 90) (layer B.Cu) 433 | (effects (font (size 1.5 1.5) (thickness 0.3)) (justify mirror)) 434 | ) 435 | (gr_line (start 178 66) (end 178 66) (layer Edge.Cuts) (width 0.15) (tstamp 59CA6B75)) 436 | (gr_line (start 177 65) (end 178 66) (layer Edge.Cuts) (width 0.15)) 437 | (gr_line (start 158 128) (end 158 128) (layer Edge.Cuts) (width 0.15) (tstamp 59CA6B72)) 438 | (gr_line (start 159 129) (end 158 128) (layer Edge.Cuts) (width 0.15)) 439 | (gr_line (start 178 128) (end 178 128) (layer Edge.Cuts) (width 0.15) (tstamp 59CA6B6F)) 440 | (gr_line (start 177 129) (end 178 128) (layer Edge.Cuts) (width 0.15)) 441 | (gr_line (start 159 65) (end 158 66) (layer Edge.Cuts) (width 0.15)) 442 | (gr_line (start 158 128) (end 158 66) (layer Edge.Cuts) (width 0.2)) 443 | (gr_line (start 177 129) (end 159 129) (layer Edge.Cuts) (width 0.2)) 444 | (gr_line (start 178 66) (end 178 128) (layer Edge.Cuts) (width 0.2)) 445 | (gr_line (start 159 65) (end 177 65) (layer Edge.Cuts) (width 0.2)) 446 | 447 | (segment (start 165.5 119.5) (end 165.4 119.6) (width 0.35) (layer B.Cu) (net 1)) 448 | (segment (start 165.4 119.6) (end 163.5 121.5) (width 0.35) (layer B.Cu) (net 1)) 449 | (segment (start 162.425431 116.511656) (end 162.425431 116.625431) (width 0.35) (layer B.Cu) (net 1)) 450 | (segment (start 162.425431 116.625431) (end 165.4 119.6) (width 0.35) (layer B.Cu) (net 1)) 451 | (segment (start 163.5 123.02146) (end 163.14868 123.02146) (width 0.35) (layer B.Cu) (net 1)) 452 | (segment (start 163.14868 123.02146) (end 161.05 125.12014) (width 0.35) (layer B.Cu) (net 1)) 453 | (segment (start 161.05 125.12014) (end 161 125.12014) (width 0.35) (layer B.Cu) (net 1)) 454 | (segment (start 175 125) (end 173.65 125) (width 0.35) (layer B.Cu) (net 1)) 455 | (segment (start 173.65 125) (end 172.32029 123.67029) (width 0.35) (layer B.Cu) (net 1)) 456 | (segment (start 172.32029 123.67029) (end 172 123.67029) (width 0.35) (layer B.Cu) (net 1)) 457 | (segment (start 160.500022 114.586247) (end 162.425431 116.511656) (width 0.35) (layer B.Cu) (net 1)) 458 | (segment (start 160.500022 81.533532) (end 160.500022 114.586247) (width 0.35) (layer B.Cu) (net 1)) 459 | (segment (start 162.573554 79.46) (end 160.500022 81.533532) (width 0.35) (layer B.Cu) (net 1)) 460 | (segment (start 164.19 79.46) (end 162.573554 79.46) (width 0.35) (layer B.Cu) (net 1)) 461 | (segment (start 176.5 124.02146) (end 175.1016 125.41986) (width 0.35) (layer B.Cu) (net 1)) 462 | (segment (start 172.5 103.174) (end 176.5 107.174) (width 0.35) (layer B.Cu) (net 1)) 463 | (segment (start 176.5 107.174) (end 176.5 124.02146) (width 0.35) (layer B.Cu) (net 1)) 464 | (segment (start 175.1016 125.41986) (end 175 125.41986) (width 0.35) (layer B.Cu) (net 1)) 465 | (segment (start 172.5 103.174) (end 172.298999 103.375001) (width 0.35) (layer B.Cu) (net 1)) 466 | (segment (start 174.634 101.04) (end 172.5 103.174) (width 0.35) (layer B.Cu) (net 1)) 467 | (segment (start 176 101.04) (end 174.634 101.04) (width 0.35) (layer B.Cu) (net 1)) 468 | (segment (start 172.298999 103.375001) (end 170.274999 103.375001) (width 0.35) (layer B.Cu) (net 1)) 469 | (segment (start 161.1016 125.41986) (end 161 125.41986) (width 0.35) (layer B.Cu) (net 1)) 470 | (segment (start 163.5 121.5) (end 163.5 123.02146) (width 0.35) (layer B.Cu) (net 1)) 471 | (segment (start 171 119.5) (end 165.5 119.5) (width 0.35) (layer B.Cu) (net 1)) 472 | (segment (start 172 120.5) (end 171 119.5) (width 0.35) (layer B.Cu) (net 1)) 473 | (segment (start 172 123.67029) (end 172 120.5) (width 0.35) (layer B.Cu) (net 1)) 474 | (segment (start 170.274999 103.375001) (end 165.332999 108.317001) (width 0.35) (layer B.Cu) (net 1)) 475 | (segment (start 165.332999 108.317001) (end 164.19 109.46) (width 0.35) (layer B.Cu) (net 1)) 476 | (segment (start 161 122.58014) (end 161 117) (width 0.35) (layer B.Cu) (net 2)) 477 | (segment (start 164.990641 77.791999) (end 165.858001 78.659359) (width 0.35) (layer B.Cu) (net 2)) 478 | (segment (start 165.858001 78.659359) (end 165.858001 80.414025) (width 0.35) (layer B.Cu) (net 2)) 479 | (segment (start 159.800011 81.243581) (end 163.251593 77.791999) (width 0.35) (layer B.Cu) (net 2)) 480 | (segment (start 161 117) (end 159.800011 115.80001) (width 0.35) (layer B.Cu) (net 2)) 481 | (segment (start 159.800011 115.80001) (end 159.800011 81.243581) (width 0.35) (layer B.Cu) (net 2)) 482 | (segment (start 163.251593 77.791999) (end 164.990641 77.791999) (width 0.35) (layer B.Cu) (net 2)) 483 | (segment (start 164.474999 81.797027) (end 164.474999 95.5) (width 0.35) (layer B.Cu) (net 2)) 484 | (segment (start 165.858001 80.414025) (end 164.474999 81.797027) (width 0.35) (layer B.Cu) (net 2)) 485 | (segment (start 164.474999 95.5) (end 164.474999 95.525001) (width 0.35) (layer B.Cu) (net 2)) 486 | (segment (start 168 101.35) (end 168 97.704998) (width 0.35) (layer B.Cu) (net 2)) 487 | (segment (start 168 97.704998) (end 166.670003 96.375001) (width 0.35) (layer B.Cu) (net 2)) 488 | (segment (start 166.670003 96.375001) (end 164.579999 96.375001) (width 0.35) (layer B.Cu) (net 2)) 489 | (segment (start 164.579999 96.375001) (end 164.474999 96.270001) (width 0.35) (layer B.Cu) (net 2)) 490 | (segment (start 164.474999 96.270001) (end 164.474999 95.5) (width 0.35) (layer B.Cu) (net 2)) 491 | (segment (start 166 102) (end 167.35 102) (width 0.35) (layer B.Cu) (net 2)) 492 | (segment (start 167.35 102) (end 168 101.35) (width 0.35) (layer B.Cu) (net 2)) 493 | (segment (start 170 91.5) (end 175.38 91.5) (width 0.35) (layer B.Cu) (net 3)) 494 | (segment (start 175.38 91.5) (end 176 90.88) (width 0.35) (layer B.Cu) (net 3)) 495 | (segment (start 170.54 76.92) (end 171.682999 78.062999) (width 0.35) (layer B.Cu) (net 3)) 496 | (segment (start 171.682999 78.062999) (end 171.682999 88.617001) (width 0.35) (layer B.Cu) (net 3)) 497 | (segment (start 171.682999 88.617001) (end 170 90.3) (width 0.35) (layer B.Cu) (net 3)) 498 | (segment (start 170 90.3) (end 170 91.5) (width 0.35) (layer B.Cu) (net 3)) 499 | (segment (start 170 95) (end 174.42 95) (width 0.35) (layer B.Cu) (net 4)) 500 | (segment (start 174.42 95) (end 174.634 94.786) (width 0.35) (layer B.Cu) (net 4)) 501 | (segment (start 174.634 94.786) (end 174.634 94.6336) (width 0.35) (layer B.Cu) (net 4)) 502 | (segment (start 174.634 94.6336) (end 175.8476 93.42) (width 0.35) (layer B.Cu) (net 4)) 503 | (segment (start 175.8476 93.42) (end 176 93.42) (width 0.35) (layer B.Cu) (net 4)) 504 | (segment (start 170.96 94.04) (end 170 95) (width 0.35) (layer B.Cu) (net 4)) 505 | (segment (start 170 102) (end 170.15 102) (width 0.35) (layer B.Cu) (net 5)) 506 | (segment (start 170.15 102) (end 171.35 100.8) (width 0.35) (layer B.Cu) (net 5)) 507 | (segment (start 171.35 100.8) (end 171.35 100.65) (width 0.35) (layer B.Cu) (net 5)) 508 | (segment (start 171.35 100.65) (end 173.5 98.5) (width 0.35) (layer B.Cu) (net 5)) 509 | (segment (start 173.5 98.5) (end 176 98.5) (width 0.35) (layer B.Cu) (net 5)) 510 | (segment (start 176 103.58) (end 176 104.7936) (width 0.35) (layer B.Cu) (net 6)) 511 | (segment (start 159.1 77.4) (end 160 76.5) (width 0.35) (layer B.Cu) (net 6)) 512 | (segment (start 176 104.7936) (end 177.5 106.2936) (width 0.35) (layer B.Cu) (net 6)) 513 | (segment (start 170.518901 85.781099) (end 166 90.3) (width 0.35) (layer B.Cu) (net 6)) 514 | (segment (start 166 90.3) (end 166 91.5) (width 0.35) (layer B.Cu) (net 6)) 515 | (segment (start 177.5 106.2936) (end 177.5 126.1) (width 0.35) (layer B.Cu) (net 6)) 516 | (segment (start 166.227974 76.5) (end 170.518901 80.790927) (width 0.35) (layer B.Cu) (net 6)) 517 | (segment (start 177.5 126.1) (end 175.6 128) (width 0.35) (layer B.Cu) (net 6)) 518 | (segment (start 159.1 115.889964) (end 159.1 77.4) (width 0.35) (layer B.Cu) (net 6)) 519 | (segment (start 160 76.5) (end 166.227974 76.5) (width 0.35) (layer B.Cu) (net 6)) 520 | (segment (start 175.6 128) (end 160.4 128) (width 0.35) (layer B.Cu) (net 6)) 521 | (segment (start 160.4 128) (end 159 126.6) (width 0.35) (layer B.Cu) (net 6)) 522 | (segment (start 159 126.6) (end 159 115.989964) (width 0.35) (layer B.Cu) (net 6)) 523 | (segment (start 159 115.989964) (end 159.1 115.889964) (width 0.35) (layer B.Cu) (net 6)) 524 | (segment (start 170.518901 80.790927) (end 170.518901 85.781099) (width 0.35) (layer B.Cu) (net 6)) 525 | (segment (start 166 91.5) (end 166 92.7) (width 0.35) (layer B.Cu) (net 6)) 526 | (segment (start 166 92.7) (end 166 95) (width 0.35) (layer B.Cu) (net 6)) 527 | (segment (start 175 122.46) (end 175 121.116498) (width 0.35) (layer B.Cu) (net 7)) 528 | (segment (start 175 121.116498) (end 172.314812 118.43131) (width 0.35) (layer B.Cu) (net 7)) 529 | (segment (start 172.314812 118.43131) (end 166.23131 118.43131) (width 0.35) (layer B.Cu) (net 7)) 530 | (segment (start 166.23131 118.43131) (end 161.544099 113.744099) (width 0.35) (layer B.Cu) (net 7)) 531 | (segment (start 161.544099 113.744099) (end 161.544099 100.355901) (width 0.35) (layer B.Cu) (net 7)) 532 | (segment (start 161.544099 100.355901) (end 163.4 98.5) (width 0.35) (layer B.Cu) (net 7)) 533 | (segment (start 163.4 98.5) (end 166 98.5) (width 0.35) (layer B.Cu) (net 7)) 534 | (segment (start 165.85 98.5) (end 166 98.5) (width 0.35) (layer B.Cu) (net 7)) 535 | (segment (start 170.72 96.58) (end 174.014 96.58) (width 0.35) (layer B.Cu) (net 8)) 536 | (segment (start 174.014 96.58) (end 174.634 95.96) (width 0.35) (layer B.Cu) (net 8)) 537 | (segment (start 174.634 95.96) (end 176 95.96) (width 0.35) (layer B.Cu) (net 8)) 538 | (segment (start 170.72 96.58) (end 170 97.3) (width 0.35) (layer B.Cu) (net 8)) 539 | (segment (start 170 97.3) (end 170 98.5) (width 0.35) (layer B.Cu) (net 8)) 540 | 541 | (zone (net 0) (net_name "") (layer B.Cu) (tstamp 0) (hatch edge 0.508) 542 | (connect_pads (clearance 0.6)) 543 | (min_thickness 0.254) 544 | (fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508)) 545 | (polygon 546 | (pts 547 | (xy 159 66) (xy 177 66) (xy 177 128) (xy 159 128) 548 | ) 549 | ) 550 | (filled_polygon 551 | (pts 552 | (xy 171.098 120.873621) (xy 171.098 123.67029) (xy 171.166661 124.01547) (xy 171.36219 124.3081) (xy 171.65482 124.503629) 553 | (xy 171.933428 124.559048) (xy 173.01219 125.63781) (xy 173.258758 125.802561) (xy 173.258758 125.95) (xy 173.315182 126.233661) 554 | (xy 173.475863 126.474137) (xy 173.716339 126.634818) (xy 174 126.691242) (xy 175.633138 126.691242) (xy 175.22638 127.098) 555 | (xy 160.77362 127.098) (xy 160.487002 126.811382) (xy 162 126.811382) (xy 162.283661 126.754958) (xy 162.524137 126.594277) 556 | (xy 162.684818 126.353801) (xy 162.741242 126.07014) (xy 162.741242 124.704519) (xy 163.004727 124.441034) (xy 165.772614 124.441034) 557 | (xy 166.11094 125.259846) (xy 166.736858 125.886858) (xy 167.555079 126.226613) (xy 168.441034 126.227386) (xy 169.259846 125.88906) 558 | (xy 169.886858 125.263142) (xy 170.226613 124.444921) (xy 170.227386 123.558966) (xy 169.88906 122.740154) (xy 169.263142 122.113142) 559 | (xy 168.444921 121.773387) (xy 167.558966 121.772614) (xy 166.740154 122.11094) (xy 166.113142 122.736858) (xy 165.773387 123.555079) 560 | (xy 165.772614 124.441034) (xy 163.004727 124.441034) (xy 163.527838 123.917923) (xy 163.84518 123.854799) (xy 164.13781 123.65927) 561 | (xy 164.333339 123.36664) (xy 164.402 123.02146) (xy 164.402 121.87362) (xy 165.87362 120.402) (xy 170.62638 120.402) 562 | ) 563 | ) 564 | (filled_polygon 565 | (pts 566 | (xy 173.848152 121.240271) (xy 173.579138 121.508816) (xy 173.323292 122.124961) (xy 173.32271 122.792112) (xy 173.57748 123.408703) 567 | (xy 173.606979 123.438254) (xy 173.475863 123.525863) (xy 173.466098 123.540478) (xy 172.9581 123.03248) (xy 172.902 122.994995) 568 | (xy 172.902 120.5) (xy 172.850879 120.242997) 569 | ) 570 | ) 571 | (filled_polygon 572 | (pts 573 | (xy 164.12438 119.6) (xy 162.86219 120.86219) (xy 162.666661 121.154819) (xy 162.605623 121.461678) (xy 162.598 121.5) 574 | (xy 162.598 122.056131) (xy 162.42252 121.631437) (xy 161.951184 121.159278) (xy 161.902 121.138855) (xy 161.902 117.37762) 575 | ) 576 | ) 577 | (filled_polygon 578 | (pts 579 | (xy 160.098 117.373621) (xy 160.098 121.138323) (xy 160.051297 121.15762) (xy 159.902 121.306657) (xy 159.902 117.177621) 580 | ) 581 | ) 582 | (filled_polygon 583 | (pts 584 | (xy 175.598 107.54762) (xy 175.598 120.438877) (xy 172.952622 117.7935) (xy 172.659993 117.597971) (xy 172.314812 117.52931) 585 | (xy 166.604931 117.52931) (xy 162.653288 113.577668) (xy 163.232487 113.578173) (xy 163.812641 113.338459) (xy 164.256899 112.894976) 586 | (xy 164.497626 112.315241) (xy 164.498173 111.687513) (xy 164.35051 111.33014) (xy 164.560334 111.330323) (xy 165.247886 111.046233) 587 | (xy 165.592906 110.701814) (xy 165.279573 111.456405) (xy 165.278628 112.538846) (xy 165.691988 113.539253) (xy 166.456721 114.305322) 588 | (xy 167.456405 114.720427) (xy 168.538846 114.721372) (xy 169.539253 114.308012) (xy 170.305322 113.543279) (xy 170.720427 112.543595) 589 | (xy 170.720628 112.312487) (xy 171.501827 112.312487) (xy 171.741541 112.892641) (xy 172.185024 113.336899) (xy 172.764759 113.577626) 590 | (xy 173.392487 113.578173) (xy 173.972641 113.338459) (xy 174.416899 112.894976) (xy 174.657626 112.315241) (xy 174.658173 111.687513) 591 | (xy 174.418459 111.107359) (xy 173.974976 110.663101) (xy 173.395241 110.422374) (xy 172.767513 110.421827) (xy 172.187359 110.661541) 592 | (xy 171.743101 111.105024) (xy 171.502374 111.684759) (xy 171.501827 112.312487) (xy 170.720628 112.312487) (xy 170.721372 111.461154) 593 | (xy 170.308012 110.460747) (xy 169.543279 109.694678) (xy 168.543595 109.279573) (xy 167.461154 109.278628) (xy 166.460747 109.691988) 594 | (xy 165.876155 110.27556) (xy 166.059674 109.833598) (xy 166.060323 109.089666) (xy 165.994722 108.930898) (xy 168.877039 106.048582) 595 | (xy 168.670326 106.546402) (xy 168.669677 107.290334) (xy 168.953767 107.977886) (xy 169.479347 108.504384) (xy 170.166402 108.789674) 596 | (xy 170.910334 108.790323) (xy 171.597886 108.506233) (xy 172.124384 107.980653) (xy 172.409674 107.293598) (xy 172.410323 106.549666) 597 | (xy 172.126233 105.862114) (xy 171.600653 105.335616) (xy 170.913598 105.050326) (xy 170.169666 105.049677) (xy 169.669125 105.256496) 598 | (xy 170.64862 104.277001) (xy 172.298999 104.277001) (xy 172.322672 104.272292) 599 | ) 600 | ) 601 | (filled_polygon 602 | (pts 603 | (xy 162.570411 110.437157) (xy 162.446099 110.488522) (xy 162.446099 110.136299) 604 | ) 605 | ) 606 | (filled_polygon 607 | (pts 608 | (xy 164.315182 99.633661) (xy 164.475863 99.874137) (xy 164.716339 100.034818) (xy 165 100.091242) (xy 167 100.091242) 609 | (xy 167.098 100.071748) (xy 167.098 100.428252) (xy 167 100.408758) (xy 165 100.408758) (xy 164.716339 100.465182) 610 | (xy 164.475863 100.625863) (xy 164.315182 100.866339) (xy 164.258758 101.15) (xy 164.258758 102.85) (xy 164.315182 103.133661) 611 | (xy 164.475863 103.374137) (xy 164.716339 103.534818) (xy 165 103.591242) (xy 167 103.591242) (xy 167.283661 103.534818) 612 | (xy 167.524137 103.374137) (xy 167.684818 103.133661) (xy 167.741242 102.85) (xy 167.741242 102.802562) (xy 167.98781 102.63781) 613 | (xy 168.258758 102.366862) (xy 168.258758 102.85) (xy 168.315182 103.133661) (xy 168.475863 103.374137) (xy 168.716339 103.534818) 614 | (xy 168.819117 103.555262) (xy 164.719371 107.655009) (xy 164.563598 107.590326) (xy 163.819666 107.589677) (xy 163.132114 107.873767) 615 | (xy 162.605616 108.399347) (xy 162.446099 108.783507) (xy 162.446099 100.729521) (xy 163.773621 99.402) (xy 164.269102 99.402) 616 | ) 617 | ) 618 | (filled_polygon 619 | (pts 620 | (xy 174.90615 102.31) (xy 174.688729 102.455276) (xy 174.34393 102.971304) (xy 174.222853 103.58) (xy 174.233091 103.631471) 621 | (xy 173.77562 103.174) (xy 174.746377 102.203243) 622 | ) 623 | ) 624 | (filled_polygon 625 | (pts 626 | (xy 174.688729 99.624724) (xy 174.90615 99.77) (xy 174.688729 99.915276) (xy 174.525487 100.159585) (xy 174.28882 100.206661) 627 | (xy 173.99619 100.40219) (xy 171.925379 102.473001) (xy 171.741242 102.473001) (xy 171.741242 101.684379) (xy 171.98781 101.437811) 628 | (xy 172.183339 101.145181) (xy 172.196474 101.079146) (xy 173.87362 99.402) (xy 174.53991 99.402) 629 | ) 630 | ) 631 | (filled_polygon 632 | (pts 633 | (xy 169 100.091242) (xy 170.659369 100.091242) (xy 170.516661 100.304819) (xy 170.503526 100.370853) (xy 170.465621 100.408758) 634 | (xy 169 100.408758) (xy 168.902 100.428252) (xy 168.902 100.071748) 635 | ) 636 | ) 637 | (filled_polygon 638 | (pts 639 | (xy 161.581541 82.892641) (xy 162.025024 83.336899) (xy 162.604759 83.577626) (xy 163.232487 83.578173) (xy 163.572999 83.437477) 640 | (xy 163.572999 96.270001) (xy 163.64166 96.615182) (xy 163.837189 96.907811) (xy 163.942188 97.012811) (xy 164.049814 97.084724) 641 | (xy 164.234819 97.20834) (xy 164.39894 97.240986) (xy 164.315182 97.366339) (xy 164.269102 97.598) (xy 163.4 97.598) 642 | (xy 163.162807 97.645181) (xy 163.054819 97.666661) (xy 162.762189 97.86219) (xy 161.402022 99.222358) (xy 161.402022 82.45817) 643 | ) 644 | ) 645 | (filled_polygon 646 | (pts 647 | (xy 174.90615 97.23) (xy 174.688729 97.375276) (xy 174.53991 97.598) (xy 173.5 97.598) (xy 173.262807 97.645181) 648 | (xy 173.154819 97.666661) (xy 172.86219 97.86219) (xy 171.741242 98.983138) (xy 171.741242 97.65) (xy 171.707825 97.482) 649 | (xy 174.014 97.482) (xy 174.359181 97.413339) (xy 174.65181 97.21781) (xy 174.746377 97.123243) 650 | ) 651 | ) 652 | (filled_polygon 653 | (pts 654 | (xy 170.780999 88.243381) (xy 169.36219 89.66219) (xy 169.197438 89.908758) (xy 169 89.908758) (xy 168.716339 89.965182) 655 | (xy 168.475863 90.125863) (xy 168.315182 90.366339) (xy 168.258758 90.65) (xy 168.258758 92.35) (xy 168.315182 92.633661) 656 | (xy 168.475863 92.874137) (xy 168.716339 93.034818) (xy 169 93.091242) (xy 171 93.091242) (xy 171.283661 93.034818) 657 | (xy 171.524137 92.874137) (xy 171.684818 92.633661) (xy 171.730898 92.402) (xy 174.617418 92.402) (xy 174.34393 92.811304) 658 | (xy 174.222853 93.42) (xy 174.280777 93.711203) (xy 173.99619 93.99579) (xy 173.927895 94.098) (xy 171.850463 94.098) 659 | (xy 171.862 94.04) (xy 171.793339 93.694819) (xy 171.59781 93.40219) (xy 171.305181 93.206661) (xy 170.96 93.138) 660 | (xy 170.614819 93.206661) (xy 170.32219 93.40219) (xy 170.315622 93.408758) (xy 169 93.408758) (xy 168.716339 93.465182) 661 | (xy 168.475863 93.625863) (xy 168.315182 93.866339) (xy 168.258758 94.15) (xy 168.258758 95.85) (xy 168.315182 96.133661) 662 | (xy 168.475863 96.374137) (xy 168.716339 96.534818) (xy 169 96.591242) (xy 169.433138 96.591242) (xy 169.36219 96.66219) 663 | (xy 169.197438 96.908758) (xy 169 96.908758) (xy 168.716339 96.965182) (xy 168.608116 97.037494) (xy 167.688047 96.117425) 664 | (xy 167.741242 95.85) (xy 167.741242 94.15) (xy 167.684818 93.866339) (xy 167.524137 93.625863) (xy 167.283661 93.465182) 665 | (xy 167 93.408758) (xy 166.902 93.408758) (xy 166.902 93.091242) (xy 167 93.091242) (xy 167.283661 93.034818) 666 | (xy 167.524137 92.874137) (xy 167.684818 92.633661) (xy 167.741242 92.35) (xy 167.741242 90.65) (xy 167.684818 90.366339) 667 | (xy 167.524137 90.125863) (xy 167.479549 90.096071) (xy 170.780999 86.794621) 668 | ) 669 | ) 670 | (filled_polygon 671 | (pts 672 | (xy 176.873 89.275158) (xy 174.984 89.275158) (xy 174.700339 89.331582) (xy 174.459863 89.492263) (xy 174.299182 89.732739) 673 | (xy 174.242758 90.0164) (xy 174.242758 90.598) (xy 171.730898 90.598) (xy 171.684818 90.366339) (xy 171.524137 90.125863) 674 | (xy 171.479549 90.096071) (xy 172.320809 89.254811) (xy 172.516338 88.962182) (xy 172.584999 88.617001) (xy 172.584999 83.502983) 675 | (xy 172.764759 83.577626) (xy 173.392487 83.578173) (xy 173.972641 83.338459) (xy 174.416899 82.894976) (xy 174.657626 82.315241) 676 | (xy 174.658173 81.687513) (xy 174.418459 81.107359) (xy 173.974976 80.663101) (xy 173.395241 80.422374) (xy 172.767513 80.421827) 677 | (xy 172.584999 80.49724) (xy 172.584999 78.062999) (xy 172.516338 77.717819) (xy 172.43115 77.590326) (xy 172.341916 77.456777) 678 | (xy 172.409674 77.293598) (xy 172.410323 76.549666) (xy 172.126233 75.862114) (xy 171.600653 75.335616) (xy 170.913598 75.050326) 679 | (xy 170.169666 75.049677) (xy 169.482114 75.333767) (xy 168.955616 75.859347) (xy 168.670326 76.546402) (xy 168.669677 77.290334) 680 | (xy 168.934253 77.930659) (xy 166.865784 75.86219) (xy 166.573155 75.666661) (xy 166.227974 75.598) (xy 160 75.598) 681 | (xy 159.712089 75.65527) (xy 159.654819 75.666661) (xy 159.36219 75.86219) (xy 159.127 76.09738) (xy 159.127 70.441034) 682 | (xy 165.772614 70.441034) (xy 166.11094 71.259846) (xy 166.736858 71.886858) (xy 167.555079 72.226613) (xy 168.441034 72.227386) 683 | (xy 169.259846 71.88906) (xy 169.886858 71.263142) (xy 170.226613 70.444921) (xy 170.227386 69.558966) (xy 169.88906 68.740154) 684 | (xy 169.263142 68.113142) (xy 168.444921 67.773387) (xy 167.558966 67.772614) (xy 166.740154 68.11094) (xy 166.113142 68.736858) 685 | (xy 165.773387 69.555079) (xy 165.772614 70.441034) (xy 159.127 70.441034) (xy 159.127 67.337285) (xy 172.118 67.337285) 686 | (xy 172.118 72.662714) (xy 176.122 72.662714) (xy 176.122 67.337285) (xy 172.118 67.337285) (xy 159.127 67.337285) 687 | (xy 159.127 66.127) (xy 176.873 66.127) 688 | ) 689 | ) 690 | (filled_polygon 691 | (pts 692 | (xy 165.691988 83.539253) (xy 166.456721 84.305322) (xy 167.456405 84.720427) (xy 168.538846 84.721372) (xy 169.539253 84.308012) 693 | (xy 169.616901 84.230499) (xy 169.616901 85.407479) (xy 165.376999 89.647381) (xy 165.376999 82.776922) 694 | ) 695 | ) 696 | (filled_polygon 697 | (pts 698 | (xy 170.166402 78.789674) (xy 170.780999 78.79021) (xy 170.780999 79.777405) (xy 169.528309 78.524715) 699 | ) 700 | ) 701 | (filled_polygon 702 | (pts 703 | (xy 160.002 79.765972) (xy 160.002 77.77362) (xy 160.37362 77.402) (xy 162.365972 77.402) 704 | ) 705 | ) 706 | (filled_polygon 707 | (pts 708 | (xy 167.731218 79.278864) (xy 167.461154 79.278628) (xy 166.760001 79.568339) (xy 166.760001 78.659359) (xy 166.69134 78.314179) 709 | (xy 166.69134 78.314178) (xy 166.539928 78.087574) 710 | ) 711 | ) 712 | ) 713 | ) 714 | --------------------------------------------------------------------------------