Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
c2836688d1 | |||
781a02dce6 | |||
8c950a02ea | |||
97a9f9f402 | |||
5ebb104e19 | |||
446b6102ac | |||
323fa68222 | |||
0ec64e6a39 | |||
3ae19dc20a | |||
eebd6e5517 | |||
b2502e7f0a | |||
fe2363cfdf | |||
b8a5ae2fcd | |||
d588eeee42 | |||
7a7399a602 | |||
7269db9e0a | |||
0da970d40f | |||
6e1a771862 | |||
101117d0bc | |||
b23252df95 | |||
14216b3888 | |||
9a896c3314 | |||
d3997d6049 | |||
f2ba588a46 | |||
b4bc651445 | |||
1be8f62f3e | |||
35268c53ae | |||
df2ec0cb17 | |||
00792df17b | |||
9e41c88c5b | |||
4f8931f193 | |||
2b070b173a | |||
13d25c6866 | |||
1e4ba2c739 | |||
f0f671c6fb | |||
465dbf8c79 | |||
90203f56cf | |||
4ea322e2f5 | |||
7479c9ed3f | |||
9bed136cd5 | |||
45e606797b | |||
014f28478b | |||
37cfd93bef |
26
.gitignore
vendored
26
.gitignore
vendored
@ -1 +1,25 @@
|
||||
doc
|
||||
# AVR temp files
|
||||
*.srec
|
||||
*.s
|
||||
*.o
|
||||
*.map
|
||||
*.lst
|
||||
*.hex
|
||||
*.elf
|
||||
*.bin
|
||||
*.obj
|
||||
|
||||
# Linux kernel driver temp files
|
||||
.cache.mk
|
||||
*.cmd
|
||||
.tmp_versions/*
|
||||
*.a
|
||||
*.mod
|
||||
|
||||
# Qt files
|
||||
build-*
|
||||
|
||||
# CMake
|
||||
**/CMakeFiles/**
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
|
@ -1,4 +1,10 @@
|
||||
# Brother LW-35 Modernization
|
||||
Drivers, firmware and tools used in my LW-35 electronic typewriter modernization.
|
||||
|
||||
Documentation coming soon-ish.
|
||||
For documentation, see my Vlog series:
|
||||
|
||||
* [Part 1: LCD](https://notsyncing.net/?p=blog&b=2018.lw35-vlog-1)
|
||||
* [Part 2: Keyboard](https://notsyncing.net/?p=blog&b=2018.lw35-vlog-2)
|
||||
* [Part 3: Printer preparation](https://notsyncing.net/?p=blog&b=2018.lw35-vlog-3)
|
||||
* [Part 4: Printer](https://notsyncing.net/?p=blog&b=2018.lw35-vlog-4)
|
||||
* [Part 5: Bringing it all together](https://notsyncing.net/?p=blog&b=2020.lw35-vlog-5)
|
||||
|
@ -2,7 +2,7 @@
|
||||
<BaliProject version="3.2" title="lmg6202" device="LCMXO2-1200HC-5SG32C" default_implementation="impl1">
|
||||
<Options/>
|
||||
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="synplify" default_strategy="Strategy1">
|
||||
<Options def_top="design.top" top="design.top"/>
|
||||
<Options def_top="design.top" lib="design" top="design.top"/>
|
||||
<Source name="../ip/gram0/gram0.ipx" type="IPX_Module" type_short="IPX">
|
||||
<Options/>
|
||||
</Source>
|
||||
@ -18,6 +18,12 @@
|
||||
<Source name="../design/spi_if.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options lib="design"/>
|
||||
</Source>
|
||||
<Source name="../ip/pll0/pll0.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options lib="ip"/>
|
||||
</Source>
|
||||
<Source name="../generics/synchronizer.vhd" type="VHDL" type_short="VHDL">
|
||||
<Options lib="generics"/>
|
||||
</Source>
|
||||
<Source name="impl1/impl1.xcf" type="Programming Project File" type_short="Programming">
|
||||
<Options/>
|
||||
</Source>
|
||||
|
@ -190,7 +190,7 @@
|
||||
<Property name="PROP_SYN_ResolvedMixedDrivers" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_UpdateCompilePtTimData" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_UseLPF" value="True" time="0"/>
|
||||
<Property name="PROP_SYN_VHDL2008" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_VHDL2008" value="True" time="0"/>
|
||||
<Property name="PROP_THERMAL_DefaultFreq" value="0" time="0"/>
|
||||
<Property name="PROP_TIM_MaxDelSimDes" value="" time="0"/>
|
||||
<Property name="PROP_TIM_MinSpeedGrade" value="False" time="0"/>
|
||||
|
@ -1,3 +0,0 @@
|
||||
Date=04/22/2018
|
||||
Time=17:34:06
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<DiamondModule name="gram0" module="gram0" VendorName="Lattice Semiconductor Corporation" generator="IPexpress" date="2018 04 22 11:42:01.314" version="7.5" type="Module" synthesis="synplify" source_format="VHDL">
|
||||
<DiamondModule name="gram0" module="gram0" VendorName="Lattice Semiconductor Corporation" generator="IPexpress" date="2020 05 10 12:58:23.793" version="7.5" type="Module" synthesis="synplify" source_format="VHDL">
|
||||
<Package>
|
||||
<File name="" type="mem" modified="2018 04 22 11:42:01.000"/>
|
||||
<File name="gram0.lpc" type="lpc" modified="2018 04 22 11:42:00.000"/>
|
||||
<File name="gram0.vhd" type="top_level_vhdl" modified="2018 04 22 11:42:00.000"/>
|
||||
<File name="gram0_tmpl.vhd" type="template_vhdl" modified="2018 04 22 11:42:00.000"/>
|
||||
<File name="tb_gram0_tmpl.vhd" type="testbench_vhdl" modified="2018 04 22 11:42:00.000"/>
|
||||
<File name="/home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem" type="mem" modified="2020 05 10 12:46:45.000"/>
|
||||
<File name="gram0.lpc" type="lpc" modified="2020 05 10 12:58:21.000"/>
|
||||
<File name="gram0.vhd" type="top_level_vhdl" modified="2020 05 10 12:58:21.000"/>
|
||||
<File name="gram0_tmpl.vhd" type="template_vhdl" modified="2020 05 10 12:58:21.000"/>
|
||||
<File name="tb_gram0_tmpl.vhd" type="testbench_vhdl" modified="2020 05 10 12:58:21.000"/>
|
||||
</Package>
|
||||
</DiamondModule>
|
||||
|
@ -16,8 +16,8 @@ CoreRevision=7.5
|
||||
ModuleName=gram0
|
||||
SourceFormat=VHDL
|
||||
ParameterFileVersion=1.0
|
||||
Date=04/22/2018
|
||||
Time=17:34:06
|
||||
Date=05/10/2020
|
||||
Time=13:18:44
|
||||
|
||||
[Parameters]
|
||||
Verilog=0
|
||||
@ -41,7 +41,7 @@ Optimization=Speed
|
||||
Reset=Sync
|
||||
Reset1=Sync
|
||||
Init=mem
|
||||
MemFile=/home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem
|
||||
MemFile=/home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem
|
||||
MemFormat=bin
|
||||
EnECC=0
|
||||
Pipeline=0
|
||||
@ -50,7 +50,7 @@ WriteB=Normal
|
||||
init_data=0
|
||||
|
||||
[FilesGenerated]
|
||||
/home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem=mem
|
||||
/home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem=mem
|
||||
|
||||
[Command]
|
||||
cmd_line= -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
cmd_line= -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
|
@ -1,5 +1,5 @@
|
||||
SCUBA, Version Diamond (64-bit) 3.10.0.111.2
|
||||
Sun Apr 22 17:34:06 2018
|
||||
Sun May 10 13:18:44 2020
|
||||
|
||||
Copyright (c) 1991-1994 by NeoCAD Inc. All rights reserved.
|
||||
Copyright (c) 1995 AT&T Corp. All rights reserved.
|
||||
@ -7,7 +7,7 @@ Copyright (c) 1995-2001 Lucent Technologies Inc. All rights reserved.
|
||||
Copyright (c) 2001 Agere Systems All rights reserved.
|
||||
Copyright (c) 2002-2017 Lattice Semiconductor Corporation, All rights reserved.
|
||||
|
||||
Issued command : /usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
Issued command : /usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
Circuit name : gram0
|
||||
Module type : RAM_DP_TRUE
|
||||
Module Version : 7.5
|
||||
@ -15,7 +15,7 @@ Copyright (c) 2002-2017 Lattice Semiconductor Corporation, All rights reserved.
|
||||
Inputs : DataInA[8:0], DataInB[8:0], AddressA[12:0], AddressB[12:0], ClockA, ClockB, ClockEnA, ClockEnB, WrA, WrB, ResetA, ResetB
|
||||
Outputs : QA[8:0], QB[8:0]
|
||||
I/O buffer : not inserted
|
||||
Memory file : /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem
|
||||
Memory file : /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem
|
||||
EDIF output : gram0.edn
|
||||
VHDL output : gram0.vhd
|
||||
VHDL template : gram0_tmpl.vhd
|
||||
|
@ -1,8 +1,8 @@
|
||||
-- VHDL netlist generated by SCUBA Diamond (64-bit) 3.10.0.111.2
|
||||
-- Module Version: 7.5
|
||||
--/usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type bram -wp 11 -rp 1010 -data_width 9 -rdata_width 9 -num_rows 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
--/usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type bram -wp 11 -rp 1010 -data_width 9 -rdata_width 9 -num_rows 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
|
||||
-- Sun Apr 22 17:34:06 2018
|
||||
-- Sun May 10 13:18:44 2020
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
@ -265,19 +265,19 @@ architecture Structure of gram0 is
|
||||
attribute MEM_INIT_FILE : string;
|
||||
attribute GSR : string;
|
||||
attribute MEM_LPC_FILE of gram0_0_0_6 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_0_0_6 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_0_0_6 : label is "splash.mem";
|
||||
attribute MEM_LPC_FILE of gram0_1_0_5 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_1_0_5 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_1_0_5 : label is "splash.mem";
|
||||
attribute MEM_LPC_FILE of gram0_2_0_4 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_2_0_4 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_2_0_4 : label is "splash.mem";
|
||||
attribute MEM_LPC_FILE of gram0_3_0_3 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_3_0_3 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_3_0_3 : label is "splash.mem";
|
||||
attribute MEM_LPC_FILE of gram0_4_0_2 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_4_0_2 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_4_0_2 : label is "splash.mem";
|
||||
attribute MEM_LPC_FILE of gram0_5_0_1 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_5_0_1 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_5_0_1 : label is "splash.mem";
|
||||
attribute MEM_LPC_FILE of gram0_6_0_0 : label is "gram0.lpc";
|
||||
attribute MEM_INIT_FILE of gram0_6_0_0 : label is "gram_init.mem";
|
||||
attribute MEM_INIT_FILE of gram0_6_0_0 : label is "splash.mem";
|
||||
attribute GSR of FF_11 : label is "ENABLED";
|
||||
attribute GSR of FF_10 : label is "ENABLED";
|
||||
attribute GSR of FF_9 : label is "ENABLED";
|
||||
@ -309,15 +309,15 @@ begin
|
||||
|
||||
gram0_0_0_6: DP8KC
|
||||
generic map (INIT_DATA=> "STATIC", ASYNC_RESET_RELEASE=> "SYNC",
|
||||
INITVAL_1F=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1E=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1F=> "0x0F800000003E00000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1E=> "0x000000000000000000000000000000000000000000000000000010007C00001E000C000000000000",
|
||||
INITVAL_1D=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1C=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1C=> "0x000000000000000000000000000180006013821F0000000000000000000000000000000000000000",
|
||||
INITVAL_1B=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1A=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_19=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1A=> "0x001FC03DF80060100201000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_19=> "0x0000000000000000000000000000000000000000000000000000000001FE3FE03002010000000000",
|
||||
INITVAL_18=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_17=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_17=> "0x000000000000000000000000000000200FE000000000000000000000000000000000000000000000",
|
||||
INITVAL_16=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_15=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_14=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
@ -374,37 +374,37 @@ begin
|
||||
|
||||
gram0_1_0_5: DP8KC
|
||||
generic map (INIT_DATA=> "STATIC", ASYNC_RESET_RELEASE=> "SYNC",
|
||||
INITVAL_1F=> "0x0020100201000003F07E001F83FDFE3FBFE3FDC03FEFF00201000000000000000000003FC1E00000",
|
||||
INITVAL_1E=> "0x001F03FC3E3F87E000003E0FE00000000003C1FE00000001FC3FE0F0020100000001C00FE01303FF",
|
||||
INITVAL_1D=> "0x3FFC13FFFF3C3FF3FE0F00000000000000000000001F03FC00000003F1FE03FC13FE07001803FC0E",
|
||||
INITVAL_1C=> "0x00000001003FE01002013F9FE0FC000000000000381FE00C003FDFF03FFD3FE0F3FFFF00E0100201",
|
||||
INITVAL_1B=> "0x00000001FC3FFFF3FFFF303FF3FFFF3FEFF003FD207FF3FFFF3FFFF07FFF3FFFF3FFFF00F813FFFF",
|
||||
INITVAL_1A=> "0x0020100000000003F83E001FC3FDFE3FDFE1FDE03FE7F0020100000000003FDFE3FDFE3FE1F3F3FF",
|
||||
INITVAL_19=> "0x3FFFF3FE033F83E3F1FE3FFFF3FFFF3FFFF3FDFF3FEFF003F93FE030020100000001C007E01383FF",
|
||||
INITVAL_18=> "0x3FFE13FFFF3C3FF3FE060000000000001E03FDFE3FFFF1FF813FFFF3FFFF003E13FF833FFFF3FFFF",
|
||||
INITVAL_17=> "0x3FFF73FFFF3FFFF3FE0F3F1FE03C0000000000003C1FE004003FDFF01FFF3FF0F3FFFF00E0100201",
|
||||
INITVAL_16=> "0x00000001FE3FFFF3FFFF383FF3FFFE3FE0F003FF307FF3FFFF3FFFF27FFF3FFFF3FFFF00F013FEFF",
|
||||
INITVAL_15=> "0x0000000000000003FC1E001FE3FCFE3FDFE0FDF03FE3F0020100000000003FDFE3FDFF3FE0F3FBFF",
|
||||
INITVAL_14=> "0x3FFFF07E013FC1E3F1FE3FFFF3FFFF3FFFE3FDFF3FE7F003F10FE010020100000001E003E013C3FF",
|
||||
INITVAL_13=> "0x1FFF13FFFF3F3FF3FC020000000000001F03FDFE3FFFF0FFC13FFFF3FEFF001E03FDC03FFFF3FFFF",
|
||||
INITVAL_12=> "0x3FFFB3FFFF3FFFF3FE073E1FE00C0000000000003C1FE000003FFFF21FFF3FF873FFFF0060100201",
|
||||
INITVAL_11=> "0x00000201FE3FFFF3FFFF383FF3FDFE03E01203FF383FF3FFFF3FFFF37FFF3FFFF3FFFF00F013FE3F",
|
||||
INITVAL_10=> "0x0000000000001003FC1E001FE3FC7E3FDFE0FDF93FE3F0020100000000003FDFE3FDFF3FE073FBFF",
|
||||
INITVAL_0F=> "0x3FE3F002013FC1E3F9FF3FFFF3FFFF3FDFE3FFFF3FE3F003E103E010020100000001F001E013C3FF",
|
||||
INITVAL_0E=> "0x0FFF13FFFF3F3FE3FC000000000000001F03FDFE3FFFF07FC13FFFF07E01001E01FD803FFFF3FFFF",
|
||||
INITVAL_0D=> "0x3FFF13FFFF3FFFF3FE033C0FE0000000000000003C0FE000003FDFF007FF3FF013FFFF0020100200",
|
||||
INITVAL_1F=> "0x01E013F2FB201DE01C0000000303871C10000C18002011C2010000000000200FE000003E00E00000",
|
||||
INITVAL_1E=> "0x3F0063FC063F80E380FE301FE001FE003F101DFC003F903E003FC7E001801FE013E2FD0003800000",
|
||||
INITVAL_1D=> "0x30383007E10187C000000020100000000003E00E001001FDC03FFFF0FFC103FF10FE013FC033FE0F",
|
||||
INITVAL_1C=> "0x3F9FE3FCFE3F03E3C0FE001E03FC02301FE00D001FA0120207300063E01E3007E2000E2000600000",
|
||||
INITVAL_1B=> "0x000000010001E01003F1383FF3FFFE303FF3FDFE003F83FDFE00FC13FFFF1FF013FFFF0FE01003FF",
|
||||
INITVAL_1A=> "0x006013F27F201FE01C0000C000FC00004013820307C00060000000000000200FE000003E00E3FDFE",
|
||||
INITVAL_19=> "0x3FE073F3FF3FE01203FF3FE3F003F93FFFF01FF13FFFF006013F81E0018007E013E2FF000E0000F0",
|
||||
INITVAL_18=> "0x0020100200001F801D800020000000000003E006001000FDE03FFFF07E013FFFF01E013FDFE3FC00",
|
||||
INITVAL_17=> "0x3E1FE3FC7E381FE3FC1E001C03FC00301FE005000FE010020D0781C0000000000381E23020000000",
|
||||
INITVAL_16=> "0x000000018000E01003F93C3FF3FDFE003FC3FC3E001803FDFE002013F9FE0FE013F3FF00E01003FD",
|
||||
INITVAL_15=> "0x002013FA1E201FE00C00038F03000200000000003020701A0000000000003007E000003F0063FDFE",
|
||||
INITVAL_14=> "0x3FE03203FF01E01003F13FE01002013FFFF00E013FE1F002013F80E001C003E013E27F0018038006",
|
||||
INITVAL_13=> "0x01C0000001200063C0E000000000000000000000000000000000000000003F01E00000201FE00400",
|
||||
INITVAL_12=> "0x0000000000001F007C0000000000000000000000000000003000FC10060100000079000CE0100201",
|
||||
INITVAL_11=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_10=> "0x000000000000000000003E0E60007800000001F0301F200C00000000000000000000000000000000",
|
||||
INITVAL_0F=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000007C1C",
|
||||
INITVAL_0E=> "0x3C000000000F8000383C000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0D=> "0x000000000000000000000000000000000000000000000000E0070001F000001F0001E00600000000",
|
||||
INITVAL_0C=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0B=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0A=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_09=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_08=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0B=> "0x000000000000000000000010000C0000E013E2070E00000000000000000000000000000000000000",
|
||||
INITVAL_0A=> "0x000000000000000000000000000000000000000000000000000000000000000000000000000001E0",
|
||||
INITVAL_09=> "0x001F83FDFE0038100600000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_08=> "0x0000000000000000000000000000000000000000000000000038002001F83FE010021F0000000000",
|
||||
INITVAL_07=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_06=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_06=> "0x00000000000000000000000001E0000003E0000001C0000001000000000000000000000000000000",
|
||||
INITVAL_05=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_04=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_03=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_04=> "0x00201002010003C00000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_03=> "0x000000000000000000000000000000000000000000000000000007800000000003E0000000000000",
|
||||
INITVAL_02=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_01=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_01=> "0x00000000000000000000000002001E00000001C00020100000000000000000000000000000000000",
|
||||
INITVAL_00=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
CSDECODE_B=> "0b001", CSDECODE_A=> "0b001", WRITEMODE_B=> "NORMAL",
|
||||
WRITEMODE_A=> "NORMAL", GSR=> "ENABLED", RESETMODE=> "SYNC",
|
||||
@ -439,38 +439,38 @@ begin
|
||||
|
||||
gram0_2_0_4: DP8KC
|
||||
generic map (INIT_DATA=> "STATIC", ASYNC_RESET_RELEASE=> "SYNC",
|
||||
INITVAL_1F=> "0x00000000003F83E000003FFFF3FFFF01E0100201001F01FC003E1FE3FD823FFFF387FF1FE0100201",
|
||||
INITVAL_1E=> "0x000000000000000001C007E0100201001E03FD801FE01002013FE0100201001C03FC02001FE3FDFE",
|
||||
INITVAL_1D=> "0x3FEFF0020100000301FE003813FFFE307FF3FE1F3FDFF01E0100000000000000000000381FE00400",
|
||||
INITVAL_1C=> "0x00000001FE303FF01E01201FE03C0000000001FE006013C3FF3FFFF3FE0700000000003FC0E003F9",
|
||||
INITVAL_1B=> "0x3FE3F3FBFF03FFD3FEFF000000000000000381FE3FFFF3FE3F00000000003FC1E3F07E000003E1FE",
|
||||
INITVAL_1A=> "0x00000000003FC3E000003FDFF3FFFF0060100201001F80FC003F1FE3FDC23FFFF383FF1FE0100201",
|
||||
INITVAL_19=> "0x00000000003FFFF3FFFF07E0100201001E03FD800FE01003011FE0100201001E03FC00001FC0FC00",
|
||||
INITVAL_18=> "0x3FC1E0020100000301FE003813FDFE383FF3FE1F3FDFF00E010000000000001FE3FDFE3FFFF00201",
|
||||
INITVAL_17=> "0x00000201FE383FF00E01201FE01C0000000001FE00201383FF003F91FC0000000000003FC07003F1",
|
||||
INITVAL_16=> "0x3FE0F3F3FF01E01002010000000000000003E1FE3FFFF3FE1F00000000003FC1E3F87F000003F0FE",
|
||||
INITVAL_15=> "0x00000000003FC1E000013FC06383FF0020100200001FC07C00000000000000000000000000000000",
|
||||
INITVAL_14=> "0x00000001003FFFF3FFFF03E0100201001F01FDC007E01003811FE0100201001F03FC00001F81FC00",
|
||||
INITVAL_13=> "0x3FE070020100000381FE0020000000000000000000000000000000000000201FE3FDFE3FEFF00201",
|
||||
INITVAL_12=> "0x00000201FE383FF00600301FE00C0000000201FE00201303FE203FF07E0000000000003FC0300201",
|
||||
INITVAL_11=> "0x000000000000000000000000000000000003E1FE3FFFF3FE0F00000000003FC0E3FE3F000003F07E",
|
||||
INITVAL_10=> "0x00000000003FC0E000013FC0E3E3FF0000000000001FE07C00000000000000000000000000000000",
|
||||
INITVAL_0F=> "0x00000001003FFFF3FFFF01E0100201001F80FDE007E01003C10FE0100201001F81FC00001F01FD80",
|
||||
INITVAL_0E=> "0x1FE0100201000003C1FE001C03FDFE3C3FF3FC023FEFF002010000000000201FE3FDFE3FEFF00201",
|
||||
INITVAL_0D=> "0x00000381FE3C3FF00000381FE0040000000301FE00201203FE383FF01E0100000000003FE01003FF",
|
||||
INITVAL_0C=> "0x3FF073FFFF20FFF3FE1F00000000000000000000001803FC0600000000003FD073FE1F000003F83E",
|
||||
INITVAL_0B=> "0x00000000003FC06002013FC1E3FC7F0000000000201FE03C003FDFE0FDF03FE7F3F3FF03E0100201",
|
||||
INITVAL_0A=> "0x000000000000000001F800E0100201001FE07DF003E01003C107E0100201001F80FC00001F03FDF0",
|
||||
INITVAL_09=> "0x07E0100201000003E1FE001F03FDFE3E3FF3FD823FFFF00201000000000000000000003F87E00000",
|
||||
INITVAL_08=> "0x000003E1FE3E3FE000003C1FE0040000000381FE00201001FE3E3FF0020100000001001FE01203FF",
|
||||
INITVAL_07=> "0x3FF873FFFF307FF3FE1F00000000000000000000001C03FC0600000001003FF013FE0F000003FC1E",
|
||||
INITVAL_06=> "0x00000000003FC03002013FD9E3FC0E0000000000201FE01C003FDFE0FDF93FE3F3F3FF03E0100201",
|
||||
INITVAL_05=> "0x000000000000000001FC0060100201301FE03DF801E01003E103E0100201001FC07C00001E03FDFE",
|
||||
INITVAL_04=> "0x01E0100201000003F0FE001F03FDFE3F3FE3FDC23FFFF00201000000000000000000003F83E00000",
|
||||
INITVAL_03=> "0x000003F8FE3F0FE000003E1FE0000000000381FE00200001FE3FE7F0020100000001801FE01303FF",
|
||||
INITVAL_02=> "0x3FF833FFFF383FF3FE0F00000000000000000000001E03FC0200000001F00FF813FE0F001003FC1E",
|
||||
INITVAL_01=> "0x00000000003FE03002013F9FE3FC020000000000301FE00C003FDFE07FFD3FE1F3FBFF01E0100201",
|
||||
INITVAL_00=> "0x000000000000000001FE00601002013F9FE005F800E01003F101E0100201001FE03C00001C03FDFE",
|
||||
INITVAL_1F=> "0x003FE001F02020F003C0007FD3FFFF007F9207DF3C20F000062000324202000670020F0040600001",
|
||||
INITVAL_1E=> "0x00000000001FC000010101E010038100E310020103FFD006013F8023C01E3E00E0C0003803E381FE",
|
||||
INITVAL_1D=> "0x3FE3F3023F3BC0E1FE0100C0C1C10000E000C00400C380C0010000000000001F001C00200FE00000",
|
||||
INITVAL_1C=> "0x3007E00000001FE3803E001C007C0007D011FE01000003F8023FDFF3FE0107CF81FBE10026118200",
|
||||
INITVAL_1B=> "0x200430030101A1C301000020100000000002007E000003E006000003F002000003C01E03E01003FD",
|
||||
INITVAL_1A=> "0x003FC005F000201001C0007FD3FFFF003F9387CF3C20700206060F10220C200C01E0602000200201",
|
||||
INITVAL_19=> "0x00000000000FC000038100E01003C1006010020103FFF002013F802301FE3FE07002013803E381FE",
|
||||
INITVAL_18=> "0x3FE0F3821F38D0F0FE0100D9C00DFC03000031F83E218060000000000000001F800C003007E00000",
|
||||
INITVAL_17=> "0x3803E00000001FE3C01E001C007C003FDFF0FE01000003F80207D000FE0103C7F1FBF1002E13007E",
|
||||
INITVAL_16=> "0x3C186000C00FD003FD000020000000000003007E000003F0063FDFF3FE03000003C11E03E01003FD",
|
||||
INITVAL_15=> "0x303FE3FDFE00201001C0007F9007F9003FD3C1C23E2070020C1CC003F27F3C1FE001382020300201",
|
||||
INITVAL_14=> "0x00000000000FC000038100FFD3FFFF006010020123EFF002013F8023FDFE3FE07002013803E3003E",
|
||||
INITVAL_13=> "0x3F0023811E3070F0FE010183E018803FDFE0FC100303C060000000000000001F8004003003E381FE",
|
||||
INITVAL_12=> "0x3FE1F00201001FE3E00E001C007DF03FFFF07E01000003F80207DC007E0123C1F1F3F1002C01E1C0",
|
||||
INITVAL_11=> "0x1800001C30021C03018E0000000000000003803E000003F8023FDFF3FE01000003C11E01E01003FD",
|
||||
INITVAL_10=> "0x3F3FE3FDFE00200001C0007F9007FD000FE3F1803F203003DC30200018C0031000040E33C0000000",
|
||||
INITVAL_0F=> "0x000000000007C01003C1007FD3FFFF002010020123EFF002013F9C21FC003F802000003803E3003E",
|
||||
INITVAL_0E=> "0x3FC003C18E3038F07E013F000060C0301800003000D8003C000000000000001FC004003803E3C1FE",
|
||||
INITVAL_0D=> "0x3FE1F00201001FE3E00E001C007DFE003C007C00000003F8020FDE001C0139E0F3F3F9003C000D00",
|
||||
INITVAL_0C=> "0x082010600C06070001E00000000000000003803E000003F802000003FC00000003E10E01E01003FF",
|
||||
INITVAL_0B=> "0x3FC00001FC00200001E0003F120EFF000FE1F9803F2030021F000060080000F01204023800600000",
|
||||
INITVAL_0A=> "0x000000000007C01003C100601003E1002010030121EFF002013FDE003C003F800000003C01E2007E",
|
||||
INITVAL_09=> "0x0FC003C1EF3039F07C0000C001C2410003E00030004001E2010000000000001FE000003C01E00000",
|
||||
INITVAL_08=> "0x3C00E00000200FE3E00E001E003CFE001E003C00000003FC000FDF8005013CE073F3FD0003E00000",
|
||||
INITVAL_07=> "0x080013820006018000000040100201000003C01E000003FC00001001FC00000003F10601E01202FF",
|
||||
INITVAL_06=> "0x1FC00001FF00000001F0003F130E3E2017E07D803FA011C2010001C0080000501186010003800000",
|
||||
INITVAL_05=> "0x000000000003E01003E100201003F12020F003C020FFF002011FDF001E013FC0003C003F00E2007E",
|
||||
INITVAL_04=> "0x03C013E3F7303DE03C000020130240000760003000201302020000000000001FE000003C01E00000",
|
||||
INITVAL_03=> "0x3E10E1FC003803E3C01E001F820CFE001E003DFE001800FC001FDFC001003EE013E3FD0000C00000",
|
||||
INITVAL_02=> "0x184000600F06006000000000000201000003C01E000003FC00001001FDE0002013FE0307E013827F",
|
||||
INITVAL_01=> "0x3FC00001FE3F802001FC003E13DC0E201FE03D003FA013820100070019C0031000E0000001C00000",
|
||||
INITVAL_00=> "0x000000000001E01003E100201003F03C23F001F0003FF0060107FE107E011FDC00FC003FC02000FE",
|
||||
CSDECODE_B=> "0b010", CSDECODE_A=> "0b010", WRITEMODE_B=> "NORMAL",
|
||||
WRITEMODE_A=> "NORMAL", GSR=> "ENABLED", RESETMODE=> "SYNC",
|
||||
REGMODE_B=> "OUTREG", REGMODE_A=> "OUTREG", DATA_WIDTH_B=> 9,
|
||||
@ -504,38 +504,38 @@ begin
|
||||
|
||||
gram0_3_0_3: DP8KC
|
||||
generic map (INIT_DATA=> "STATIC", ASYNC_RESET_RELEASE=> "SYNC",
|
||||
INITVAL_1F=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1E=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1D=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1C=> "0x00000000003FDFE3FDFF3FE013FBFF0FE01002013FC06000003F80E00000000003F01E381FE00000",
|
||||
INITVAL_1B=> "0x000003FD063FFFF3FFFF00E0100201000000000000000000000000000000001F83FDFE3FFFF07FE1",
|
||||
INITVAL_1A=> "0x3FFFF1FE01001F01FC00001E03FC0000000001C007E013FE3F00000001F021FFF3FFFF3FEFF00201",
|
||||
INITVAL_19=> "0x00000000000000000000000000000000000381FE3FFFF3FFFF3C3FE3FDFE00E01203FF00201003FE",
|
||||
INITVAL_18=> "0x0020100201381FE005E007E01002013F0FE3F1FE3FFFF3FE0F201FE3FC1E3FDFE01FF93FE0700201",
|
||||
INITVAL_17=> "0x00000000003FDFF3FFFF3FE033FFFF3FFFF002013FC0E002013FC1E00000000003F83E3C1FE00400",
|
||||
INITVAL_16=> "0x001C03FD8E3FFFF3FFFF01E013F3FF07FFD3FFFF3F9FE1FC000000000000001FC3FDFE3FFFF07FF1",
|
||||
INITVAL_15=> "0x3FFFF3FE7F001F81FC00001F03FC0000000001E007E013FA3F00000001FE30FFF3FFFF3FE7F00381",
|
||||
INITVAL_14=> "0x3FFFF387FF3FFC13FFFF002010020000000381FE3FFFF3FFFF3E3FE3FDFE1FE01303FF00201201FE",
|
||||
INITVAL_13=> "0x00201002003C1FE005C00FE01002013FC3E3F9FF3FFFF3FE07301FE3FC1E3FDFF03FFF3FE0700201",
|
||||
INITVAL_12=> "0x00000000003FFFF3FFFF3FF013FFFF3FFFF03E013FC07002013FC0E00001000003FC1E381FE00C00",
|
||||
INITVAL_11=> "0x001F03FDC03FFFF3FFFF00E013FBFF03FFD3FEFF3FDFE0FC000000000000001FE3FDFE3FFFF03FF1",
|
||||
INITVAL_10=> "0x3FFFF3FFFF003FC0FC00001F01FC0000000001E003E013FA7F00000301FE383FF3FFFF3FE7F003C1",
|
||||
INITVAL_0F=> "0x3FFFF3C3FF1FFE13FFFF0020100000000003C1FE3FFFF3FFFF3E1FE3FDFE3FE07383FF00201301FE",
|
||||
INITVAL_0E=> "0x00201002003E1FE001800FE01002013FC0F3FBFF3FFFF3FE03381FE3FC1E3FFFF01FFF3FE0700201",
|
||||
INITVAL_0D=> "0x00000000003FDFE3FFFF3FE013FFFF3FFFF0FE013FC03002013FC0600201001003FC0E301FE01C00",
|
||||
INITVAL_0C=> "0x001FE0FD003FFFF3FFFF006013FBFF01FFF3FEFF3FDFE07C0100000000000000000000201FE01C00",
|
||||
INITVAL_0B=> "0x000003F1FE003FF07E00001F80FC0000000001F001E013F2FF000003E1FE00200000003FC3E001E0",
|
||||
INITVAL_0A=> "0x3FEFF3C3FF0FFF13FFFF00200000000000000000000003E0FE00000000003FE0F3C3FF00200381FE",
|
||||
INITVAL_09=> "0x00201000003E0FE001801FE01003013FE0100201001E03FC023C1FE3FD0E3FFFF20FFF3FE0300201",
|
||||
INITVAL_08=> "0x000000000000000001801FE0100201001F81FC003FE03002013FC0700201001803FC0E201FE3FDFE",
|
||||
INITVAL_07=> "0x3FFFF03E0100000001FE002013FFFF21FFF3FE7F3FDFE07C0100000000000000000000301FE01C00",
|
||||
INITVAL_06=> "0x00000201FE003FF03E01001FC07C0000000001F800E013E3FF3FFFF3FEFF00000000003FC1E001E0",
|
||||
INITVAL_05=> "0x3FE7F3E3FF0FFF93FFFF00000000000000000000000003F07E00000000003FC1E3E1FF00000381FE",
|
||||
INITVAL_04=> "0x00200000003F07E001003FFFF3FFFF0FE0100201001F03FC003E1FE3FD063FFFF307FF3FE0100201",
|
||||
INITVAL_03=> "0x000000000000000001800FE0100201001E03FD003FE01002013FE0300201001C03FC06201FE3FDFE",
|
||||
INITVAL_02=> "0x3FFFF0060100000201FE003013FFFF30FFF3FE3F3FDFE03E0100000000000000000000381FE00C00",
|
||||
INITVAL_01=> "0x00000001FE203FF01E01001FE07C0000000001FC00E013C3FF3FFFF3FE1F00000000003FC0E001F1",
|
||||
INITVAL_00=> "0x3FE7F3F3FF07FF93FFFF00000000000000000000000003F87E00000000003FC1E3E0FE000003C1FE",
|
||||
INITVAL_1F=> "0x00000000000000000000000000000000000000000000000000000000000000000000000018000006",
|
||||
INITVAL_1E=> "0x080000600C060000C1C0000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1D=> "0x0000000000000000000000000000000000000000000000001800C000198103100004003020100000",
|
||||
INITVAL_1C=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1B=> "0x0000000000000000000003830000C018100004100000E03000000000000000000000000000000000",
|
||||
INITVAL_1A=> "0x0000000000000000000000000000000000000000000000000000000000000000000000000C020002",
|
||||
INITVAL_19=> "0x1800031C700200018180000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_18=> "0x0000000000000000000000000000000000000000000000000C00000213FF3FF8F002012000300200",
|
||||
INITVAL_17=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_16=> "0x0000000000000000000001818001C007E013FE1F0001C06000000000000000000000000000000000",
|
||||
INITVAL_15=> "0x00000000000000000000000000000000000000000000000000000000000000000000000006030000",
|
||||
INITVAL_14=> "0x3E182000C00F80030100002000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_13=> "0x00000000000000000000000000000000000000000000000006001E1036193008007C002000200201",
|
||||
INITVAL_12=> "0x000000000000000000000000000000000003E03E00000001FE002010000000000001E000E0100201",
|
||||
INITVAL_11=> "0x0000000000000000000000C0C30106018000610C002190620000000001C03FFFF07FFD3FFFF307FF",
|
||||
INITVAL_10=> "0x3FFFF003E13FE01002013FE3F003F1002013FA033F9FE0050001E01202FF1FC0007D800066118201",
|
||||
INITVAL_0F=> "0x200630030101A3C301000020100000381FE3FDFE3FBFE3FC3E3FDFF3FE1F3F1FE0FC00301FE3FC0E",
|
||||
INITVAL_0E=> "0x3E01E001C0007F13FEFF200FE000000FDE001FF13023F00006000070620600046200060040600201",
|
||||
INITVAL_0D=> "0x000003F9FE3FFC33FFFF07FFD3FFFF03FE13FFFF002013FBFE03E013FE013803E381FE3FE013E20F",
|
||||
INITVAL_0C=> "0x001F800CFE3E0063F00200C0C060000063C0C007018300C00000000001C03FFFF03FFD3FFFF383FF",
|
||||
INITVAL_0B=> "0x3FEFF203FF3FE1F003F13FFFF007E1006013FA013FFFF07E0101E013823F1FD800FDC00026118381",
|
||||
INITVAL_0A=> "0x000363E006005812020200201000003C1FE3FDFE3FDFE3FC1E3FDFF3FE0F3FDFE3FE033F1FE3FC7E",
|
||||
INITVAL_09=> "0x3803E001E0203FF3FFFF002FF0000007DF100FF93821F00006100013830001E3D002190040600001",
|
||||
INITVAL_08=> "0x000003FDFE3FFE13FFFF03FFD3FFFF01FFD03FF100FC13FE031FE013FA073C01E3F03E3FC0E3C00E",
|
||||
INITVAL_07=> "0x001FE2007E3F8063F80000C0C01800300FF30203020300C0000000000000001E003C00001FE00000",
|
||||
INITVAL_06=> "0x200FE3C07E380FE001FE003F901D8000E013FFC101F813FE0103E013C20F0FDC00FDC100261182C1",
|
||||
INITVAL_05=> "0x0000C3F00E0010020203002010000000000001FE000003C01E000003E00E03E013F20F3FC02201FF",
|
||||
INITVAL_04=> "0x300FE001E03823F003F1003FF0030101FF100FFF3821F00006180013830001E39002110040600001",
|
||||
INITVAL_03=> "0x00000000001FC000000001E010030120EFF0030101FF103E013FC003E00E3C00E3FC003C01E3C01E",
|
||||
INITVAL_02=> "0x3007E2007E3FC061F80000C0C01000200FF38203030300C0000000000000001F001C00200FE00000",
|
||||
INITVAL_01=> "0x3007E3C00E201FE300FE001E007D0001F011FFC1002013FE033FDFF3FE0707DF00FFE10026118380",
|
||||
INITVAL_00=> "0x000363C00600CC120202002010000000000200FE000003E00E000003F00600C003C21F0FC00003FD",
|
||||
CSDECODE_B=> "0b011", CSDECODE_A=> "0b011", WRITEMODE_B=> "NORMAL",
|
||||
WRITEMODE_A=> "NORMAL", GSR=> "ENABLED", RESETMODE=> "SYNC",
|
||||
REGMODE_B=> "OUTREG", REGMODE_A=> "OUTREG", DATA_WIDTH_B=> 9,
|
||||
@ -569,38 +569,38 @@ begin
|
||||
|
||||
gram0_4_0_2: DP8KC
|
||||
generic map (INIT_DATA=> "STATIC", ASYNC_RESET_RELEASE=> "SYNC",
|
||||
INITVAL_1F=> "0x00000000003C40101E013FE0F003E1001F03FC003F8FE001C01FE013E303003F13FE0E3E0FE001E0",
|
||||
INITVAL_1E=> "0x0011E03C0E3E1FE005E01FE01003FF3FE0F3FFFF20FFF3FE3F00000000000001C078F02000E1E000",
|
||||
INITVAL_1D=> "0x1C00000000003C10061F3C10001D002060F3020F01C002001F3C0001C1F801E000001D1E00000000",
|
||||
INITVAL_1C=> "0x3FDFE0FDF03FE7F3E3FF07E010020100000001801E2010F0000020101E010003C0001E03D0001CF0",
|
||||
INITVAL_1B=> "0x2007E0E00000CE00020103C0001C003FAF3002000390001C00001E03FDFE3E3FF3FD823FFFF00201",
|
||||
INITVAL_1A=> "0x0000000000301FE00D800021E000F0000003800201DE0000701E0003E10E0023D0000E001E0000E0",
|
||||
INITVAL_19=> "0x201CE27006001E0000F000000001FE3FF073FFFF307FF3FE1F0000000000000003FC7E380023C000",
|
||||
INITVAL_18=> "0x1E00000000004F10020F0F10000D8031E073800101C000001E1E0001E18E00F003FC1F3E0FE00000",
|
||||
INITVAL_17=> "0x3FDFE0FDF13FE3F3F3FF03E010020100000001F00FE0103A010030100E000001C2000E01D8000478",
|
||||
INITVAL_16=> "0x301E607000000F10020103D0001D0031E7F003F901E013FE3F001F03FDFE3F3FE3FD823FFFF00201",
|
||||
INITVAL_15=> "0x00000000000F180005C02000E00070000003C00000CF0000390F0000719C0021E2000E000E000070",
|
||||
INITVAL_14=> "0x2007E3F0023F0FE0018007E01203FF3FF833FFFF383FF3FE0F00000000000018000438380001E000",
|
||||
INITVAL_13=> "0x0F00000000002712020F07180005803FA023C00000C002000F0E0003F102006012020F0018000400",
|
||||
INITVAL_12=> "0x3FDFE07DF93FE1F3FBFF01E0100201000000003C07800039800038100C002000E3000600D8000439",
|
||||
INITVAL_11=> "0x3818207C00002790020100D8000F812023F0020101C0000039001F83FDFE3F3FE3FDC03FEFF00201",
|
||||
INITVAL_10=> "0x0000000000079C0005C03820200038000000F80000C700027907800039F80003C3C0020003C00078",
|
||||
INITVAL_0F=> "0x3001E3E002000700000007800301FE3FFC13FFFF383FF3FE0F0000000000001803FC1E301FE03C00",
|
||||
INITVAL_0E=> "0x3FE0F3C3FF00238300063F1FE005C03E000381FE003E13FE01070001F100003E13FE073F1FE00000",
|
||||
INITVAL_0D=> "0x3FDFE03FFD3FE0F3FFFF00E010020100000001F003E013E2FF201FE1FC001FE013020300C003FE1F",
|
||||
INITVAL_0C=> "0x3810003C003FC06203FF003C1007C02021F001FE00F813FE0F001F83FDFE3F9FE1FDE03FE7F00201",
|
||||
INITVAL_0B=> "0x0000000000300FE0000001C013C3FF003FD00000000300030103E0101AC1001C001C001FC0000018",
|
||||
INITVAL_0A=> "0x300021C0003FC3E001F800201383FE3FFC13FFFF3C3FF3FE06000000000000000000000000000000",
|
||||
INITVAL_09=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_08=> "0x3FDFF01FFF3FE0F3FFFF00E010020100000000000000000000000000000000000000000000000000",
|
||||
INITVAL_07=> "0x00000000000000000000000000000000000000000000000000001FC3FCFE3FDFE0FDF03FE3F00201",
|
||||
INITVAL_06=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_05=> "0x0000000000000000000000000381FE1FFE13FFFF3E3FF3FC02000000000000000000000000000000",
|
||||
INITVAL_04=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_03=> "0x3FDFF01FFF3FF073FFFF006010020100000000000000000000000000000000000000000000000000",
|
||||
INITVAL_02=> "0x00000000000000000000000000000000000000000000000000001FC3FC7E3FDFE07DF03FE3F00201",
|
||||
INITVAL_1F=> "0x000002007E200060C0003F00000030180000E000000013820F30006060000020F302000001C20006",
|
||||
INITVAL_1E=> "0x3E0060000000C003000200180005C001A012301E380000000000000000003FC010C201003F10FC00",
|
||||
INITVAL_1D=> "0x06000039000023C0018007E010F3010021E1C000000003020100DC03FC010006000000004000021D",
|
||||
INITVAL_1C=> "0x3E0C0001800F8000700000000000000000E0780000207303060030100780300023C0023818200D80",
|
||||
INITVAL_1B=> "0x202033C2000021900200004302020F0040100207000380000001D8000C0C3010003D000020100000",
|
||||
INITVAL_1A=> "0x000000E1800021C0C0000001D0023130002030000060101CE13001C060000060F300010003030002",
|
||||
INITVAL_19=> "0x004700000100C0030002000700001E03800031C00020E00000000000010020206300000021D30002",
|
||||
INITVAL_18=> "0x06000061C000076000E03800037100002761C0000000020207000300020F00060000000040030203",
|
||||
INITVAL_17=> "0x01DC03FDFF200061800000000000002000200000004061820100500007013FE010E2070C00003980",
|
||||
INITVAL_16=> "0x206020C20700219002003FC1E2000301C0000006000380000000039003FD3FE013C2010000100201",
|
||||
INITVAL_15=> "0x000000E000000700C0000023100230201FE01D0001F0000D80300320600001E0F30000001E03FC00",
|
||||
INITVAL_14=> "0x004C00000100C00300020000C3800000000000000043900201000000000000201203FE0020F20006",
|
||||
INITVAL_13=> "0x060000C0E0200C2000703000207106003C61C000000000020F001F100E0C3C07E001FE006011C201",
|
||||
INITVAL_12=> "0x002010020000070200060000000000000FC000003FC070C20100D00004000C2010720C0600006180",
|
||||
INITVAL_11=> "0x21E020C01800219002000180E2007E019803FC063FC3E0010020207380060003E0000E00C0000000",
|
||||
INITVAL_10=> "0x000002007E0000E0C00000261000300000C00D800390000500302C2060000720F30000000C00C000",
|
||||
INITVAL_0F=> "0x000C00003C00C0030002200020710003E013F20F038E00000000000000003F0000C0000020F20006",
|
||||
INITVAL_0E=> "0x060001807038180000703000207118003061C400000000021D002010000C038600000000400033C1",
|
||||
INITVAL_0D=> "0x3018000CE0039800041C00000000000000003900002071C00000500004010600101A390E00003180",
|
||||
INITVAL_0C=> "0x272020C06000219002002300600000018C00000600038001C01C000010E00E180000300300000000",
|
||||
INITVAL_0B=> "0x0000000180202060C000002390023000198004C00710000DC030102064001C20F300000018006000",
|
||||
INITVAL_0A=> "0x000E00000C00C00300021800000CC0301C0000100E180004000000000000300020E0000021D30002",
|
||||
INITVAL_09=> "0x06000300181C100004E03800007170002061D8000000000331002600000E01860000000040001E31",
|
||||
INITVAL_08=> "0x180000600E0600001C3000000000000000607100002073800000101006010340000E711C00001D80",
|
||||
INITVAL_07=> "0x3C2020C1800001900200360002000600DC0000070003800060070000080000F01006C10E00000000",
|
||||
INITVAL_06=> "0x000001C1C00000E0C00000C0E00231001F0000700C0000787030002078003020F300000010003C00",
|
||||
INITVAL_05=> "0x03C380003C00C00300020E180000400003C000303800000C0000000000001FC01383FF003F10FC00",
|
||||
INITVAL_04=> "0x3FC1F2020F0E00001D8007E01073C1002061E00000000003E1001C03FC003F07E001FE007010061D",
|
||||
INITVAL_03=> "0x080003800006000030600000000000001F800C003FC06003FD001FC3FC0001D00004E0000FE00180",
|
||||
INITVAL_02=> "0x302020C10000219002001C000001F0002013FC063FC3E00030018000080000701007011820000000",
|
||||
INITVAL_01=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_00=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_00=> "0x00000000000000000000070600004020066000302000201800000000000000000000000000000000",
|
||||
CSDECODE_B=> "0b100", CSDECODE_A=> "0b100", WRITEMODE_B=> "NORMAL",
|
||||
WRITEMODE_A=> "NORMAL", GSR=> "ENABLED", RESETMODE=> "SYNC",
|
||||
REGMODE_B=> "OUTREG", REGMODE_A=> "OUTREG", DATA_WIDTH_B=> 9,
|
||||
@ -635,37 +635,37 @@ begin
|
||||
gram0_5_0_1: DP8KC
|
||||
generic map (INIT_DATA=> "STATIC", ASYNC_RESET_RELEASE=> "SYNC",
|
||||
INITVAL_1F=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1E=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1E=> "0x0000000000000000000000000000000000000000000000000000000001FC3FE01002010000000000",
|
||||
INITVAL_1D=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1C=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1C=> "0x0000000000000000000000000000003F9FE03C000000000000000000000000000000000000000000",
|
||||
INITVAL_1B=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1A=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_19=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_1A=> "0x001C0001800000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_19=> "0x00000000000000000000000000000000000000000000000000000000000C30000000000000000000",
|
||||
INITVAL_18=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_17=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_17=> "0x00000000000000000000000000000001800030000000000000000000000000000000000000000000",
|
||||
INITVAL_16=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_15=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_14=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_15=> "0x000C0001800000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_14=> "0x00000000000000000000000000000000000000000000000000000000000C30000000000000000000",
|
||||
INITVAL_13=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_12=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_12=> "0x00000000000000000000000000000001C000F0010000000000000000000000000000000000000000",
|
||||
INITVAL_11=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_10=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0F=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_10=> "0x000FE0018000E0100201000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0F=> "0x00000000000000000000000000000000000000000000000000000003F80C301FE000000000000000",
|
||||
INITVAL_0E=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0D=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0D=> "0x0000000000000000000000000001F001A00030FC0000000000000000000000000000000000000000",
|
||||
INITVAL_0C=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0B=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0A=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0B=> "0x0F8C0001803C00200000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_0A=> "0x00000000000000000000000000000000000000000000000000001F00000C300001F0000000000000",
|
||||
INITVAL_09=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_08=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_08=> "0x00000000000000000000000003800601800030000020100201000000000000000000000000000000",
|
||||
INITVAL_07=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_06=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_05=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_06=> "0x002C1003810007800000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_05=> "0x00000000000000000000000000000000000000000000000000300060000C300002000E0000000000",
|
||||
INITVAL_04=> "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_03=> "0x0000000000000000000000000000000000000000000000000000000000000000001CE0001E003C00",
|
||||
INITVAL_02=> "0x38000001FE000003F802001FC01C000020F003E0003011FE0038000381C001D003FC3E001FE01C00",
|
||||
INITVAL_01=> "0x3F1FE0FDC03FE3F3C3FF03E010020100000381E01C000381FE0020103C003FC0E001F101E013F3FF",
|
||||
INITVAL_00=> "0x0001E1C0003F87E001F800E0103A013C2E1003F907E013FAFF001C03FDFE3C3FF3FF063FFFF00601",
|
||||
INITVAL_03=> "0x00000000000000000000000000780001800070000380000000000000000000000000000000000000",
|
||||
INITVAL_02=> "0x000000000000000000000000000000000000000000000000000000000000000000000000000000E0",
|
||||
INITVAL_01=> "0x000F8001800038100E01000000000000000000000000000000000000000000000000000000000000",
|
||||
INITVAL_00=> "0x000000000000000000000000000000000000000000000000000E0003E00E3007E000F00000000000",
|
||||
CSDECODE_B=> "0b101", CSDECODE_A=> "0b101", WRITEMODE_B=> "NORMAL",
|
||||
WRITEMODE_A=> "NORMAL", GSR=> "ENABLED", RESETMODE=> "SYNC",
|
||||
REGMODE_B=> "OUTREG", REGMODE_A=> "OUTREG", DATA_WIDTH_B=> 9,
|
||||
|
@ -3,7 +3,7 @@ Starting process: Module
|
||||
Starting process:
|
||||
|
||||
SCUBA, Version Diamond (64-bit) 3.10.0.111.2
|
||||
Sun Apr 22 17:34:06 2018
|
||||
Sun May 10 13:18:44 2020
|
||||
|
||||
Copyright (c) 1991-1994 by NeoCAD Inc. All rights reserved.
|
||||
Copyright (c) 1995 AT&T Corp. All rights reserved.
|
||||
@ -13,7 +13,7 @@ Copyright (c) 2002-2017 Lattice Semiconductor Corporation, All rights reserved.
|
||||
|
||||
BEGIN SCUBA Module Synthesis
|
||||
|
||||
Issued command : /usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
Issued command : /usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
Circuit name : gram0
|
||||
Module type : RAM_DP_TRUE
|
||||
Module Version : 7.5
|
||||
@ -21,7 +21,7 @@ BEGIN SCUBA Module Synthesis
|
||||
Inputs : DataInA[8:0], DataInB[8:0], AddressA[12:0], AddressB[12:0], ClockA, ClockB, ClockEnA, ClockEnB, WrA, WrB, ResetA, ResetB
|
||||
Outputs : QA[8:0], QB[8:0]
|
||||
I/O buffer : not inserted
|
||||
Memory file : /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem
|
||||
Memory file : /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem
|
||||
EDIF output : gram0.edn
|
||||
VHDL output : gram0.vhd
|
||||
VHDL template : gram0_tmpl.vhd
|
||||
|
@ -1,6 +1,6 @@
|
||||
-- VHDL module instantiation generated by SCUBA Diamond (64-bit) 3.10.0.111.2
|
||||
-- Module Version: 7.5
|
||||
-- Sun Apr 22 17:34:06 2018
|
||||
-- Sun May 10 13:18:44 2020
|
||||
|
||||
-- parameterized module component declaration
|
||||
component gram0
|
||||
|
@ -1,5 +1,5 @@
|
||||
SCUBA, Version Diamond (64-bit) 3.10.0.111.2
|
||||
Sun Apr 22 17:34:06 2018
|
||||
Sun May 10 13:18:44 2020
|
||||
|
||||
Copyright (c) 1991-1994 by NeoCAD Inc. All rights reserved.
|
||||
Copyright (c) 1995 AT&T Corp. All rights reserved.
|
||||
@ -9,7 +9,7 @@ Copyright (c) 2002-2017 Lattice Semiconductor Corporation, All rights reserved.
|
||||
|
||||
BEGIN SCUBA Module Synthesis
|
||||
|
||||
Issued command : /usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
Issued command : /usr/local/diamond/3.10_x64/ispfpga/bin/lin64/scuba -w -n gram0 -lang vhdl -synth synplify -bus_exp 7 -bb -arch xo2c00 -type ramdp -device LCMXO2-1200HC -aaddr_width 13 -widtha 9 -baddr_width 13 -widthb 9 -anum_words 7000 -bnum_words 7000 -outdataA REGISTERED -outdataB REGISTERED -cascade -1 -resetmode SYNC -sync_reset -memfile /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem -memformat bin -writemodeA NORMAL -writemodeB NORMAL
|
||||
Circuit name : gram0
|
||||
Module type : RAM_DP_TRUE
|
||||
Module Version : 7.5
|
||||
@ -17,7 +17,7 @@ BEGIN SCUBA Module Synthesis
|
||||
Inputs : DataInA[8:0], DataInB[8:0], AddressA[12:0], AddressB[12:0], ClockA, ClockB, ClockEnA, ClockEnB, WrA, WrB, ResetA, ResetB
|
||||
Outputs : QA[8:0], QB[8:0]
|
||||
I/O buffer : not inserted
|
||||
Memory file : /home/markus/projects/workspaceSigasi/lmg6202/bin/gram_init.mem
|
||||
Memory file : /home/markus/projects/cross-discipline/lw35-upgrade/display/tools/splash.mem
|
||||
EDIF output : gram0.edn
|
||||
VHDL output : gram0.vhd
|
||||
VHDL template : gram0_tmpl.vhd
|
||||
|
@ -1,12 +1,12 @@
|
||||
obj-m := lmg6202ulyt.o
|
||||
KDIR := ~/projects/arm-linux/current
|
||||
KDIR := ~/projects/linux/opi-current
|
||||
PWD := $(shell pwd)
|
||||
default: lmg6202ulyt.ko
|
||||
lmg6202ulyt.ko: lmg6202ulyt.c
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
$(MAKE) -C $(KDIR) M=$(PWD)
|
||||
|
||||
deploy: lmg6202ulyt.ko
|
||||
scp $< markus@opi:/home/markus/lmg6202ulyt/deploy
|
||||
scp $< markus@opi:/home/markus/projects/lw35/deploy/
|
||||
|
||||
clean:
|
||||
rm -f ./*.o ./*.ko ./*.mod.c modules.order Module.symvers
|
||||
|
@ -1,30 +0,0 @@
|
||||
&pio {
|
||||
leds_opc: led_pins {
|
||||
pins = "PA15";
|
||||
function = "gpio_out";
|
||||
};
|
||||
|
||||
lmg6202ulyt_opc: lmg6202ulyt_pins {
|
||||
pins = "PA12", "PA3";
|
||||
function = "gpio_in"; /* initial configuration */
|
||||
#gpio-cells = <3>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
lmg6202ulyt@0 {
|
||||
compatible = "hitachi,lmg6202ulyt";
|
||||
reg = <0x0>;
|
||||
spi-max-frequency = <2000000>;
|
||||
cs-gpios = <0>, <&pio 0 3 GPIO_ACTIVE_LOW>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&lmg6202ulyt_opc>;
|
||||
irq-gpios = <&pio 0 12 GPIO_ACTIVE_LOW>;
|
||||
interrupt-parent = <&pio>;
|
||||
/*interrupts = <GIC_SPI 12 IRQ_TYPE_EDGE_FALLING>;*/
|
||||
};
|
||||
};
|
@ -5,14 +5,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define BPP 8 // 8
|
||||
#define PIX_THRESHOLD 0
|
||||
#define BPP 16
|
||||
|
||||
#define LMGE_GPIO 100
|
||||
#define LMGE_OTHER 99
|
||||
@ -24,9 +20,9 @@ MODULE_AUTHOR("Markus Koch");
|
||||
MODULE_DESCRIPTION("lmg6202ulyt display driver");
|
||||
MODULE_VERSION("0.1");
|
||||
|
||||
static char *testparam = "param";
|
||||
module_param(testparam, charp, S_IRUGO);
|
||||
MODULE_PARM_DESC(testparam, "A test parameter");
|
||||
static int pix_threshold = 0;
|
||||
module_param(pix_threshold, int, 0);
|
||||
MODULE_PARM_DESC(pix_threshold, "Black / White threshold. 0-255");
|
||||
|
||||
static struct of_device_id lmg6202ulyt_dt_ids[] = {
|
||||
{ .compatible = "hitachi,lmg6202ulyt", },
|
||||
@ -34,20 +30,6 @@ static struct of_device_id lmg6202ulyt_dt_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lmg6202ulyt_dt_ids);
|
||||
|
||||
|
||||
/* IOC Declerations */
|
||||
//static int device_open(struct inode *, struct file *);
|
||||
//static int device_release(struct inode *, struct file *);
|
||||
//static ssize_t device_read(struct file *, char *, size_t, loff_t *);
|
||||
//static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
|
||||
//static struct file_operations fops = {
|
||||
// .read = device_read,
|
||||
// .write = device_write,
|
||||
// .open = device_open,
|
||||
// .release = device_release
|
||||
//};
|
||||
|
||||
/* VIDEO DRIVER Declarations */
|
||||
static const struct fb_videomode default_mode = {
|
||||
NULL, 30, 480, 128, /* name, refresh, xres, yres */
|
||||
39300, /* pixclk */
|
||||
@ -57,208 +39,14 @@ static const struct fb_videomode default_mode = {
|
||||
};
|
||||
|
||||
struct lmg6202ulyt_priv {
|
||||
/* SPI dev */
|
||||
struct spi_device *spi;
|
||||
|
||||
/* FB dev */
|
||||
struct fb_info info;
|
||||
|
||||
dma_addr_t fb_phys;
|
||||
void __iomem *fb_virt;
|
||||
u32 pseudo_palette[PALETTE_SIZE];
|
||||
|
||||
/* IOC */
|
||||
struct gpio_desc *ioc_irq;
|
||||
int ioc_irq_number;
|
||||
struct work_struct ioc_work;
|
||||
|
||||
struct gpio_desc *gpio_ioc_cs;
|
||||
|
||||
u32 deferred_instructions;
|
||||
};
|
||||
|
||||
|
||||
/* IOC Code */
|
||||
#define IOC_DEFERRED_INSTRUCTION_GETKEY (1 << 0)
|
||||
|
||||
static irqreturn_t ioc_irq_handler(int irq, void* user_data)
|
||||
{
|
||||
struct lmg6202ulyt_priv *priv = user_data;
|
||||
|
||||
priv->deferred_instructions |= IOC_DEFERRED_INSTRUCTION_GETKEY;
|
||||
|
||||
schedule_work(&priv->ioc_work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define SPI_SELECT_IOC(PRIV) {PRIV->spi->chip_select = 1; PRIV->spi->cs_gpio = desc_to_gpio(PRIV->gpio_ioc_cs);}
|
||||
#define SPI_SELECT_DISPLAY(PRIV) {PRIV->spi->chip_select = 0; PRIV->spi->cs_gpio = -2;}
|
||||
|
||||
#define SPI_COMMAND_KEYBOARD_GETKEY 0x20 /* ret: KEY, ... */
|
||||
|
||||
/* Bits of the IOC status byte */
|
||||
#define IOC_STATUS_KEYPRESSES_AVAILABLE (1 << 0)
|
||||
#define IOC_STATUS_PRINTER_PAUSED (1 << 1)
|
||||
|
||||
#define GETKEY_AMOUNT 2
|
||||
|
||||
#define SPI_SPEED_READWRITE 10000
|
||||
#define SPI_SPEED_WRITEONLY 100000
|
||||
|
||||
void spi_test_transaction(struct lmg6202ulyt_priv *priv)
|
||||
{
|
||||
char tx_buf[256] = "\x01The quick brown fox jumps over the lazy dog.\n"
|
||||
"abcdefghijklmnopqrstuvwxyz 0123456789\n"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
|
||||
"!\"#$%&'()*+,-./:;=?_`|\n\n"
|
||||
;//{0x01, 0x10, 0x20, 0x30};
|
||||
char rx_buf[256];
|
||||
int i;
|
||||
struct spi_transfer t = {
|
||||
.tx_buf = tx_buf,
|
||||
.rx_buf = rx_buf,
|
||||
.len = strlen(tx_buf),
|
||||
.speed_hz = SPI_SPEED_WRITEONLY,
|
||||
};
|
||||
tx_buf[0] = 0x01;
|
||||
// for (i =1; i < 120; ++i) {
|
||||
// tx_buf[i] = (i % 12) + '0';
|
||||
// if (tx_buf[i] == '9'+1)
|
||||
// tx_buf[i] = '\r';
|
||||
// if (tx_buf[i] == '9'+2)
|
||||
// tx_buf[i] = '\n';
|
||||
|
||||
// }
|
||||
|
||||
spi_sync_transfer(priv->spi, &t, 1);
|
||||
printk(KERN_INFO "test done.\n");
|
||||
}
|
||||
|
||||
/* https://linux-kernel-labs.github.io/master/labs/deferred_work.html */
|
||||
void ioc_defio(struct work_struct *work)
|
||||
{
|
||||
#define ioc_status rx_buf[0]
|
||||
struct lmg6202ulyt_priv *priv;
|
||||
int i;
|
||||
char rx_buf[8] = {0, 0, 0, 0}; // Minimum size: GETKEY_AMOUNT + 2
|
||||
char tx_buf[8] = {0, 0x10, 0x20, 0x30}; // Minimum size: GETKEY_AMOUNT + 2
|
||||
struct spi_transfer t = {
|
||||
.tx_buf = tx_buf,
|
||||
.rx_buf = rx_buf,
|
||||
.len = 0,
|
||||
.speed_hz = SPI_SPEED_READWRITE,
|
||||
};
|
||||
|
||||
priv = container_of(work, struct lmg6202ulyt_priv, ioc_work);
|
||||
//printk(KERN_INFO "lmg: workpriv=%p\n", priv);
|
||||
|
||||
//SPI_SELECT_DISPLAY(priv);
|
||||
priv->spi->chip_select = 1;
|
||||
priv->spi->cs_gpio = desc_to_gpio(priv->gpio_ioc_cs);
|
||||
|
||||
// if (priv->deferred_instructions & IOC_DEFERRED_INSTRUCTION_GETKEY) {
|
||||
// // Get status + n keys
|
||||
// tx_buf[0] = SPI_COMMAND_KEYBOARD_GETKEY;
|
||||
// t.len = GETKEY_AMOUNT + 2;
|
||||
|
||||
// if (spi_sync_transfer(priv->spi, &t, 1))
|
||||
// goto SPI_ERR;
|
||||
|
||||
// for (i = 2; (i < GETKEY_AMOUNT + 2) && rx_buf[i]; ++i) {
|
||||
// printk(KERN_INFO "lmg: Report key: %x\n", rx_buf[i]);
|
||||
// }
|
||||
|
||||
// if (i < GETKEY_AMOUNT + 2) {
|
||||
// printk(KERN_INFO "lmg: getkey finished.\n");
|
||||
// ioc_status &= ~IOC_STATUS_KEYPRESSES_AVAILABLE;
|
||||
// } else {
|
||||
// printk(KERN_INFO "lmg: Want more keys!!\n");
|
||||
// }
|
||||
// }
|
||||
spi_test_transaction(priv);
|
||||
|
||||
if (ioc_status) {
|
||||
// TODO: Handle non-zero IOC status
|
||||
// schedule_work(&priv->ioc_work);
|
||||
}
|
||||
|
||||
// struct spi_transfer t = {
|
||||
// .tx_buf = "HELLO\r\n",
|
||||
// .len = 7,
|
||||
// .speed_hz = 1000000,
|
||||
// };
|
||||
|
||||
// if (evil) {
|
||||
// SPI_SELECT_IOC(priv);
|
||||
// } else {
|
||||
// SPI_SELECT_DISPLAY(priv);
|
||||
// }
|
||||
// evil = !evil;
|
||||
// printk(KERN_INFO "cs %d/%d", priv->spi->chip_select, priv->spi->cs_gpio);
|
||||
|
||||
// spi_sync_transfer(priv->spi, &t, 1);
|
||||
|
||||
// printk(KERN_INFO "lmg: SPI transaction done: %d\n", ret);
|
||||
|
||||
return;
|
||||
SPI_ERR:
|
||||
printk(KERN_ERR "lmg: IOC SPI transaction failed!\n");
|
||||
}
|
||||
|
||||
static int ioc_probe(struct spi_device *spi,
|
||||
struct lmg6202ulyt_priv *priv)
|
||||
{
|
||||
priv->ioc_irq_number = -1;
|
||||
printk(KERN_INFO "probe priv=%p", priv);
|
||||
|
||||
// priv->ioc_work = devm_kzalloc(&spi->dev, sizeof(struct work_struct),
|
||||
// GFP_KERNEL);
|
||||
// if (!priv->ioc_work) {
|
||||
// dev_err(&spi->dev,
|
||||
// "IOC defio memory allocation failed\n");
|
||||
// return -ENOMEM;
|
||||
// }
|
||||
|
||||
INIT_WORK(&priv->ioc_work, ioc_defio);
|
||||
|
||||
printk(KERN_INFO "lmg: ioc defio init complete");
|
||||
|
||||
priv->gpio_ioc_cs = gpiod_get_index(&spi->dev,
|
||||
"cs",
|
||||
1,
|
||||
GPIOD_OUT_LOW);
|
||||
|
||||
priv->ioc_irq = gpiod_get_index(&spi->dev,
|
||||
"irq",
|
||||
0,
|
||||
GPIOD_IN);
|
||||
|
||||
if (IS_ERR(priv->ioc_irq)) {
|
||||
printk(KERN_ERR "lmg: Error obtaining IRQ GPIO");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
priv->ioc_irq_number = gpiod_to_irq(priv->ioc_irq);
|
||||
|
||||
if (priv->ioc_irq_number < 0) {
|
||||
printk(KERN_ERR "lmg: Error retrieving IRQ number for GPIO. ret=%d\n", priv->ioc_irq_number);
|
||||
return -EIO;
|
||||
}
|
||||
printk(KERN_INFO "Found IRQ number: %d\n", priv->ioc_irq_number);
|
||||
|
||||
if (request_irq(priv->ioc_irq_number, ioc_irq_handler, 0, "ioc", (void*) priv)) {
|
||||
printk(KERN_ERR "lmg: Can't allocate irq %d\n", priv->ioc_irq_number);
|
||||
priv->ioc_irq_number = -1;
|
||||
return -EBUSY;
|
||||
}
|
||||
printk(KERN_INFO "IRQ configuration complete\n");
|
||||
|
||||
priv->deferred_instructions = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* VIDEO DRIVER CODE */
|
||||
|
||||
static int lmg6202ulyt_init_var(struct lmg6202ulyt_priv *priv)
|
||||
{
|
||||
struct fb_var_screeninfo *var = &priv->info.var;
|
||||
@ -333,7 +121,9 @@ static int lmg6202ulyt_init_fix(struct lmg6202ulyt_priv *priv)
|
||||
else
|
||||
fix->visual = FB_VISUAL_TRUECOLOR;
|
||||
|
||||
printk(KERN_INFO "lmg6202ulyt: Using %d bpp.\n", var->bits_per_pixel);
|
||||
printk(KERN_INFO "lmg6202ulyt: Using %d bpp (%s).\n",
|
||||
var->bits_per_pixel,
|
||||
(var->grayscale ? "grayscale" : "truecolor"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -420,6 +210,7 @@ void lmg6202ulyt_deferred_io(struct fb_info *info, struct list_head *pagelist)
|
||||
int i;
|
||||
int blk;
|
||||
char __iomem *pixel;
|
||||
char pixval;
|
||||
int txsz;
|
||||
|
||||
spi_write(priv->spi, buf, 5);
|
||||
@ -430,7 +221,13 @@ void lmg6202ulyt_deferred_io(struct fb_info *info, struct list_head *pagelist)
|
||||
buf[0] = 1;
|
||||
|
||||
for (i = 0; i < BLOCKSIZE * 8; i++) {
|
||||
if (*pixel > PIX_THRESHOLD) {
|
||||
#if BPP == 8
|
||||
pixval = *(pixel);
|
||||
#else
|
||||
pixval = *(pixel + 1);
|
||||
// TODO: We should have more cases here for higher BPPs
|
||||
#endif
|
||||
if (pixval > pix_threshold) {
|
||||
buf[(i / 8) + 1] |= (1 << (7 - (i % 8)));
|
||||
}
|
||||
if (pixel >= info->screen_base + info->screen_size - ((info->var.bits_per_pixel) / 8))
|
||||
@ -451,7 +248,6 @@ static int lmg6202ulyt_probe(struct spi_device *spi)
|
||||
{
|
||||
struct lmg6202ulyt_priv *priv = NULL;
|
||||
struct fb_deferred_io *fbdefio = NULL;
|
||||
|
||||
int fbsize;
|
||||
int ret;
|
||||
|
||||
@ -470,10 +266,6 @@ static int lmg6202ulyt_probe(struct spi_device *spi)
|
||||
priv->info.device = &spi->dev;
|
||||
priv->info.par = priv;
|
||||
|
||||
ioc_probe(spi, priv); // TODO: Handle return value
|
||||
|
||||
printk(KERN_INFO "lmg6202ulyt: DEBUG: SKIP DISPLAY INIT\n");
|
||||
return 0;
|
||||
|
||||
printk(KERN_INFO "lmg6202ulyt: vmode\n");
|
||||
|
||||
@ -562,16 +354,7 @@ static int lmg6202ulyt_remove(struct spi_device *spi)
|
||||
struct lmg6202ulyt_priv *priv = spi_get_drvdata(spi);
|
||||
|
||||
//unregister_framebuffer(&priv->info);
|
||||
|
||||
printk(KERN_INFO "DEBUG: SKIPPING framebuffer dealloc");
|
||||
//fb_dealloc_cmap(&priv->info.cmap); // TODO: reenable
|
||||
|
||||
|
||||
if (priv->ioc_irq_number >= 0)
|
||||
free_irq(priv->ioc_irq_number, priv);
|
||||
gpiod_put(priv->ioc_irq);
|
||||
|
||||
gpiod_put(priv->gpio_ioc_cs);
|
||||
fb_dealloc_cmap(&priv->info.cmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1
display/tools/.gitignore
vendored
1
display/tools/.gitignore
vendored
@ -1,3 +1,2 @@
|
||||
*.raw
|
||||
*.mem
|
||||
*.png
|
||||
|
BIN
display/tools/splashscreen.png
Normal file
BIN
display/tools/splashscreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
BIN
doc/architecture.dia
Normal file
BIN
doc/architecture.dia
Normal file
Binary file not shown.
12
doc/ioc.md
Normal file
12
doc/ioc.md
Normal file
@ -0,0 +1,12 @@
|
||||
# IOC
|
||||
|
||||
## Firmware
|
||||
### General
|
||||
* All serial links run at 19200 baud
|
||||
|
||||
### Bootloader
|
||||
* The bootloader is a standard Arduino bootloader with the following additions
|
||||
* Use ASCII command 'X' to enable byass mode. Everything received on UART RX will be forwarded to UART TX until the next reset.
|
||||
* Use ASCII command 'Y' to set the next unit in the chain into bypass mode.
|
||||
* Use ASCII command 'Z' to immediately launch into the user firmware
|
||||
* Use the following avrdude command to program: `avrdude -p m8 -P /dev/ttyUSBx -c arduino -b 19200 -U flash:w:$(TARGET).hex`
|
8
ioc/avr-bootloader/.gitignore
vendored
Normal file
8
ioc/avr-bootloader/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.srec
|
||||
*.s
|
||||
*.o
|
||||
*.map
|
||||
*.lst
|
||||
*.hex
|
||||
*.elf
|
||||
*.bin
|
440
ioc/avr-bootloader/main.c
Normal file
440
ioc/avr-bootloader/main.c
Normal file
@ -0,0 +1,440 @@
|
||||
/**********************************************************/
|
||||
/* Serial Bootloader for Atmel mega8 AVR Controller */
|
||||
/* */
|
||||
/* ATmegaBOOT.c */
|
||||
/* */
|
||||
/* Copyright (c) 2003, Jason P. Kyle */
|
||||
/* */
|
||||
/* Hacked by DojoCorp - ZGZ - MMX - IVR */
|
||||
/* Hacked by David A. Mellis */
|
||||
/* Hacked by Markus Koch */
|
||||
/* */
|
||||
/* This program is free software; you can redistribute it */
|
||||
/* and/or modify it under the terms of the GNU General */
|
||||
/* Public License as published by the Free Software */
|
||||
/* Foundation; either version 2 of the License, or */
|
||||
/* (at your option) any later version. */
|
||||
/* */
|
||||
/* This program is distributed in the hope that it will */
|
||||
/* be useful, but WITHOUT ANY WARRANTY; without even the */
|
||||
/* implied warranty of MERCHANTABILITY or FITNESS FOR A */
|
||||
/* PARTICULAR PURPOSE. See the GNU General Public */
|
||||
/* License for more details. */
|
||||
/* */
|
||||
/* You should have received a copy of the GNU General */
|
||||
/* Public License along with this program; if not, write */
|
||||
/* to the Free Software Foundation, Inc., */
|
||||
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
/* */
|
||||
/* Licence can be viewed at */
|
||||
/* http://www.fsf.org/licenses/gpl.txt */
|
||||
/* */
|
||||
/* Target = Atmel AVR m8 */
|
||||
/**********************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#define MAX_TIME_COUNT (F_CPU>>4)
|
||||
|
||||
/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
|
||||
#define HW_VER 0x02
|
||||
#define SW_MAJOR 0x01
|
||||
#define SW_MINOR 0x12
|
||||
|
||||
// AVR-GCC compiler compatibility
|
||||
// avr-gcc compiler v3.1.x and older doesn't support outb() and inb()
|
||||
// if necessary, convert outb and inb to outp and inp
|
||||
#ifndef outb
|
||||
#define outb(sfr,val) (_SFR_BYTE(sfr) = (val))
|
||||
#endif
|
||||
#ifndef inb
|
||||
#define inb(sfr) _SFR_BYTE(sfr)
|
||||
#endif
|
||||
|
||||
/* defines for future compatibility */
|
||||
#ifndef cbi
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif
|
||||
#ifndef sbi
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif
|
||||
|
||||
/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
|
||||
#define eeprom_rb(addr) eeprom_read_byte ((uint8_t *)(addr))
|
||||
#define eeprom_rw(addr) eeprom_read_word ((uint16_t *)(addr))
|
||||
#define eeprom_wb(addr, val) eeprom_write_byte ((uint8_t *)(addr), (uint8_t)(val))
|
||||
|
||||
|
||||
#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
|
||||
#define SIG2 0x93
|
||||
#define SIG3 0x07
|
||||
#define PAGE_SIZE 0x20U //32 words
|
||||
|
||||
|
||||
void putch(char);
|
||||
char getch(void);
|
||||
void getNch(uint8_t);
|
||||
void byte_response(uint8_t);
|
||||
void nothing_response(void);
|
||||
|
||||
union address_union {
|
||||
uint16_t word;
|
||||
uint8_t byte[2];
|
||||
} address;
|
||||
|
||||
union length_union {
|
||||
uint16_t word;
|
||||
uint8_t byte[2];
|
||||
} length;
|
||||
|
||||
struct flags_struct {
|
||||
unsigned eeprom : 1;
|
||||
unsigned rampz : 1;
|
||||
} flags;
|
||||
|
||||
uint8_t buff[256];
|
||||
//uint8_t address_high;
|
||||
|
||||
uint8_t pagesz=0x80;
|
||||
|
||||
uint8_t i;
|
||||
//uint8_t bootuart0=0,bootuart1=0;
|
||||
|
||||
|
||||
void (*app_start)(void) = 0x0000;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t ch,ch2;
|
||||
uint16_t w;
|
||||
|
||||
/* Disable interrupts */
|
||||
cli();
|
||||
|
||||
/* Pre-init I/O */
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
|
||||
asm volatile("nop\n\t");
|
||||
|
||||
/* initialize UART(s) depending on CPU defined */
|
||||
/* m8 */
|
||||
UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
|
||||
UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
|
||||
UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
|
||||
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
|
||||
|
||||
/*for (i = 0; i < 16; i++) {
|
||||
_delay_loop_2(0);
|
||||
}*/
|
||||
|
||||
/* forever */
|
||||
for (;;) {
|
||||
//if ((inb(UCSRA) & _BV(RXC))){
|
||||
/* get character from UART */
|
||||
ch = getch();
|
||||
|
||||
/* A bunch of if...else if... gives smaller code than switch...case ! */
|
||||
|
||||
/* Hello is anyone home ? */
|
||||
if (ch == '0') {
|
||||
nothing_response();
|
||||
}
|
||||
|
||||
/* Request programmer ID */
|
||||
/* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
|
||||
/* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
|
||||
else if (ch == '1') {
|
||||
if (getch() == ' ') {
|
||||
putch(0x14);
|
||||
putch('A');
|
||||
putch('V');
|
||||
putch('R');
|
||||
putch(' ');
|
||||
putch('I');
|
||||
putch('S');
|
||||
putch('P');
|
||||
putch(0x10);
|
||||
}
|
||||
}
|
||||
|
||||
/* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
|
||||
else if (ch == '@') {
|
||||
ch2 = getch();
|
||||
if (ch2>0x85) getch();
|
||||
nothing_response();
|
||||
}
|
||||
|
||||
/* AVR ISP/STK500 board requests */
|
||||
else if (ch == 'A') {
|
||||
ch2 = getch();
|
||||
if (ch2==0x80) byte_response(HW_VER); // Hardware version
|
||||
else if (ch2==0x81) byte_response(SW_MAJOR); // Software major version
|
||||
else if (ch2==0x82) byte_response(SW_MINOR); // Software minor version
|
||||
//else if (ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56
|
||||
else byte_response(0x00); // Covers various unnecessary responses we don't care about
|
||||
}
|
||||
|
||||
/* Device Parameters DON'T CARE, DEVICE IS FIXED */
|
||||
else if (ch == 'B') {
|
||||
getNch(20);
|
||||
nothing_response();
|
||||
}
|
||||
|
||||
/* Parallel programming stuff DON'T CARE */
|
||||
else if (ch == 'E') {
|
||||
getNch(5);
|
||||
nothing_response();
|
||||
}
|
||||
|
||||
/* Enter programming mode */
|
||||
else if (ch == 'P') {
|
||||
nothing_response();
|
||||
// FIXME: modified only here by DojoCorp, Mumbai, India, 20050626
|
||||
//time_count=0; // exted the delay once entered prog.mode
|
||||
}
|
||||
|
||||
/* Leave programming mode */
|
||||
else if (ch == 'Q') {
|
||||
nothing_response();
|
||||
//time_count=MAX_TIME_COUNT_MORATORY; // once the programming is done,
|
||||
// we should start the application
|
||||
// but uisp has problems with this,
|
||||
// therefore we just change the times
|
||||
// and give the programmer 1 sec to react
|
||||
}
|
||||
|
||||
/* Set to bypass until restart */
|
||||
else if (ch == 'X') {
|
||||
while (1) {
|
||||
if (UCSRA & (1 << RXC)) {
|
||||
UDR = UDR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send 'X' via UART TX (set next unit to bypass) */
|
||||
else if (ch == 'Y') {
|
||||
putch('X');
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Start user code NOW */
|
||||
else if (ch == 'Z') {
|
||||
app_start();
|
||||
}
|
||||
|
||||
/* Erase device, don't care as we will erase one page at a time anyway. */
|
||||
else if (ch == 'R') {
|
||||
nothing_response();
|
||||
}
|
||||
|
||||
/* Set address, little endian. EEPROM in bytes, FLASH in words */
|
||||
/* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
|
||||
/* This might explain why little endian was used here, big endian used everywhere else. */
|
||||
else if (ch == 'U') {
|
||||
address.byte[0] = getch();
|
||||
address.byte[1] = getch();
|
||||
nothing_response();
|
||||
}
|
||||
|
||||
/* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
|
||||
else if (ch == 'V') {
|
||||
getNch(4);
|
||||
byte_response(0x00);
|
||||
}
|
||||
|
||||
/* Write memory, length is big endian and is in bytes */
|
||||
else if (ch == 'd') {
|
||||
length.byte[1] = getch();
|
||||
length.byte[0] = getch();
|
||||
flags.eeprom = 0;
|
||||
if (getch() == 'E') flags.eeprom = 1;
|
||||
for (w=0; w<length.word; w++) {
|
||||
buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
|
||||
}
|
||||
if (getch() == ' ') {
|
||||
if (flags.eeprom) { //Write to EEPROM one byte at a time
|
||||
for(w=0;w<length.word;w++) {
|
||||
eeprom_wb(address.word,buff[w]);
|
||||
address.word++;
|
||||
}
|
||||
} else { //Write to FLASH one page at a time
|
||||
cli(); //Disable interrupts, just to be sure
|
||||
while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete
|
||||
asm volatile(
|
||||
"clr r17 \n\t" //page_word_count
|
||||
"lds r30,address \n\t" //Address of FLASH location (in words)
|
||||
"lds r31,address+1 \n\t"
|
||||
"lsl r30 \n\t" //address * 2 -> byte location
|
||||
"rol r31 \n\t"
|
||||
"ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
|
||||
"ldi r29,hi8(buff) \n\t"
|
||||
"lds r24,length \n\t" //Length of data to be written (in bytes)
|
||||
"lds r25,length+1 \n\t"
|
||||
"sbrs r24,0 \n\t" //Even up an odd number of bytes
|
||||
"rjmp length_loop \n\t"
|
||||
"adiw r24,1 \n\t"
|
||||
"length_loop: \n\t" //Main loop, repeat for number of words in block
|
||||
"cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
|
||||
"brne no_page_erase \n\t"
|
||||
"rcall wait_spm \n\t"
|
||||
|
||||
"ldi r16,0x03 \n\t" //Erase page pointed to by Z
|
||||
"sts %0,r16 \n\t"
|
||||
"spm \n\t"
|
||||
"rcall wait_spm \n\t"
|
||||
|
||||
"ldi r16,0x11 \n\t" //Re-enable RWW section
|
||||
"sts %0,r16 \n\t"
|
||||
"spm \n\t"
|
||||
"no_page_erase: \n\t"
|
||||
"ld r0,Y+ \n\t" //Write 2 bytes into page buffer
|
||||
"ld r1,Y+ \n\t"
|
||||
|
||||
"rcall wait_spm \n\t"
|
||||
|
||||
"ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
|
||||
"sts %0,r16 \n\t"
|
||||
"spm \n\t"
|
||||
|
||||
"inc r17 \n\t" //page_word_count++
|
||||
"cpi r17,%1 \n\t"
|
||||
"brlo same_page \n\t" //Still same page in FLASH
|
||||
"write_page: \n\t"
|
||||
"clr r17 \n\t" //New page, write current one first
|
||||
"rcall wait_spm \n\t"
|
||||
|
||||
"ldi r16,0x05 \n\t" //Write page pointed to by Z
|
||||
"sts %0,r16 \n\t"
|
||||
"spm \n\t"
|
||||
"rcall wait_spm \n\t"
|
||||
|
||||
"ldi r16,0x11 \n\t" //Re-enable RWW section
|
||||
"sts %0,r16 \n\t"
|
||||
"spm \n\t"
|
||||
"same_page: \n\t"
|
||||
"adiw r30,2 \n\t" //Next word in FLASH
|
||||
"sbiw r24,2 \n\t" //length-2
|
||||
"breq final_write \n\t" //Finished
|
||||
"rjmp length_loop \n\t"
|
||||
|
||||
"wait_spm: \n\t"
|
||||
"lds r16,%0 \n\t" //Wait for previous spm to complete
|
||||
"andi r16,1 \n\t"
|
||||
"cpi r16,1 \n\t"
|
||||
"breq wait_spm \n\t"
|
||||
"ret \n\t"
|
||||
|
||||
"final_write: \n\t"
|
||||
"cpi r17,0 \n\t"
|
||||
"breq block_done \n\t"
|
||||
"adiw r24,2 \n\t" //length+2, fool above check on length after short page write
|
||||
"rjmp write_page \n\t"
|
||||
"block_done: \n\t"
|
||||
"clr __zero_reg__ \n\t" //restore zero register
|
||||
: "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31");
|
||||
|
||||
/* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
|
||||
/* exit the bootloader without a power cycle anyhow */
|
||||
}
|
||||
putch(0x14);
|
||||
putch(0x10);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read memory block mode, length is big endian. */
|
||||
else if (ch == 't') {
|
||||
length.byte[1] = getch();
|
||||
length.byte[0] = getch();
|
||||
if (getch() == 'E') flags.eeprom = 1;
|
||||
else {
|
||||
flags.eeprom = 0;
|
||||
address.word = address.word << 1; // address * 2 -> byte location
|
||||
}
|
||||
if (getch() == ' ') { // Command terminator
|
||||
putch(0x14);
|
||||
for (w=0; w < length.word; w++) { // Can handle odd and even lengths okay
|
||||
if (flags.eeprom) { // Byte access EEPROM read
|
||||
putch(eeprom_rb(address.word));
|
||||
address.word++;
|
||||
} else {
|
||||
if (!flags.rampz) putch(pgm_read_byte_near(address.word));
|
||||
address.word++;
|
||||
}
|
||||
}
|
||||
putch(0x10);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get device signature bytes */
|
||||
else if (ch == 'u') {
|
||||
if (getch() == ' ') {
|
||||
putch(0x14);
|
||||
putch(SIG1);
|
||||
putch(SIG2);
|
||||
putch(SIG3);
|
||||
putch(0x10);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read oscillator calibration byte */
|
||||
else if (ch == 'v') {
|
||||
byte_response(0x00);
|
||||
}
|
||||
} /* end of forever loop */
|
||||
}
|
||||
|
||||
void putch(char ch)
|
||||
{
|
||||
/* m8 */
|
||||
while (!(inb(UCSRA) & _BV(UDRE)));
|
||||
outb(UDR,ch);
|
||||
}
|
||||
|
||||
char getch(void)
|
||||
{
|
||||
/* m8 */
|
||||
uint32_t count = 0;
|
||||
while(!(inb(UCSRA) & _BV(RXC))) {
|
||||
/* HACKME:: here is a good place to count times*/
|
||||
count++;
|
||||
if (count > MAX_TIME_COUNT)
|
||||
app_start();
|
||||
}
|
||||
return (inb(UDR));
|
||||
}
|
||||
|
||||
void getNch(uint8_t count)
|
||||
{
|
||||
uint8_t i;
|
||||
for(i=0;i<count;i++) {
|
||||
getch(); // need to handle time out
|
||||
}
|
||||
}
|
||||
|
||||
void byte_response(uint8_t val)
|
||||
{
|
||||
if (getch() == ' ') {
|
||||
putch(0x14);
|
||||
putch(val);
|
||||
putch(0x10);
|
||||
}
|
||||
}
|
||||
|
||||
void nothing_response(void)
|
||||
{
|
||||
if (getch() == ' ') {
|
||||
putch(0x14);
|
||||
putch(0x10);
|
||||
}
|
||||
}
|
2
ioc/kernel-driver/.gitignore
vendored
2
ioc/kernel-driver/.gitignore
vendored
@ -4,3 +4,5 @@
|
||||
modules.order
|
||||
Module.symvers
|
||||
*.pro.user
|
||||
.*
|
||||
*.a
|
||||
|
@ -1,12 +1,12 @@
|
||||
obj-m := lw35-ioc.o
|
||||
KDIR := ~/projects/arm-linux/current
|
||||
obj-m := lw35ioc.o
|
||||
KDIR := ~/projects/linux/opi-current
|
||||
PWD := $(shell pwd)
|
||||
default: lw35-ioc.ko
|
||||
lw35-ioc.ko: lw35-ioc.c
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
|
||||
default: lw35ioc.ko
|
||||
lw35ioc.ko: lw35ioc.c
|
||||
$(MAKE) -C $(KDIR) M=$(PWD)
|
||||
|
||||
deploy: lw35-ioc.ko
|
||||
scp $< markus@opi:/home/markus/lw35-ioc/deploy
|
||||
deploy: lw35ioc.ko
|
||||
scp $< markus@opi:/home/markus/projects/lw35/deploy/
|
||||
|
||||
clean:
|
||||
rm -f ./*.o ./*.ko ./*.mod.c modules.order Module.symvers
|
||||
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
Reading: https://www.kernel.org/doc/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
*/
|
||||
|
||||
&spi1 {
|
||||
status = "okay";
|
||||
lw35ioc@0 {
|
||||
compatible = "brother,lw35ioc";
|
||||
reg = <0x0>;
|
||||
spi-max-frequency = <2000000>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&lw35ioc>;
|
||||
data-gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* TODO: get real IO num */
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <52 2>;
|
||||
};
|
||||
};
|
||||
|
||||
&pio {
|
||||
lmg6202ulyt_opc: lmg6202ulyt_pins {
|
||||
pins = "PA7";
|
||||
function = "gpio_out";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
41
ioc/kernel-driver/device-tree-opi-pc.patch
Normal file
41
ioc/kernel-driver/device-tree-opi-pc.patch
Normal file
@ -0,0 +1,41 @@
|
||||
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
|
||||
index c8201e79dff3..5407742acad6 100644
|
||||
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
|
||||
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
|
||||
@@ -210,12 +210,22 @@ &uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&pio {
|
||||
+ lw35ioc_pins: lw35ioc-pins {
|
||||
+ pins = "PA10";
|
||||
+ function = "gpio_out";
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart1_pins>;
|
||||
lw35ioc@0 {
|
||||
compatible = "brother,lw35";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&lw35ioc_pins>;
|
||||
+ rst-gpios = <&pio 0 10 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -242,3 +252,13 @@ &usbphy {
|
||||
/* VBUS on USB host ports are always on */
|
||||
status = "okay";
|
||||
};
|
||||
+
|
||||
+&spi0 {
|
||||
+ status = "okay";
|
||||
+ lmg6202ulyt@0 {
|
||||
+ compatible = "hitachi,lmg6202ulyt";
|
||||
+ reg = <0x0>;
|
||||
+ spi-max-frequency = <2000000>;
|
||||
+ cs-gpios = <0>, <&pio 0 3 GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+};
|
@ -1,78 +0,0 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
/*
|
||||
* irq in general: https://notes.shichao.io/lkd/ch7/
|
||||
* raspi irqs: http://morethanuser.blogspot.com/2013/04/raspberry-pi-gpio-interrupts-in-kernel.html
|
||||
* kdoc devtree irq: https://www.kernel.org/doc/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
* GPIOD doc (including irq): https://www.kernel.org/doc/Documentation/gpio/consumer.txt
|
||||
*/
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Markus Koch");
|
||||
MODULE_DESCRIPTION("LW35 I/O Controller Driver");
|
||||
MODULE_VERSION("0.1");
|
||||
|
||||
static char *testparam = "param";
|
||||
module_param(testparam, charp, S_IRUGO);
|
||||
MODULE_PARM_DESC(testparam, "A test parameter");
|
||||
|
||||
static struct of_device_id lw35ioc_dt_ids[] = {
|
||||
{ .compatible = "brother,lw35", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lw35ioc_dt_ids);
|
||||
|
||||
struct lw35ioc_priv {
|
||||
struct spi_device *spi;
|
||||
|
||||
// USER VARS HERE
|
||||
};
|
||||
|
||||
static int lw35ioc_probe(struct spi_device *spi)
|
||||
{
|
||||
struct lw35ioc_priv *priv = NULL;
|
||||
|
||||
printk(KERN_INFO "lw35ioc: probe\n");
|
||||
|
||||
priv = devm_kzalloc(&spi->dev,
|
||||
sizeof(struct lw35ioc_priv),
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
spi_set_drvdata(spi, priv);
|
||||
|
||||
priv->spi = spi;
|
||||
|
||||
printk(KERN_INFO "lw35ioc: Loaded driver\n");
|
||||
|
||||
return 0;
|
||||
|
||||
// Error handlers go here
|
||||
}
|
||||
|
||||
static int lw35ioc_remove(struct spi_device *spi)
|
||||
{
|
||||
struct lw35ioc_priv *priv = spi_get_drvdata(spi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver lw35ioc_driver = {
|
||||
.probe = lw35ioc_probe,
|
||||
.remove = lw35ioc_remove,
|
||||
.driver = {
|
||||
.name = "lw35ioc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = lw35ioc_dt_ids,
|
||||
},
|
||||
};
|
||||
module_spi_driver(lw35ioc_driver);
|
||||
|
744
ioc/kernel-driver/lw35ioc.c
Normal file
744
ioc/kernel-driver/lw35ioc.c
Normal file
@ -0,0 +1,744 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/serdev.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/circ_buf.h>
|
||||
|
||||
// #define ENABLE_DEBUG ENABLE_DEBUG
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Markus Koch");
|
||||
MODULE_DESCRIPTION("LW-35 I/O Controller Driver");
|
||||
MODULE_VERSION("0.1");
|
||||
|
||||
static int debug_level = 0;
|
||||
module_param(debug_level, int, 0);
|
||||
MODULE_PARM_DESC(debug_level, "Debug level");
|
||||
|
||||
/* Only for chrdev... man they really suck! */
|
||||
static struct serdev_device *static_serdev = NULL;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(wq);
|
||||
|
||||
void pbuf_work_handler(struct work_struct *work);
|
||||
DECLARE_WORK(pbuf_work, pbuf_work_handler);
|
||||
|
||||
static DEFINE_SPINLOCK(printer_status_lock);
|
||||
|
||||
static struct of_device_id lw35ioc_dt_ids[] = {
|
||||
{ .compatible = "brother,lw35", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lw35ioc_dt_ids);
|
||||
|
||||
/* Chardev */
|
||||
#define DEVICE_NAME "lw35"
|
||||
#define CLASS_NAME "lw35ioc"
|
||||
|
||||
/* Only used for initialization, not for actual keycode mapping */
|
||||
static int keycode_map[] = {
|
||||
KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
|
||||
KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
|
||||
KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z,
|
||||
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
|
||||
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9,
|
||||
KEY_F10, KEY_F11, KEY_F12,
|
||||
KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT, KEY_PAGEUP, KEY_PAGEDOWN,
|
||||
KEY_102ND, KEY_INSERT, KEY_HOME, KEY_END, KEY_PRINT,
|
||||
KEY_CAPSLOCK, KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_TAB,
|
||||
KEY_MINUS, KEY_COMMA, KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_LEFTBRACE,
|
||||
KEY_GRAVE, KEY_SPACE, KEY_EQUAL, KEY_DOT, KEY_SLASH, KEY_APOSTROPHE,
|
||||
KEY_BACKSLASH,
|
||||
KEY_DELETE, KEY_ESC, KEY_ENTER, KEY_BACKSPACE,
|
||||
KEY_SYSRQ
|
||||
};
|
||||
|
||||
enum lw35ioc_state {PASSIVE = 0, INIT, PROG_KBD, PROG_PRI, BYPASS, ACTIVE, STATE_COUNT};
|
||||
|
||||
enum lw35ioc_packet_state {SYNC, TYPE, KEYBOARD, PRINTER};
|
||||
|
||||
struct lw35ioc_packet {
|
||||
enum lw35ioc_packet_state state;
|
||||
int payload_offset;
|
||||
};
|
||||
|
||||
struct lw35ioc_chardev {
|
||||
int major_number;
|
||||
struct class* class;
|
||||
struct device* device;
|
||||
int open_count;
|
||||
};
|
||||
|
||||
struct lw35ioc_printer_status{
|
||||
int buffer_free;
|
||||
int status;
|
||||
int rx_count;
|
||||
int reserved1;
|
||||
};
|
||||
|
||||
#define UART_BUF_SIZE 256
|
||||
#define PBUF_SIZE 256
|
||||
|
||||
struct lw35ioc_priv {
|
||||
struct serdev_device *serdev;
|
||||
struct input_dev *input_dev;
|
||||
struct gpio_desc *gpio_rst; /* GPIO to reset both AVRs */
|
||||
struct lw35ioc_chardev chardev;
|
||||
|
||||
struct lw35ioc_printer_status printer_status_temp;
|
||||
struct lw35ioc_printer_status printer_status;
|
||||
|
||||
char uart_buf_rx[UART_BUF_SIZE];
|
||||
char *uart_buf_rx_rd;
|
||||
char *uart_buf_rx_wr;
|
||||
|
||||
char pbuf[PBUF_SIZE];
|
||||
unsigned long pbuf_tail;
|
||||
unsigned long pbuf_head;
|
||||
|
||||
enum lw35ioc_state state;
|
||||
struct lw35ioc_packet packet;
|
||||
|
||||
u8 tx_count;
|
||||
u8 tx_count_resync;
|
||||
};
|
||||
|
||||
|
||||
static int lw35ioc_process_buf(struct serdev_device *serdev,
|
||||
const unsigned char *data,
|
||||
size_t count)
|
||||
{
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
unsigned char c;
|
||||
int ev;
|
||||
int i;
|
||||
unsigned long lock_flags;
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
dev_info(&serdev->dev, "IRQ.\n");
|
||||
#endif
|
||||
for (i = 0; i < count; ++i) {
|
||||
c = data[i];
|
||||
#ifdef ENABLE_DEBUG
|
||||
dev_info(&serdev->dev, " RX [%d]: %02x\n", priv->packet.state, c);
|
||||
#endif
|
||||
switch (priv->packet.state) {
|
||||
case SYNC:
|
||||
if (c == 0xFF)
|
||||
priv->packet.state = TYPE;
|
||||
break;
|
||||
|
||||
case TYPE:
|
||||
if (c == 0x55)
|
||||
priv->packet.state = KEYBOARD;
|
||||
else if (c == 0xAA)
|
||||
priv->packet.state = PRINTER;
|
||||
else
|
||||
priv->packet.state = SYNC;
|
||||
priv->packet.payload_offset = 0;
|
||||
break;
|
||||
|
||||
case KEYBOARD:
|
||||
if (c > 127) {
|
||||
c -= 128;
|
||||
ev = 1;
|
||||
} else {
|
||||
ev = 0;
|
||||
}
|
||||
input_report_key(priv->input_dev, c, ev);
|
||||
input_sync(priv->input_dev);
|
||||
priv->packet.state = SYNC;
|
||||
break;
|
||||
|
||||
case PRINTER:
|
||||
switch (priv->packet.payload_offset) {
|
||||
case 0: /* Status */
|
||||
priv->printer_status_temp.status = (int)c;
|
||||
break;
|
||||
case 1: /* Buffer status */
|
||||
priv->printer_status_temp.buffer_free = (int)c;
|
||||
break;
|
||||
case 2: /* Reserved */
|
||||
priv->printer_status_temp.rx_count = (int)c;
|
||||
break;
|
||||
case 3: /* Reserved */
|
||||
priv->printer_status_temp.reserved1 = (int)c;
|
||||
|
||||
dev_info(&serdev->dev,
|
||||
"New printer status. status=0x%02X buffer_free=0x%02X rx_count=0x%02X reserved=0x%02X.\n",
|
||||
priv->printer_status_temp.status,
|
||||
priv->printer_status_temp.buffer_free,
|
||||
priv->printer_status_temp.rx_count,
|
||||
priv->printer_status_temp.reserved1);
|
||||
if (priv->printer_status_temp.status == 0xFF) {
|
||||
dev_err(&serdev->dev,
|
||||
"HARDFAULT in printer firmware! Reset required.\n");
|
||||
}
|
||||
spin_lock_irqsave(&printer_status_lock, lock_flags);
|
||||
memcpy(&priv->printer_status,
|
||||
&priv->printer_status_temp,
|
||||
sizeof(priv->printer_status));
|
||||
spin_unlock_irqrestore(&printer_status_lock, lock_flags);
|
||||
|
||||
if (priv->printer_status_temp.buffer_free > 0)
|
||||
schedule_work(&pbuf_work);
|
||||
|
||||
priv->packet.state = SYNC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
priv->packet.payload_offset++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int lw35ioc_receive_buf(struct serdev_device *serdev,
|
||||
const unsigned char *data,
|
||||
size_t count)
|
||||
{
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
int i;
|
||||
|
||||
switch (priv->state) {
|
||||
case ACTIVE:
|
||||
return lw35ioc_process_buf(serdev, data, count);
|
||||
break;
|
||||
case PASSIVE:
|
||||
break;
|
||||
default:
|
||||
/* Pass data directly to chardev */
|
||||
for (i = 0; i < count; ++i) {
|
||||
#ifdef ENABLE_DEBUG
|
||||
dev_info(&serdev->dev, " RX [PSV]: %02x\n", data[i]);
|
||||
#endif
|
||||
*(priv->uart_buf_rx_wr) = data[i];
|
||||
if (priv->uart_buf_rx_wr == priv->uart_buf_rx + UART_BUF_SIZE - 1)
|
||||
priv->uart_buf_rx_wr = priv->uart_buf_rx;
|
||||
else
|
||||
priv->uart_buf_rx_wr++;
|
||||
|
||||
if (priv->uart_buf_rx_rd == priv->uart_buf_rx_wr) {
|
||||
dev_err(&serdev->dev, "UART RX buffer overflow.\n");
|
||||
}
|
||||
}
|
||||
|
||||
wake_up_interruptible(&wq);
|
||||
}
|
||||
|
||||
return count; /* Pretend we read all data */
|
||||
}
|
||||
|
||||
static void lw35ioc_write_wakeup(struct serdev_device *serdev)
|
||||
{
|
||||
// schedule work here
|
||||
}
|
||||
|
||||
static struct serdev_device_ops lw35ioc_serdev_ops = {
|
||||
.receive_buf = lw35ioc_receive_buf,
|
||||
.write_wakeup = lw35ioc_write_wakeup,
|
||||
};
|
||||
|
||||
static void lw35ioc_set_hw_reset(struct serdev_device *serdev,
|
||||
int reset_active)
|
||||
{
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
gpiod_set_value(priv->gpio_rst, !!reset_active);
|
||||
}
|
||||
|
||||
static void lw35ioc_reset_ioc_hw(struct serdev_device *serdev)
|
||||
{
|
||||
dev_info(&serdev->dev, "Resetting IOC...\n");
|
||||
lw35ioc_set_hw_reset(serdev, 1);
|
||||
usleep_range(90000, 100000);
|
||||
lw35ioc_set_hw_reset(serdev, 0);
|
||||
usleep_range(90000, 100000);
|
||||
}
|
||||
|
||||
/* Chardev */
|
||||
static int lw35ioc_chardev_open(struct inode *inodep, struct file *filep) {
|
||||
struct serdev_device *serdev = static_serdev;
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
filep->private_data = serdev;
|
||||
|
||||
if (!priv->chardev.open_count) {
|
||||
dev_info(&serdev->dev, "Opened chardev.\n");
|
||||
|
||||
switch (priv->state) {
|
||||
case PROG_KBD:
|
||||
lw35ioc_reset_ioc_hw(serdev);
|
||||
serdev_device_write(serdev, "X", 1, 0);
|
||||
dev_info(&serdev->dev, "Put ioc into programming mode: keyboard.\n");
|
||||
break;
|
||||
case PROG_PRI:
|
||||
lw35ioc_reset_ioc_hw(serdev);
|
||||
serdev_device_write(serdev, "Y", 1, 0);
|
||||
dev_info(&serdev->dev, "Put ioc into programming mode: printer.\n");
|
||||
break;
|
||||
case BYPASS:
|
||||
lw35ioc_reset_ioc_hw(serdev);
|
||||
serdev_device_write(serdev, "XX", 2, 0);
|
||||
dev_info(&serdev->dev, "Put ioc into bypass mode.\n");
|
||||
break;
|
||||
case INIT:
|
||||
case PASSIVE:
|
||||
// TODO: locks
|
||||
priv->pbuf_tail = 0;
|
||||
priv->pbuf_head = 0;
|
||||
lw35ioc_reset_ioc_hw(serdev);
|
||||
usleep_range(2100000, 2210000);
|
||||
dev_info(&serdev->dev, "Put ioc into active mode.\n");
|
||||
if (priv->state == INIT) {
|
||||
serdev_device_write(serdev, "\xFF", 1, 0);
|
||||
priv->state = ACTIVE;
|
||||
}
|
||||
break;
|
||||
case ACTIVE:
|
||||
/* Don't do anything when active */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
dev_err(&serdev->dev, "Rejected. Device may only be opened once.\n");
|
||||
//return -EBUSY; // TODO
|
||||
}
|
||||
|
||||
priv->tx_count_resync = 1;
|
||||
priv->chardev.open_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t lw35ioc_chardev_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
|
||||
struct serdev_device *serdev = filep->private_data;
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
int error_count;
|
||||
int available;
|
||||
|
||||
available = priv->uart_buf_rx_wr - priv->uart_buf_rx_rd;
|
||||
if (available < 0)
|
||||
available = 1;
|
||||
if (!available) { /* Wait for data to become available */
|
||||
wait_event_interruptible(wq, priv->uart_buf_rx_rd != priv->uart_buf_rx_wr);
|
||||
available = priv->uart_buf_rx_wr - priv->uart_buf_rx_rd;
|
||||
if (available < 0)
|
||||
available = 1; /* TODO: We should calculate the remaining block until wraparound here... */
|
||||
if (!available)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (available < len)
|
||||
len = available;
|
||||
|
||||
error_count = copy_to_user(buffer, priv->uart_buf_rx_rd, len);
|
||||
len -= error_count;
|
||||
priv->uart_buf_rx_rd += len;
|
||||
if (priv->uart_buf_rx_rd >= priv->uart_buf_rx + UART_BUF_SIZE) {
|
||||
priv->uart_buf_rx_rd -= UART_BUF_SIZE;
|
||||
}
|
||||
|
||||
if (error_count == 0) {
|
||||
return len;
|
||||
} else {
|
||||
dev_err(&serdev->dev, "Failed to read %d characters to chardev.\n",
|
||||
error_count);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
char msg[256]; // TODO
|
||||
static ssize_t lw35ioc_chardev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset) {
|
||||
struct serdev_device *serdev = filep->private_data;
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
unsigned long tail;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
switch (priv->state) {
|
||||
case ACTIVE:
|
||||
/* Put data into pbuf */
|
||||
// TODO: spinlock
|
||||
if (CIRC_SPACE(priv->pbuf_head, READ_ONCE(priv->pbuf_tail), PBUF_SIZE) < 1) {
|
||||
dev_err(&serdev->dev, "chdev write: Waiting for space...\n");
|
||||
if (ret = (wait_event_interruptible(wq, CIRC_SPACE(priv->pbuf_head, priv->pbuf_tail, PBUF_SIZE) >= 1))) { // TODO: Accessing pbuf_tail without any protection... this might be bad?
|
||||
dev_err(&serdev->dev,
|
||||
"chdev write: device closed while waiting. ret: %d\n",
|
||||
ret);
|
||||
// TODO: This is not proper handling of this I guess...
|
||||
return len;
|
||||
}
|
||||
dev_err(&serdev->dev, "chdev write: done waiting...\n");
|
||||
}
|
||||
|
||||
tail = READ_ONCE(priv->pbuf_tail);
|
||||
for (i = 0; i < len; ++i) { // TODO: Block copy would be faster...
|
||||
if (CIRC_SPACE(priv->pbuf_head, tail, PBUF_SIZE) >= 1) {
|
||||
ret = copy_from_user(priv->pbuf + priv->pbuf_head,
|
||||
buffer + i,
|
||||
1);
|
||||
if (ret) {
|
||||
dev_err(&serdev->dev, "chdev write: copy_from_user failed (%d).\n",
|
||||
ret);
|
||||
i = len - 1;
|
||||
}
|
||||
smp_store_release(&(priv->pbuf_head),
|
||||
(priv->pbuf_head + 1) & (PBUF_SIZE - 1));
|
||||
} else {
|
||||
dev_warn(&serdev->dev, "chdev write: ring buffer full.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
len = i;
|
||||
|
||||
schedule_work(&pbuf_work);
|
||||
dev_info(&serdev->dev,
|
||||
"Copied %d bytes to FIFO (FIFO free: %d)",
|
||||
len, CIRC_SPACE(priv->pbuf_head, tail, PBUF_SIZE));
|
||||
break;
|
||||
case PASSIVE:
|
||||
len = -EBUSY; // TODO: Can I do this?
|
||||
break;
|
||||
default: /* Pass-through */
|
||||
if (len > 256) {
|
||||
len = 256;
|
||||
}
|
||||
copy_from_user(msg, buffer, len); // TODO: Return value
|
||||
serdev_device_write_buf(serdev, msg, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int lw35ioc_chardev_release(struct inode *inodep, struct file *filep){
|
||||
struct serdev_device *serdev = filep->private_data;
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
priv->chardev.open_count--;
|
||||
|
||||
dev_info(&serdev->dev, "Device successfully closed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define IOCTL_SET_MODE 42
|
||||
|
||||
static long lw35ioc_chardev_ioctl(struct file *filep, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct serdev_device *serdev = filep->private_data;
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
switch (cmd) {
|
||||
case IOCTL_SET_MODE:
|
||||
if (arg >= STATE_COUNT || arg < 0) {
|
||||
dev_err(&serdev->dev, "Invalid driver mode: %lu", arg);
|
||||
return -1;
|
||||
}
|
||||
priv->state = arg;
|
||||
dev_info(&serdev->dev, "Switched driver mode to: %lu. Will be applied with next open().\n", arg);
|
||||
break;
|
||||
default:
|
||||
dev_info(&serdev->dev, "Ignoring IOCTL %u(%lu)\n", cmd, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__poll_t poll(struct file *filep, struct poll_table_struct *ptab)
|
||||
{
|
||||
struct serdev_device *serdev = filep->private_data;
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
poll_wait(filep, &wq, ptab);
|
||||
|
||||
if (priv->uart_buf_rx_wr != priv->uart_buf_rx_rd)
|
||||
return EPOLLIN | EPOLLRDNORM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PRINTER_READY_MASK (0b00011111)
|
||||
int printer_ready_for_data(struct lw35ioc_printer_status printer_status)
|
||||
{
|
||||
return ((printer_status.status & PRINTER_READY_MASK) == PRINTER_READY_MASK);
|
||||
}
|
||||
|
||||
void pbuf_work_handler(struct work_struct *work)
|
||||
{
|
||||
// TODO: get private data using container_of(): https://linux-kernel-labs.github.io/master/labs/deferred_work.html
|
||||
struct serdev_device *serdev = static_serdev; // Not cool, but whatever...
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
unsigned long head;
|
||||
unsigned long tail;
|
||||
unsigned long lock_flags;
|
||||
int bsize = 0;
|
||||
int i;
|
||||
int locked = 0;
|
||||
|
||||
while (1) {
|
||||
// TODO: We are the only consumer, so we should be fine without a spinlock, right?
|
||||
head = smp_load_acquire(&priv->pbuf_head);
|
||||
tail = priv->pbuf_tail;
|
||||
bsize = CIRC_CNT(head, tail, PBUF_SIZE);
|
||||
//dev_info(&serdev->dev, "CIRC CNT=%d\n", bsize);
|
||||
if (bsize == 0)
|
||||
break;
|
||||
|
||||
spin_lock_irqsave(&printer_status_lock, lock_flags);
|
||||
locked = 1;
|
||||
if (!printer_ready_for_data(priv->printer_status)) {
|
||||
dev_warn(&serdev->dev, "Cannot transmit data to device. Device is not ready.\n");
|
||||
break;
|
||||
}
|
||||
if (priv->tx_count_resync) {
|
||||
priv->tx_count = priv->printer_status.rx_count;
|
||||
priv->tx_count_resync = 0;
|
||||
}
|
||||
if (priv->printer_status.rx_count != priv->tx_count) {
|
||||
dev_info(&serdev->dev, "Not transmitting any data to device because rx is unconfirmed [tx=%d, rx=%d].\n",
|
||||
priv->tx_count, priv->printer_status.rx_count);
|
||||
break;
|
||||
}
|
||||
if (bsize > priv->printer_status.buffer_free)
|
||||
bsize = priv->printer_status.buffer_free;
|
||||
if (bsize > CIRC_CNT_TO_END(head, tail, PBUF_SIZE))
|
||||
bsize = CIRC_CNT_TO_END(head, tail, PBUF_SIZE);
|
||||
if (bsize > priv->printer_status.buffer_free - 20)
|
||||
bsize = priv->printer_status.buffer_free - 20; // TODO: Bug workaround
|
||||
dev_info(&serdev->dev, "TX %d of %d bytes [%d bytes free on device].\n",
|
||||
bsize,
|
||||
CIRC_CNT(head, tail, PBUF_SIZE),
|
||||
priv->printer_status.buffer_free);
|
||||
priv->printer_status.buffer_free-=bsize;
|
||||
spin_unlock_irqrestore(&printer_status_lock, lock_flags);
|
||||
locked = 0;
|
||||
if (bsize == 0) {
|
||||
dev_warn(&serdev->dev, "Cannot transmit data to device. Device buffer is full.\n");
|
||||
break;
|
||||
}
|
||||
priv->tx_count += bsize;
|
||||
serdev_device_write_buf(serdev,
|
||||
priv->pbuf + tail,
|
||||
bsize);
|
||||
#ifdef ENABLE_DEBUG
|
||||
for (i=0; i<bsize; ++i) {
|
||||
dev_info(&serdev->dev,
|
||||
"UART TX: %c\n",
|
||||
priv->pbuf[tail + i]);
|
||||
}
|
||||
#endif
|
||||
smp_store_release(&priv->pbuf_tail,
|
||||
(tail + bsize) & (PBUF_SIZE - 1));
|
||||
}
|
||||
if (locked)
|
||||
spin_unlock_irqrestore(&printer_status_lock, lock_flags);
|
||||
wake_up_interruptible(&wq); // There's some space available in the FIFO now, so wake up chardev write
|
||||
}
|
||||
|
||||
|
||||
static struct file_operations fops =
|
||||
{
|
||||
.open = lw35ioc_chardev_open,
|
||||
.read = lw35ioc_chardev_read,
|
||||
.write = lw35ioc_chardev_write,
|
||||
.release = lw35ioc_chardev_release,
|
||||
.unlocked_ioctl = lw35ioc_chardev_ioctl,
|
||||
.poll = poll,
|
||||
};
|
||||
|
||||
|
||||
static int lw35ioc_cdev_init(struct serdev_device *serdev)
|
||||
{
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
priv->chardev.open_count = 0;
|
||||
|
||||
// Try to dynamically allocate a major number for the device
|
||||
priv->chardev.major_number = register_chrdev(0, DEVICE_NAME, &fops);
|
||||
if (priv->chardev.major_number < 0) {
|
||||
dev_err(&serdev->dev, "Failed to register a major number\n");
|
||||
return priv->chardev.major_number;
|
||||
}
|
||||
dev_info(&serdev->dev, "Registered correctly with major number %d\n", priv->chardev.major_number);
|
||||
|
||||
// Register the device class
|
||||
priv->chardev.class = class_create(THIS_MODULE, CLASS_NAME);
|
||||
if (IS_ERR(priv->chardev.class)) {
|
||||
unregister_chrdev(priv->chardev.major_number, DEVICE_NAME);
|
||||
dev_err(&serdev->dev, "Failed to register device class\n");
|
||||
return PTR_ERR(priv->chardev.class);
|
||||
}
|
||||
dev_info(&serdev->dev, "Device class registered correctly\n");
|
||||
|
||||
// Register the device driver
|
||||
priv->chardev.device = device_create(priv->chardev.class, NULL, MKDEV(priv->chardev.major_number, 0), NULL, DEVICE_NAME);
|
||||
if (IS_ERR(priv->chardev.device)) {
|
||||
class_destroy(priv->chardev.class);
|
||||
unregister_chrdev(priv->chardev.major_number, DEVICE_NAME);
|
||||
dev_err(&serdev->dev, "Failed to create the device\n");
|
||||
return PTR_ERR(priv->chardev.device);
|
||||
}
|
||||
|
||||
dev_info(&serdev->dev, "Device class created correctly\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lw35ioc_probe(struct serdev_device *serdev)
|
||||
{
|
||||
struct lw35ioc_priv *priv = NULL;
|
||||
int ret = 0;
|
||||
int i;
|
||||
u32 speed = 19200;
|
||||
struct input_dev *input_dev;
|
||||
|
||||
printk(KERN_INFO "lw35ioc: probe\n");
|
||||
|
||||
if (static_serdev) {
|
||||
printk(KERN_ERR "lw35ioc: Can only be loaded once.\n");
|
||||
goto fail_multicheck;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
priv = devm_kzalloc(&serdev->dev,
|
||||
sizeof(struct lw35ioc_priv),
|
||||
GFP_KERNEL);
|
||||
if (!priv) {
|
||||
printk(KERN_ERR "lw35ioc: Not enough memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->state = ACTIVE; // TODO: This should be passive
|
||||
priv->uart_buf_rx_rd = priv->uart_buf_rx;
|
||||
priv->uart_buf_rx_wr = priv->uart_buf_rx;
|
||||
|
||||
priv->pbuf_tail = 0;
|
||||
priv->pbuf_head = 0;
|
||||
|
||||
priv->printer_status.buffer_free = 0;
|
||||
priv->printer_status.status = 0;
|
||||
|
||||
priv->tx_count = 0;
|
||||
priv->tx_count_resync = 1;
|
||||
|
||||
priv->serdev = serdev;
|
||||
static_serdev = serdev;
|
||||
priv->packet.state = SYNC;
|
||||
serdev_device_set_drvdata(serdev, priv);
|
||||
|
||||
/* Register input device */
|
||||
input_dev = devm_input_allocate_device(&serdev->dev);
|
||||
if (!input_dev) {
|
||||
dev_err(&serdev->dev, "Unable to allocate input device.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
priv->input_dev = input_dev;
|
||||
input_dev->name = "lw35ioc";
|
||||
input_dev->phys = "lw35ioc/input1";
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(EV_REP, input_dev->evbit);
|
||||
for (i = 0; i < ARRAY_SIZE(keycode_map); i++)
|
||||
__set_bit(keycode_map[i], input_dev->keybit);
|
||||
ret = input_register_device(input_dev);
|
||||
if (ret) {
|
||||
dev_err(&serdev->dev, "Unable to register input device.\n");
|
||||
goto fail_input;
|
||||
}
|
||||
|
||||
serdev_device_set_client_ops(serdev, &lw35ioc_serdev_ops);
|
||||
|
||||
ret = serdev_device_open(serdev);
|
||||
if (ret) {
|
||||
dev_err(&serdev->dev, "Unable to open device.\n");
|
||||
goto fail_serdev;
|
||||
}
|
||||
speed = serdev_device_set_baudrate(serdev, speed);
|
||||
dev_info(&serdev->dev, "Using baudrate: %u\n", speed);
|
||||
|
||||
/* Register GPIO */
|
||||
priv->gpio_rst = gpiod_get_index(&serdev->dev,
|
||||
"rst",
|
||||
0,
|
||||
GPIOD_OUT_HIGH);
|
||||
|
||||
/* Register character device */
|
||||
ret = lw35ioc_cdev_init(serdev);
|
||||
if (ret) {
|
||||
dev_err(&serdev->dev, "Unable to initialize character device.\n");
|
||||
goto fail_gpio;
|
||||
}
|
||||
|
||||
if (IS_ERR(priv->gpio_rst)) {
|
||||
dev_err(&serdev->dev, "Unable to get reset GPIO.\n");
|
||||
ret = -ENODEV; /* TODO */
|
||||
goto fail_gpio;
|
||||
}
|
||||
|
||||
lw35ioc_reset_ioc_hw(serdev);
|
||||
|
||||
dev_info(&serdev->dev, "Loaded driver.\n");
|
||||
|
||||
return 0;
|
||||
fail_gpio:
|
||||
fail_serdev:
|
||||
input_unregister_device(input_dev);
|
||||
fail_input:
|
||||
devm_kfree(&serdev->dev, input_dev);
|
||||
fail_multicheck:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lw35ioc_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev);
|
||||
|
||||
dev_info(&serdev->dev, "remove\n");
|
||||
dev_info(&serdev->dev, " cdev class: %p\n", priv->chardev.class);
|
||||
|
||||
device_destroy(priv->chardev.class, MKDEV(priv->chardev.major_number, 0));
|
||||
dev_info(&serdev->dev, "unreg\n");
|
||||
class_unregister(priv->chardev.class);
|
||||
dev_info(&serdev->dev, "destroy: SKIP\n");
|
||||
//class_destroy(priv->chardev.class);
|
||||
dev_info(&serdev->dev, "unreg-dev\n");
|
||||
unregister_chrdev(priv->chardev.major_number, DEVICE_NAME);
|
||||
|
||||
dev_info(&serdev->dev, " gpio rst: %p\n", priv->gpio_rst);
|
||||
dev_info(&serdev->dev, " serdev: %p\n", priv->serdev);
|
||||
dev_info(&serdev->dev, " input dev: %p\n", priv->input_dev);
|
||||
lw35ioc_set_hw_reset(serdev, 1);
|
||||
usleep_range(90000, 100000); // Make sure the reset actually happens
|
||||
gpiod_put(priv->gpio_rst);
|
||||
serdev_device_close(priv->serdev);
|
||||
input_unregister_device(priv->input_dev);
|
||||
|
||||
dev_info(&serdev->dev, "done.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static struct serdev_device_driver lw35ioc_driver = {
|
||||
.probe = lw35ioc_probe,
|
||||
.remove = lw35ioc_remove,
|
||||
.driver = {
|
||||
.name = "lw35ioc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(lw35ioc_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
module_serdev_device_driver(lw35ioc_driver);
|
@ -6,4 +6,4 @@ CONFIG -= qt
|
||||
INCLUDEPATH += /home/markus/projects/arm-linux/current/include
|
||||
|
||||
SOURCES += \
|
||||
lw35-ioc.c
|
||||
lw35ioc.c
|
5
ioc/lw35-tool/CMakeLists.txt
Normal file
5
ioc/lw35-tool/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(lw35-tool LANGUAGES C)
|
||||
|
||||
add_executable(lw35-tool main.c)
|
78
ioc/lw35-tool/main.c
Normal file
78
ioc/lw35-tool/main.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stropts.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define IOCTL_SET_MODE 42
|
||||
enum lw35ioc_state {PASSIVE = 0, INIT, PROG_KBD, PROG_PRI, BYPASS, ACTIVE, STATE_COUNT};
|
||||
|
||||
int f;
|
||||
|
||||
static void help(int argc, char *argv[])
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s <command>\n\n"
|
||||
" command: set-mode <mode>\n"
|
||||
" mode: passive, active, rfu-kbd, rfu-pri, bypass\n",
|
||||
argv[0]);
|
||||
}
|
||||
|
||||
static int set_mode(int argc, char *argv[])
|
||||
{
|
||||
int mode = -1;
|
||||
|
||||
if (argc < 3) {
|
||||
help(argc, argv);
|
||||
return 10;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[2], "passive"))
|
||||
mode = PASSIVE;
|
||||
else if (!strcmp(argv[2], "rfu-kbd"))
|
||||
mode = PROG_KBD;
|
||||
else if (!strcmp(argv[2], "rfu-pri"))
|
||||
mode = PROG_PRI;
|
||||
else if (!strcmp(argv[2], "bypass"))
|
||||
mode = BYPASS;
|
||||
else if (!strcmp(argv[2], "active"))
|
||||
mode = ACTIVE;
|
||||
else if (!strcmp(argv[2], "init"))
|
||||
mode = INIT;
|
||||
|
||||
if (mode == -1) {
|
||||
fprintf(stderr, "Error: Invalid mode.\n");
|
||||
return 10;
|
||||
}
|
||||
|
||||
ioctl(f, IOCTL_SET_MODE, mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc < 2) {
|
||||
help(argc, argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = open("/dev/lw35", O_RDWR);
|
||||
if (f == -1) {
|
||||
fprintf(stderr, "Error opening lw35ioc device.\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "set-mode")) {
|
||||
ret = set_mode(argc, argv);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown command.\n");
|
||||
ret = 2;
|
||||
}
|
||||
|
||||
close(f);
|
||||
|
||||
return ret;
|
||||
}
|
8
keyboard/avr-bootloader/.gitignore
vendored
Normal file
8
keyboard/avr-bootloader/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.srec
|
||||
*.s
|
||||
*.o
|
||||
*.map
|
||||
*.lst
|
||||
*.hex
|
||||
*.elf
|
||||
*.bin
|
88
keyboard/avr-bootloader/Makefile
Normal file
88
keyboard/avr-bootloader/Makefile
Normal file
@ -0,0 +1,88 @@
|
||||
# Makefile for ATmegaBOOT
|
||||
# E.Lins, 2004-10-14
|
||||
|
||||
# program name should not be changed...
|
||||
PROGRAM = main
|
||||
|
||||
PRODUCT=atmega8
|
||||
|
||||
# enter the parameters for the UISP isp tool
|
||||
ISPPARAMS = -dprog=stk500 -dserial=$(SERIAL) -dspeed=115200
|
||||
|
||||
|
||||
#DIRAVR = /usr/local/avr
|
||||
DIRAVRBIN = $(DIRAVR)/bin
|
||||
DIRAVRUTILS = $(DIRAVR)/utils/bin
|
||||
DIRINC = $(DIRAVR)/include
|
||||
DIRLIB = $(DIRAVR)/avr/lib
|
||||
|
||||
|
||||
MCU_TARGET = atmega8
|
||||
LDSECTION = --section-start=.text=0x1c00
|
||||
FUSE_L = 0xdf
|
||||
FUSE_H = 0xca
|
||||
ISPFUSES = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --wr_fuse_l=$(FUSE_L) --wr_fuse_h=$(FUSE_H)
|
||||
ISPFLASH = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --erase --upload if=$(PROGRAM).hex -v
|
||||
|
||||
|
||||
OBJ = $(PROGRAM).o
|
||||
OPTIMIZE = -Os -funsigned-char -funsigned-bitfields -fno-inline-small-functions
|
||||
|
||||
DEFS = -DF_CPU=8000000 -DBAUD_RATE=19200
|
||||
LIBS =
|
||||
|
||||
CC = $(DIRAVRBIN)/avr-gcc
|
||||
|
||||
|
||||
# Override is only needed by avr-lib build system.
|
||||
|
||||
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -D$(PRODUCT) $(DEFS) -I$(DIRINC)
|
||||
override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)
|
||||
|
||||
OBJCOPY = $(DIRAVRBIN)/avr-objcopy
|
||||
OBJDUMP = $(DIRAVRBIN)/avr-objdump
|
||||
SIZE = $(DIRAVRBIN)/avr-size
|
||||
|
||||
all: $(PROGRAM).elf lst text asm size
|
||||
|
||||
isp: $(PROGRAM).hex
|
||||
$(ISPFUSES)
|
||||
$(ISPFLASH)
|
||||
|
||||
$(PROGRAM).elf: $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.s
|
||||
rm -rf *.o *.elf
|
||||
rm -rf *.lst *.map
|
||||
|
||||
asm: $(PROGRAM).s
|
||||
|
||||
%.s: %.c
|
||||
$(CC) -S $(CFLAGS) -g1 $^
|
||||
|
||||
lst: $(PROGRAM).lst
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
size: $(PROGRAM).hex
|
||||
$(SIZE) $^
|
||||
|
||||
# Rules for building the .text rom images
|
||||
|
||||
text: hex bin srec
|
||||
|
||||
hex: $(PROGRAM).hex
|
||||
bin: $(PROGRAM).bin
|
||||
srec: $(PROGRAM).srec
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||
|
||||
%.srec: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O srec $< $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O binary $< $@
|
1
keyboard/avr-bootloader/main.c
Symbolic link
1
keyboard/avr-bootloader/main.c
Symbolic link
@ -0,0 +1 @@
|
||||
../../ioc/avr-bootloader/main.c
|
@ -1,8 +1,9 @@
|
||||
MCU=atmega8
|
||||
PDEV=/dev/ttyUSB1
|
||||
CFLAGS=-g -Wall -mcall-prologues -mmcu=$(MCU) -Os -DF_CPU=8000000
|
||||
LDFLAGS=-Wl,-gc-sections -Wl,-relax
|
||||
CC=avr-gcc
|
||||
TARGET=main
|
||||
TARGET=fw_keyboard
|
||||
OBJECT_FILES=main.o
|
||||
|
||||
all: $(TARGET).hex
|
||||
@ -16,9 +17,12 @@ clean:
|
||||
%.obj: $(OBJECT_FILES)
|
||||
$(CC) $(CFLAGS) $(OBJECT_FILES) $(LDFLAGS) -o $@
|
||||
|
||||
rfu: $(TARGET).hex
|
||||
scp $< markus@opi:/home/markus/projects/lw35/deploy/
|
||||
ssh root@opi 'lw35-tool set-mode rfu-kbd; avrdude -p atmega8 -P /dev/lw35 -c arduino -b 19200 -U flash:w:/home/markus/projects/lw35/deploy/$<'
|
||||
|
||||
program: $(TARGET).hex
|
||||
avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex
|
||||
#avrdude -p $(MCU) -P /dev/ttyUSB1 -c arduino -b 57600 -U flash:w:$(TARGET).hex
|
||||
avrdude -p $(MCU) -P $(PDEV) -c arduino -b 19200 -U flash:w:$(TARGET).hex
|
||||
|
||||
fuse:
|
||||
avrdude -p m8 -c usbasp -U lfuse:w:0xe4:m -U hfuse:w:0xd9:m
|
||||
|
@ -7,3 +7,5 @@ INCLUDEPATH += /usr/avr/include
|
||||
|
||||
SOURCES += \
|
||||
main.c
|
||||
|
||||
DEFINES += __AVR_ATmega8__
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define MATRIX_X(t) t##B
|
||||
#define MATRIX_Y1(t) t##C
|
||||
@ -11,8 +12,9 @@
|
||||
|
||||
#define DELAY_ROW_SWITCH() _delay_ms(1) //_delay_us(1)
|
||||
|
||||
#define BAUDRATE 9600
|
||||
#define UBRR 51 // (F_CPU / BAUDRATE) / 32
|
||||
#define BAUDRATE 19200
|
||||
|
||||
#define PRINTER_PACKET_SIZE 6
|
||||
|
||||
/* Keycode from include/linux/input.h */
|
||||
#define KEY_RESERVED 0
|
||||
@ -147,30 +149,46 @@
|
||||
#define KEY_COMPOSE 127
|
||||
|
||||
#define SKEY_FN 255
|
||||
#define KEYCODE_FN 127
|
||||
// #define KEYCODE_FN 127
|
||||
|
||||
/*
|
||||
* Special keys:
|
||||
* * Control : Code
|
||||
* * Alt : Del
|
||||
* * FN : Delword
|
||||
* * Del : Inhalt
|
||||
* * ` : SM
|
||||
* * Escape : Storno
|
||||
* * Print : Menu
|
||||
* * Pause : GS End
|
||||
*
|
||||
* FN Keymap:
|
||||
* * F-Keys : Number keys for F1-F10, and ? and ` for F11-F12
|
||||
* * Home / End / PGUP / PGDN : Arrow keys
|
||||
* * Sys rq : Print
|
||||
*/
|
||||
static uint8_t keycode_translation_matrix[2][9][8] = {
|
||||
{ /* Standard keymap */
|
||||
{KEY_4, KEY_3, 3, 4, 5, 6, 7, 8},
|
||||
{KEY_5, KEY_6, 13, 14, 15, 16, 17, 18},
|
||||
{KEY_8, KEY_7, 23, 24, 25, 26, 27, 28},
|
||||
{KEY_1, KEY_2, 33, 34, 35, 36, 37, 38},
|
||||
{KEY_9, 42, 43, 44, 45, 46, 47, 48},
|
||||
{51, KEY_0, 53, 54, 55, 56, 57, 58},
|
||||
{61, 62, 63, 64, 65, 66, 67, 68},
|
||||
{71, 72, 73, 74, 75, SKEY_FN, 77, 78},
|
||||
{81, 82, 83, 84, 85, 86, 87, 88}
|
||||
{KEY_5, KEY_6, KEY_R, KEY_T, KEY_C, KEY_F, KEY_UP, 0},
|
||||
{KEY_8, KEY_7, KEY_Y, KEY_H, KEY_G, KEY_V, KEY_PAUSE, 0},
|
||||
{KEY_1, KEY_2, KEY_Q, KEY_Z, KEY_A, KEY_S, KEY_CAPSLOCK, 0},
|
||||
{KEY_9, KEY_J, KEY_I, KEY_U, KEY_B, KEY_N, KEY_RIGHT, 0},
|
||||
{KEY_MINUS, KEY_0, KEY_P, KEY_O, KEY_M, KEY_COMMA, KEY_SYSRQ, 0},
|
||||
{KEY_DELETE, KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_LEFTBRACE, KEY_LEFT, KEY_DOWN, 0, KEY_LEFTCTRL},
|
||||
{KEY_4, KEY_3, KEY_W, KEY_E, KEY_D, KEY_X, KEY_TAB, 0},
|
||||
{KEY_GRAVE, KEY_ESC, KEY_ENTER, KEY_BACKSPACE, KEY_LEFTALT, SKEY_FN, KEY_LEFTSHIFT, KEY_SPACE},
|
||||
{KEY_EQUAL, KEY_L, KEY_BACKSLASH, KEY_K, KEY_DOT, KEY_SLASH, 0, KEY_APOSTROPHE}
|
||||
},
|
||||
{ /* FN keymap */
|
||||
{ 1, 2, 3, 4, 5, 6, 7, 8},
|
||||
{11, 12, 13, 14, 15, 16, 17, 18},
|
||||
{21, 22, 23, 24, 25, 26, 27, 28},
|
||||
{31, 32, 33, 34, 35, 36, 37, 38},
|
||||
{41, 42, 43, 44, 45, 46, 47, 48},
|
||||
{51, 52, 53, 54, 55, 56, 57, 58},
|
||||
{61, 62, 63, 64, 65, 66, 67, 68},
|
||||
{71, 72, 73, 74, 75, SKEY_FN, 77, 78},
|
||||
{81, 82, 83, 84, 85, 86, 87, 88}
|
||||
{KEY_F5, KEY_F6, KEY_R, KEY_T, KEY_C, KEY_F, KEY_PAGEUP, 0},
|
||||
{KEY_F8, KEY_F7, KEY_Z, KEY_H, KEY_G, KEY_V, KEY_PAUSE, 0},
|
||||
{KEY_F1, KEY_F2, KEY_Q, KEY_102ND, KEY_A, KEY_S, KEY_CAPSLOCK, 0},
|
||||
{KEY_F9, KEY_J, KEY_I, KEY_U, KEY_B, KEY_N, KEY_END, 0},
|
||||
{KEY_F11, KEY_F10, KEY_P, KEY_O, KEY_M, KEY_COMMA, KEY_SYSRQ, 0},
|
||||
{KEY_DELETE, KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_LEFTBRACE, KEY_HOME, KEY_PAGEDOWN, 0, KEY_LEFTCTRL},
|
||||
{KEY_F4, KEY_F3, KEY_W, KEY_E, KEY_D, KEY_X, KEY_TAB, 0},
|
||||
{KEY_GRAVE, KEY_ESC, KEY_ENTER, KEY_BACKSPACE, KEY_LEFTALT, SKEY_FN, KEY_LEFTSHIFT, KEY_SPACE},
|
||||
{KEY_F12, KEY_L, KEY_BACKSLASH, KEY_K, KEY_DOT, KEY_SLASH, 0, KEY_APOSTROPHE}
|
||||
}
|
||||
};
|
||||
|
||||
@ -178,26 +196,81 @@ uint8_t matrix_state_last_vector[9] = {0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF};
|
||||
|
||||
|
||||
uint8_t fn_active = 0;
|
||||
|
||||
/* UART forwarding */
|
||||
#define RING_BUFFER_SIZE 256 // Important: must be 256 atm, when changed, you need to change code handling print_buffer_*.
|
||||
volatile char ring_buffer[RING_BUFFER_SIZE];
|
||||
volatile uint8_t ring_buffer_wr = 0;
|
||||
volatile uint8_t ring_buffer_rd = 0;
|
||||
#define UART_BYTE_READY (UCSRA & (1 << RXC))
|
||||
|
||||
void uart_putc(char c)
|
||||
{
|
||||
while (!(UCSRA & (1 << UDRE)));
|
||||
UDR = c;
|
||||
}
|
||||
|
||||
ISR(USART_RXC_vect)
|
||||
{
|
||||
if (UCSRA & (1 << RXC)) {
|
||||
ring_buffer[ring_buffer_wr] = UDR;
|
||||
ring_buffer_wr++; // WARNING: No overflow protection
|
||||
// Will auto wrap at 256; print_buffer_wr = print_buffer_wr % PRINT_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_forward_packets()
|
||||
{
|
||||
uint8_t size;
|
||||
uint8_t i;
|
||||
|
||||
if (ring_buffer_wr > ring_buffer_rd)
|
||||
size = ring_buffer_wr - ring_buffer_rd;
|
||||
else
|
||||
size = ring_buffer_rd - ring_buffer_wr;
|
||||
|
||||
if (size >= PRINTER_PACKET_SIZE) {
|
||||
/* check sync */
|
||||
if (ring_buffer[ring_buffer_rd] != ((char)0xFF)) {
|
||||
ring_buffer_rd++; /* Drop wrong sync header */
|
||||
return;
|
||||
}
|
||||
if (ring_buffer[ring_buffer_rd + 1] != ((char)0xAA)) {
|
||||
ring_buffer_rd += 1; /* Drop wrong app header */
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < PRINTER_PACKET_SIZE; ++i) {
|
||||
uart_putc(ring_buffer[ring_buffer_rd]); // Will auto wrap at 256
|
||||
ring_buffer_rd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_key_event(uint8_t col, uint8_t row, uint8_t state)
|
||||
{
|
||||
char c;
|
||||
uint8_t keycode;
|
||||
int event = 0;
|
||||
|
||||
keycode = keycode_translation_matrix[fn_active][col][row];
|
||||
|
||||
if (keycode == SKEY_FN) {
|
||||
fn_active = state;
|
||||
#ifdef KEYCODE_FN
|
||||
while (!(UCSRA & (1 << UDRE)));
|
||||
UDR = KEYCODE_FN | (state << 7);
|
||||
c = KEYCODE_FN | (state << 7);
|
||||
event = 1;
|
||||
#endif
|
||||
} else {
|
||||
c = keycode | (state << 7);
|
||||
while (!(UCSRA & (1 << UDRE)));
|
||||
UDR = c;
|
||||
event = 1;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
uart_putc(0xFF);
|
||||
uart_putc(0x55);
|
||||
uart_putc(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,16 +315,23 @@ int main()
|
||||
MATRIX_Y2(DDR) &= ~MASK_Y2; /* Disable rows */
|
||||
MATRIX_Y1(PORT) &= ~MASK_Y1; /* Pull row low when selected */
|
||||
MATRIX_Y2(PORT) &= ~MASK_Y2; /* Pull row low when selected */
|
||||
UCSRB = (1 << TXEN);
|
||||
UBRRH = (UBRR >> 8) & 0xFF;
|
||||
UBRRL = UBRR & 0xFF;
|
||||
|
||||
/* Set up UART */
|
||||
UCSRA = 0;
|
||||
UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
|
||||
UCSRC = 0;
|
||||
UBRRH = ((((F_CPU / BAUDRATE) / 16) - 1) >> 8);
|
||||
UBRRL = (((F_CPU / BAUDRATE) / 16) - 1);
|
||||
|
||||
fn_active = 0;
|
||||
|
||||
sei();
|
||||
|
||||
/* Continuously scan matrix */
|
||||
while (1) {
|
||||
for (col = 0; col < 9; ++col) {
|
||||
matrix_scan_col(col);
|
||||
}
|
||||
uart_forward_packets();
|
||||
}
|
||||
}
|
||||
|
88
printer/avr-bootloader/Makefile
Normal file
88
printer/avr-bootloader/Makefile
Normal file
@ -0,0 +1,88 @@
|
||||
# Makefile for ATmegaBOOT
|
||||
# E.Lins, 2004-10-14
|
||||
|
||||
# program name should not be changed...
|
||||
PROGRAM = main
|
||||
|
||||
PRODUCT=atmega8
|
||||
|
||||
# enter the parameters for the UISP isp tool
|
||||
ISPPARAMS = -dprog=stk500 -dserial=$(SERIAL) -dspeed=115200
|
||||
|
||||
|
||||
#DIRAVR = /usr/local/avr
|
||||
DIRAVRBIN = $(DIRAVR)/bin
|
||||
DIRAVRUTILS = $(DIRAVR)/utils/bin
|
||||
DIRINC = $(DIRAVR)/include
|
||||
DIRLIB = $(DIRAVR)/avr/lib
|
||||
|
||||
|
||||
MCU_TARGET = atmega8
|
||||
LDSECTION = --section-start=.text=0x1c00
|
||||
FUSE_L = 0xdf
|
||||
FUSE_H = 0xca
|
||||
ISPFUSES = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --wr_fuse_l=$(FUSE_L) --wr_fuse_h=$(FUSE_H)
|
||||
ISPFLASH = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --erase --upload if=$(PROGRAM).hex -v
|
||||
|
||||
|
||||
OBJ = $(PROGRAM).o
|
||||
OPTIMIZE = -Os -funsigned-char -funsigned-bitfields -fno-inline-small-functions
|
||||
|
||||
DEFS = -DF_CPU=16000000 -DBAUD_RATE=19200
|
||||
LIBS =
|
||||
|
||||
CC = $(DIRAVRBIN)/avr-gcc
|
||||
|
||||
|
||||
# Override is only needed by avr-lib build system.
|
||||
|
||||
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -D$(PRODUCT) $(DEFS) -I$(DIRINC)
|
||||
override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)
|
||||
|
||||
OBJCOPY = $(DIRAVRBIN)/avr-objcopy
|
||||
OBJDUMP = $(DIRAVRBIN)/avr-objdump
|
||||
SIZE = $(DIRAVRBIN)/avr-size
|
||||
|
||||
all: $(PROGRAM).elf lst text asm size
|
||||
|
||||
isp: $(PROGRAM).hex
|
||||
$(ISPFUSES)
|
||||
$(ISPFLASH)
|
||||
|
||||
$(PROGRAM).elf: $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.s
|
||||
rm -rf *.o *.elf
|
||||
rm -rf *.lst *.map
|
||||
|
||||
asm: $(PROGRAM).s
|
||||
|
||||
%.s: %.c
|
||||
$(CC) -S $(CFLAGS) -g1 $^
|
||||
|
||||
lst: $(PROGRAM).lst
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
size: $(PROGRAM).hex
|
||||
$(SIZE) $^
|
||||
|
||||
# Rules for building the .text rom images
|
||||
|
||||
text: hex bin srec
|
||||
|
||||
hex: $(PROGRAM).hex
|
||||
bin: $(PROGRAM).bin
|
||||
srec: $(PROGRAM).srec
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||
|
||||
%.srec: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O srec $< $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O binary $< $@
|
1
printer/avr-bootloader/main.c
Symbolic link
1
printer/avr-bootloader/main.c
Symbolic link
@ -0,0 +1 @@
|
||||
../../ioc/avr-bootloader/main.c
|
@ -1,8 +1,9 @@
|
||||
MCU=atmega8
|
||||
CFLAGS=-g -Wall -mcall-prologues -mmcu=$(MCU) -Os -DF_CPU=8000000
|
||||
PDEV=/dev/ttyUSB0
|
||||
CFLAGS=-g -Wall -mcall-prologues -mmcu=$(MCU) -O2 -DF_CPU=16000000
|
||||
LDFLAGS=-Wl,-gc-sections -Wl,-relax
|
||||
CC=avr-gcc
|
||||
TARGET=main
|
||||
TARGET=fw_printer
|
||||
OBJECT_FILES=main.o
|
||||
|
||||
all: $(TARGET).hex
|
||||
@ -15,10 +16,14 @@ clean:
|
||||
|
||||
%.obj: $(OBJECT_FILES)
|
||||
$(CC) $(CFLAGS) $(OBJECT_FILES) $(LDFLAGS) -o $@
|
||||
avr-size -C --mcu=atmega8 main.obj
|
||||
|
||||
rfu: $(TARGET).hex
|
||||
scp $< markus@opi:/home/markus/projects/lw35/deploy/
|
||||
ssh root@opi 'lw35-tool set-mode rfu-pri; avrdude -p atmega8 -P /dev/lw35 -c arduino -b 19200 -U flash:w:/home/markus/projects/lw35/deploy/$<'
|
||||
|
||||
program: $(TARGET).obj
|
||||
avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex
|
||||
#avrdude -p $(MCU) -P /dev/ttyUSB1 -c arduino -b 57600 -U flash:w:$(TARGET).hex
|
||||
avrdude -p $(MCU) -P $(PDEV) -c arduino -b 19200 -U flash:w:$(TARGET).hex
|
||||
|
||||
fuse:
|
||||
avrdude -p m8 -c usbasp -U lfuse:w:0xe4:m -U hfuse:w:0xd9:m
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -7,3 +7,5 @@ INCLUDEPATH += /usr/avr/include
|
||||
|
||||
SOURCES += \
|
||||
main.c
|
||||
|
||||
DEFINES += __AVR_ATmega8__
|
||||
|
29
printer/scripts/convert.sh
Executable file
29
printer/scripts/convert.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
source shared.sh
|
||||
|
||||
if [ "$1" == "" ]; then
|
||||
echo "usage: $0 <file>"
|
||||
exit;
|
||||
fi
|
||||
|
||||
mkdir -p out
|
||||
rm out/*
|
||||
|
||||
echo ".ll $LL" > out/header
|
||||
cat "$1" | sed 's/\./\\\&./g' > out/text
|
||||
echo ".sp 0" > out/footer
|
||||
cat out/header out/text out/footer | nroff -Tascii > out/render
|
||||
|
||||
cline=0
|
||||
page=1
|
||||
while IFS="" read -r p || [ -n "$p" ]
|
||||
do
|
||||
cline=$(($cline + 1))
|
||||
if [ $cline -eq $PL ]; then
|
||||
page=$(($page + 1))
|
||||
cline=0
|
||||
fi
|
||||
printf '%s\n' "$p" >> "out/out$page.txt"
|
||||
done < out/render
|
||||
|
||||
echo "Created $page pages."
|
39
printer/scripts/print.sh
Executable file
39
printer/scripts/print.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
source shared.sh
|
||||
|
||||
ML=$(( (110-$LL) / 2))
|
||||
MT=$(( (64 - $PL) / 2 ))
|
||||
echo "Margin left: $ML"
|
||||
echo "Margin top : $MT"
|
||||
echo "Page width : $LL"
|
||||
echo "Page length: $PL"
|
||||
|
||||
if [ $MT -gt 127 ]; then
|
||||
echo "Margin top > 127 not supported because I am lazy. Is $MT."
|
||||
exit
|
||||
fi
|
||||
MT=$(( $MT + 128 )) # Set "move by n line bit"
|
||||
#exit
|
||||
echo -ne $(printf "\\\\x%02x\\\\x%02x" 224 $ML) > /dev/lw35
|
||||
MR=$((ML + $LL + 2)); # Plus 2 because bug in FW in conjunction with manual newlines
|
||||
echo -ne $(printf "\\\\x%02x\\\\x%02x" 225 $MR) > /dev/lw35
|
||||
|
||||
for file in ./out/out*; do
|
||||
foo=""
|
||||
while [ true ]; do
|
||||
echo "Insert a piece of paper and press enter. When you're done, enter y."
|
||||
read foo
|
||||
if [ "$foo" == "y" ]; then
|
||||
break;
|
||||
fi
|
||||
echo -ne "\xE3\x8C" > /dev/lw35 # Draw in until at top of paper
|
||||
echo -ne $(printf "\\\\x%02x\\\\x%02x" 0xE3 $MT) > /dev/lw35 # Move over margin top
|
||||
done
|
||||
echo "Printing part $file..."
|
||||
|
||||
cat $file > /dev/lw35
|
||||
echo "Part done."
|
||||
done
|
||||
|
||||
echo "Done."
|
6
printer/scripts/shared.sh
Executable file
6
printer/scripts/shared.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Limits for A4 vertical
|
||||
LL=80 # Max 90
|
||||
PL=58 # Max 64
|
||||
|
Loading…
Reference in New Issue
Block a user