├── .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 | 
9 |
10 | Drawn using Bresenham's algorithm, adapted for integer maths: [line.py](line.py)
11 |
12 | 
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 | | {{ module.name }} |
12 |
13 |
14 |
15 |
16 | {% for in, out in module.zip_ports() %}
17 |
18 | | {{in.name}} | // in ports
19 | | // separator
20 | {{out.name}} | // out ports
21 |
22 | {% endfor %}
23 |
24 | |
25 |
26 |
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 | 
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 | 
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 |
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 |
--------------------------------------------------------------------------------