This commit is contained in:
dfnr2 2022-09-08 02:32:48 +00:00
parent 51022040f1
commit 9a201209fb
302 changed files with 19191 additions and 161461 deletions

4
.buildinfo Normal file
View File

@ -0,0 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: a2eb8b3dc1e4b438d766803263306bf7
tags: 645f666f9bcd5a90fca523b33c5a78b7

Binary file not shown.

BIN
.doctrees/index.doctree Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

23
.gitignore vendored
View File

@ -1,23 +0,0 @@
#MacOS related
.DS_Store
#KiCAD related
*.bak
*.bck
*.sch-bak
*.dcm
*-cache.lib
*.kicad_pcb-bak
fp-lib-table
fp-info-cache
*-rescue.lib
#C related
*.o
*.elf
*.map
#misc
\*scratch\*
/.gitignore~
*.hex

0
.nojekyll Normal file
View File

View File

@ -1,29 +0,0 @@
## Unified Retrocomputer Keyboard Project
This project aims to provide a unified collection of keyboards and encoders for vintage computers, with modular design to reuse as many elements as possible across the designs.
Home computers of the 1970's typically either polled a switch matrix, or interfaced to a parallel ASCII keyboard via a parallel port.
The keyboard allows use of Cherry MX keys, or Futaba MD-4PCS (aka George Risk KBM-01-01) keys.
The keyboard is designed using KiCad in order to be the most useful for anybody wishing to modify the keyboard for more specific uses, or to add to the project.
### Capabilities so far:
- Replacement keyboard for OSI computers
- Replacement keyboard for Apple II/II+ computers
- Replacement keyboard for the Sol-20 computer
- Generic ADM-3A/Teletype style keyboard
- Apple I keyboard (multiple styles)
### Coming soon:
- Replace encoder board on Apple II/II+ keyboards
- Convert an OSI 542 keyboard into a generic ASCII keyboard
- Replica for Knight keyboard
### This keyboard project so far consists of:
- A classic retro-style ASCII keyboard, modeled after the ADM-3A keyboard, which
can be also be populated to fit perfectly in an Apple II/II+ case (with corresponding Apple II keymaps), or an OSI
case (with OSI adapter).
- A Sol-20 compatible keyboard.
- Keyscan/decoder interface modules that can output parallel ASCII, and can be adapted for other protocols.
- An OSI interface module, to connect the classic keyboard to an OSI computer.

View File

@ -0,0 +1,447 @@
:1000000085C20000A3C20000A1C200009FC2000080
:100010009DC200009BC2000099C2000097C2000070
:1000200095C2000093C2000091C200008FC2000080
:100030008DC200008BC2000089C2000087C2000090
:1000400085C2000083C2000081C200007FC20000A0
:100050007DC20000C3C3000079C2000077C2000067
:1000600075C2000073C2000071C200006FC20000C0
:100070006DC200006BC2000069C2000067C20000D0
:1000800065C2000063C2000061C200005FC20000E0
:100090005DC200005BC2000059C2000057C20000F0
:1000A00055C2000053C2000051C200004FC2000000
:1000B0004DC200004BC2000049C2000047C2000010
:1000C00045C2000043C2000041C200003FC2000020
:1000D0003DC200003BC2000039C2000037C2000030
:1000E00035C20000A0A1A1A01B09A51CA010A0A0C2
:1000F000201A0111B12C0D0E02160318A00B0A08CC
:1001000007060413A009151914120517A0A6A40DBB
:100110000A0F0CA0A01D1BA0A0C0BFBE00BDBCBB91
:10012000BAB9B8B7A8A9AAAB0000ADACA0A1A1A06C
:100130001B09A55C7F503B2F205A4151A02C4D4EEE
:1001400042564358A04B4A4847464453A049555944
:1001500054524557A0A6A40D0A4F4C2E7E5D5B2D30
:100160003A3039384037363534333231A8A9AAAB62
:100170000000ADACA0A1A1A01B09A57C7F502B3F26
:10018000205A4151B23C4D4E42564358A04B4A482A
:1001900047464453A049555954524557A0A6A40D6B
:1001A0000A4F4C3E7E7D7B3D2A302928602726253C
:1001B00024232221A8A9AAAB0000ADACA0A1A1A034
:1001C0001B09A55C7F703B2F207A6171A02C6D6E9E
:1001D00062766378A06B6A6867666473A0697579F4
:1001E00074726577A0A6A40D0A6F6C2E7E5D5B2DE0
:1001F0003A3039384037363534333231A8A9AAABD2
:100200000000ADACA4A1A1A0A01BA515A010A0A0AA
:10021000201A0111A02C0D0E02160318A00B0A08BB
:1002200007060413A009151914120517A0A0A00DA4
:10023000A60F0CA0A0A0B1A0A0C0BFBE08BDBCBBB3
:10024000BAB9B8B7A8A9AAAB0000ADACA4A1A1A047
:10025000A01BA515A0503B2F205A4151A02C4D4E5C
:1002600042564358A04B4A4847464453A049555923
:1002700054524557A0A0A00DA64F4C2EA0A0A02DD3
:100280003A3039380837363534333231A8A9AAAB79
:100290000000ADACA4A1A1A0A01BA515A0402B3FC0
:1002A000205A4151A03C4D5E42564358A04B4A480B
:1002B00047464453A049555954524557A0A0A00D54
:1002C000A64F4C3EA0A0B23D2A302928082726255B
:1002D00024232221A8A9AAAB0000ADACA4A1A1A00F
:1002E000A01BA515A0502B3F205A4151A03C4D4EBC
:1002F00042564358A04B4A4847464453A049555993
:1003000054524557A0A0A00D404F4C3EA0A0B23D76
:100310002A3029280827262524232221A8A9AAAB88
:100320000000ADACA4A1A1A0A01BA5157F703B2F20
:10033000207A6171A02C6D6E62766378A06B6A681A
:1003400067666473A069757974726577A0A0A00D63
:100350005E6F6C2EA0A0A02D3A30393808373635A4
:1003600034333231A8A9AAAB0000ADACA5A2011369
:10037000040607080A0B0C0B0A7FB1A5A4A11A18E2
:100380000316020E0D0C0E0FA180A0A01B0102038C
:10039000040506070809000D1E1B1C1DB2091117D4
:1003A0000512141915090F10000D0A8CA8A9AAAB83
:1003B0000000ADACB3978120939A8E8B2D372A38ED
:1003C0002F39A0A0343135323633A0A0302E2BA0E7
:1003D000A0A0A0A0A5A24153444647484A4B4C3B8D
:1003E0003A5FA6A5A4A15A584356424E4D3C3E3F03
:1003F000A180A0A01B212223242526272829203DD7
:100400007E5B5C5DB20951574552545955494F5076
:10041000600D0A8CA8A9AAAB0000ADACB3978120EF
:10042000939A8E8B2D372A382F39A0A0343135324C
:100430003633A0A0302E2BA0A0A0A0A0A5A241538F
:10044000444647484A4B4C3B3A7FA6A5A4A15A587C
:100450004356424E4D2C2E2FA180A0A01B3132338B
:10046000343536373839302D5E5B5C5DB209515713
:100470004552545955494F50400D0A8CA8A9AAAB72
:100480000000ADACB3978120939A8E8B2D372A381C
:100490002F39A0A0343135323633A0A0302E2BA016
:1004A000A0A0A0A0A5A26173646667686A6B6C3B9C
:1004B0003A7FA6A5A4A17A786376626E6D2C2E2F62
:1004C000A180A0A01B313233343536373839302D76
:1004D0005E5B5C5DB20971776572747975696F7086
:1004E000400D0A8CA8A9AAAB0000ADACB39781203F
:1004F000939A8E8B2D372A382F39A0A0343135327C
:100500003633A0A0302E2BA0A0A0A0A011241FBE87
:10051000CFEFD1E2DEBFCDBF00E00CBF13E0A0E023
:10052000B2E0E4EAFAE100E00BBF02C007900D92EE
:10053000A033B107D9F724E0A0E3B3E001C01D92D6
:10054000A43CB207E1F7A6D70C94220D59CD805AEE
:10055000813208F00895E82FF0E08827EC5DF24F33
:100560008F4FBAC784E0A6C28DE0A4C28CE0A2C2BD
:100570008BE0A0C28AE09EC289E09CC288E09AC259
:1005800087E098C286E096C285E094C286E0F2C514
:1005900085E0F0C584E0EEC583E0ECC582E0EAC505
:1005A00081E0E8C589E0E6C588E0E4C587E0E2C50A
:1005B0007BC12AC5E2C3A1C360C31FC33BC54BC4F3
:1005C0003EC432C429C422C4815A8D3008F0089533
:1005D000E82FF0E08827EB5BF24F8F4F7DC73FC4D9
:1005E00043C440C5EAC229C368C3A7C3F9C45FC1F5
:1005F000CF93C82F8A3041F06C2F8091320315D2EF
:100600008C2F90E0CF9108956DE0809132030DD250
:10061000F3CFCF93809132032AD2C82F803A41F092
:10062000809130039091310354D18C2FCF91089554
:1006300080913303CF911BC290E09093310380935C
:10064000300308955F926F927F928F929F92AF9244
:10065000BF92CF92DF92EF92FF920F931F93CF93AF
:10066000DF9381E036D25C0183E024D200E03AE0FF
:10067000732E88248394912C50EA652E71D208172A
:1006800008F06BC0802FF5011995D82F802F90E0CE
:100690009C012B543C4F6901F90110811D27C0E0DA
:1006A000880F991F880F991F880F991F9C012B5C39
:1006B0003C4F790105C0811115C01695D695CF5FC5
:1006C0005AD2C81708F044C08D2F817010FFF3CFA5
:1006D000F701EC0FF11D90812FEF290F9130F9F008
:1006E0002083EBCFC4D3482F6C2F802F66D39091FB
:1006F00034039813E2CFC3D48823F9F25090340323
:10070000F0EAF51510F1652D809133038ED18091BB
:100710003403581691F25092340359D4CECF7082DC
:10072000F601908194010C2E01C0220F0A94EAF781
:10073000882319F1922B90839AD3482F6C2F802F06
:100740003CD3582EF0EAF817F0F6852D00DFB5CF30
:100750000F5F06D2081708F495CFDF91CF911F9154
:100760000F91FF90EF90DF90CF90BF90AF909F9050
:100770008F907F906F905F9008952095292320831C
:1007800076D3482F6C2F802F18D3813A38F490916C
:100790003403981392CF609234038FCF15DF8DCF3F
:1007A00080EA809334030DD103D4F0D180E190E04E
:1007B0000FD18093330380E890E00AD18093320315
:1007C000E5EBF3E080E1DF011D928A95E9F740E86F
:1007D00050E06AE070E085E393E09AC68F9381E091
:1007E0008093C6038F9118958091C6031092C6031B
:1007F0000895882311F05D9808955D9A08958823DF
:1008000011F05E9808955E9A0895882311F05F981C
:1008100008955F9A08950895882319F02D9A259ACE
:1008200008952D98259A0895882319F025982D9AD2
:1008300008952D98259A0895882319F02D9A259AC0
:10084000089525982D980895882319F02E9A269AB0
:1008500008952E98269A0895882319F026982E9A9E
:1008600008952E98269A0895882319F02E9A269A8C
:10087000089526982E980895882319F02F9A279A7C
:1008800008952F98279A0895882319F027982F9A6A
:1008900008952F98279A0895882319F02F9A279A58
:1008A000089527982F9808952C98249A08952C9AA3
:1008B000249A089585E38A95F1F7000008952FEFB3
:1008C00080E792E0215080409040E1F700C00000B6
:1008D00008959C01892B61F090E080E0EFE9FFE052
:1008E0003197F1F700C00000019628173907B1F7DA
:1008F0000895F8941092C60387E0809361001092E7
:10090000C60389EF87BD15BC82E084BD80936E006D
:1009100083E085BD8091C503809302018FEF8093B2
:1009200001011092C5032C98249A559A569A579A09
:1009300081B98093040117B888B978940895282F55
:1009400081E090E0A0E0B0E004C0880F991FAA1FEA
:10095000BB1F2A95D2F780959095A095B09580936E
:10096000050125E12A95F1F70000892F9A2FAB2F79
:10097000BB2782B985E18A95F1F7000086B18095A1
:1009800008959091C5038927809302011C9A85E3FD
:100990008A95F1F700001C9A0895833049F028F4F5
:1009A000813041F0823029F4A0C4843011F434C580
:1009B000CFC42CC45DC4982F81E0953008F080E04E
:1009C00008951092C9031092C8031092C7030895A6
:1009D0009C018091C703843034F54091C803509145
:1009E000C90360E970E0641B750B62177307DCF0E4
:1009F00091E0980F9093C70397E08902F0011124CA
:100A0000E653FC4F33832283BA016A517C4F7183D2
:100A10006083148215821682420F531F5093C903BC
:100A20004093C80308958FEF089587FD1EC09091ED
:100A3000C7038917DCF497E08902F0011124E6531B
:100A4000FC4F2681428153812417150674F484815A
:100A500090E0A081B181A80FB91F6C930196BA01F3
:100A600028D584832F5F268308950895089587FDF0
:100A700004C09091C70389171CF030EA832F0895B2
:100A800097E08902F0011124E653FC4F26812223CE
:100A9000A1F3858190E0A081B181A80FB91F3C919D
:100AA00001966281738105D5858321502683832F2A
:100AB000089508959FEF980F9D3050F4E82FF0E0CF
:100AC000EE0FFF1FEA58FB4F0190F081E02D1994C3
:100AD00008959FEF980F9D3048F4E82FF0E0EE0F57
:100AE000FF1FEA58FB4F80819181089589E595E0C9
:100AF00008959FEF980F9D3040F4E82FF0E0EE0F3F
:100B0000FF1FEA58FB4F608371830895E6E7F4E026
:100B100089E595E08193919324E0E239F207D1F7DA
:100B20008FE994E0909379048093780481EC94E0C9
:100B300090937B0480937A040895643080F441316B
:100B400070F4293060F4E62FF0E0EE0FFF1FEE0F97
:100B5000FF1FED56FB4F80839183428323830895CB
:100B600086D1E82FF0E0EE0FFF1FEE0FFF1FED56CE
:100B7000FB4F828108957BD1E82FF0E0EE0FFF1F3D
:100B8000EE0FFF1FED56FB4F8381089580E013DFCA
:100B9000811101C0089510929204ABDEE3E9F4E004
:100BA0001182108212821382349684E0E33AF807AD
:100BB000B9F70AD3ABDF80E0F0CECF9380919204F7
:100BC000C82FCE7F80FD02C0CF9108958C2FF3DE19
:100BD0008823D1F3C09392048CDEE3E9F4E0118220
:100BE000108212821382349684E0E33AF807B9F750
:100BF000EBD28CDF8C2FCF91D0CECF93809192040B
:100C0000C82FC16080FF02C0CF9108958C2FD3DE22
:100C10008823D1F3C09392046CDEE3E9F4E01182FF
:100C2000108212821382349684E0E33AF807B9F70F
:100C3000CBD26CDF8C2FCF91B0CECF93809192042A
:100C4000C82FCD7F81FD02C0CF9108958C2FB3DED8
:100C50008823D1F3C09392044CDEE3E9F4E01182DF
:100C6000108212821382349684E0E33AF807B9F7CF
:100C7000ABD24CDF8C2FCF9190CECF93809192044A
:100C8000C82FC26081FF02C0CF9108958C2F93DEE0
:100C90008823D1F3C09392042CDEE3E9F4E01182BF
:100CA000108212821382349684E0E33AF807B9F78F
:100CB0008BD22CDF8C2FCF9170CECF93809192046A
:100CC000C82FCB7F82FD02C0CF9108958C2F73DE99
:100CD0008823D1F3C09392040CDEE3E9F4E011829F
:100CE000108212821382349684E0E33AF807B9F74F
:100CF0006BD20CDF8C2FCF9150CECF93809192048A
:100D0000C82FC46082FF02C0CF9108958C2F53DE9C
:100D10008823D1F3C0939204ECDDE3E9F4E011827F
:100D2000108212821382349684E0E33AF807B9F70E
:100D30004BD2ECDE8C2FCF9130CECF9380919204AA
:100D4000C82FC77F83FD02C0CF9108958C2F33DE5B
:100D50008823D1F3C0939204CCDDE3E9F4E011825F
:100D6000108212821382349684E0E33AF807B9F7CE
:100D70002BD2CCDE8C2FCF9110CECF9380919204CA
:100D8000C82FC86083FF02C0CF9108958C2F13DE57
:100D90008823D1F3C0939204ACDDE3E9F4E011823F
:100DA000108212821382349684E0E33AF807B9F78E
:100DB0000BD2ACDE8C2FCF91F0CD982FA091920466
:100DC000B0E0AA0FBB1FAA0FBB1FAD56BB4F1396B7
:100DD0008C9113978823C9F012962C912223A1F0AD
:100DE000E42FF0E0EE0FFF1FEE0FFF1FED56FB4F5D
:100DF00070E0899F600D711D11240190F081E02D3C
:100E0000E60FF71F8491089580E0089581E08093B4
:100E1000A50462E08BE049C18091A50482608093C3
:100E2000A50461E08BE041C18091A50492E089278F
:100E30008093A50462E081FD61E08BE036C1909172
:100E4000A40481E089278093A40462E0913009F032
:100E500061E08AE02AC181E08093A30408951092A2
:100E6000A50462E08BE021C11092A3040895E1E0A3
:100E70008091A504811101C0E0E08091A40481115A
:100E8000E2608091A3048111E460F0E0EE5BFD4F2D
:100E900080810895CF93DF93C82FD0E0CC0FDD1F62
:100EA000CC0FDD1FC050DE4FE881F98181E019953C
:100EB00081E08A83DF91CF910895CF93DF93C82F8C
:100EC000D0E0CC0FDD1FCC0FDD1FC050DE4FE8811E
:100ED000F98180E019951A82DF91CF9108951F93CF
:100EE000CF93DF93C82FD0E0CC0FDD1FCC0FDD1FD9
:100EF000FE01E050FE4F11E08281811110E0C050F0
:100F0000DE4FE881F981812F19951A83DF91CF9106
:100F10001F910895E82FF0E0EE0FFF1FEE0FFF1F67
:100F2000E050FE4F83810895582F8091030288235B
:100F300091F0581303C027C0581771F0282F30E0E4
:100F4000982F220F331F220F331FF901E050FE4F5D
:100F500083818111F1CF089581508C30B8F49D3098
:100F6000A9F0E52FF0E0EE0FFF1FEE0FFF1FE0509E
:100F7000FE4F838120503E4FD90113968C9363839B
:100F8000428381E0089581508C3010F080E0089514
:100F900030E020E0E6CFE2E0F2E080E091E0908314
:100FA0008F5F818334968D30D1F71092330208958C
:100FB0008DE092E09093A9048093A8049093AB04F1
:100FC0008093AA049093A7048093A6040895809127
:100FD000AA049091AB049093A7048093A60408956B
:100FE0001092A9041092A8048091AA049091AB04D5
:100FF0008234910541F01092AB041092AA04109231
:10100000A7041092A60408958DE092E09093A9049D
:101010008093A8042091AA043091AB0422343105B6
:1010200041F09093AB048093AA049093A70480931B
:10103000A60408958091A6049091A7048334910595
:1010400030F48091AA049091AB04892B51F482E48E
:1010500090E09093AB048093AA049093A7048093AC
:10106000A60408958091A8049091A9049093AB04DC
:101070008093AA049093A7048093A6040895809176
:10108000A6049091A704009771F0019741F482E4BF
:1010900090E09093A7048093A60481E00895909334
:1010A000A7048093A60480E00895CF93DF93E82FF0
:1010B000F0E0EE0FFF1FE455FB4FC081633051F1AC
:1010C00080F0643009F43BC0653031F007C08C2FEC
:1010D00006DF8C2F1FDFC82FC111F9CFDF91CF9111
:1010E0000895613091F0623031F0F8CF8C2FE5DE59
:1010F0008C2F10DFC82FC111F9CFDF91CF91089548
:101100008C2FC8DE8C2F06DFC82FC111F9CFDF91DD
:10111000CF910895DC2FCC2339F18D2FE0DE8D2F78
:10112000F9DED82F8111F9CFC5DB8C2FD8DE8C2FBB
:10113000F1DEC82F8111F9CFDF91CF910895DC2F17
:10114000CC23A9F08D2FCBDE8D2FE4DED82F81119B
:10115000F9CFB5DB8C2FC3DE8C2FDCDEC82F8111DD
:10116000F9CFDF91CF910895DF91CF91A3CBDF919C
:10117000CF91A5CBE82FF0E0EE0FFF1FE455FB4F1A
:10118000618193CF0F931F93CF93DF93162F042F7B
:101190009FEF980F9B3028F0DF91CF911F910F9117
:1011A0000895C82FD0E0CC0FDD1FC455DB4F422F70
:1011B0006881812FB9DE882379F318830983DF9151
:1011C000CF911F910F910895E6DEECEAF4E01182D1
:1011D0001082329684E0E43CF807C9F70895CF9373
:1011E000DF93CDB7DEB7FE01369661917191AF0105
:1011F00084E392E094D1DF91CF9108958AE492E064
:101200009F938F93ECDF0F900F90089588E214DA8C
:1012100060E080E057D062E081E054D061E082E09D
:1012200051D063E083E04ED06EEF78E08DE061DC7A
:1012300062ED79E08CE05DDC21E040E06AE087E08F
:10124000A1DF20E040E06CE08AE09CDF21E043E0A9
:1012500068E081E097DF20E044E063E082E092CF45
:101260008AE492E09F938F93BADF0F900F900895D6
:1012700088E2E2D960E081E025D062E081E022D01E
:1012800061E082E01FD063E083E01CD060E379E09E
:101290008DE02FDC62ED79E08CE02BDC21E040E09A
:1012A0006AE087E06FDF20E040E06CE087E06ADF23
:1012B00021E043E068E081E065DF20E044E063E0B6
:1012C00082E060CFE82FF0E0EE0FFF1FE35AFD4F02
:1012D00028E049E08081918130CC85E692E09F93BF
:1012E0008F937DDF0F900F90089588E2A5D960E07D
:1012F00080E07FD062E081E07CD061E082E079D064
:1013000063E084E076D062ED79E08CE0F2DB6DE6BC
:1013100079E08DE0EEDB20E040E06AE08AE032DF59
:1013200020E040E06CE088E02DDF21E043E068E071
:1013300081E028DF20E044E063E082E023DF7FCD2E
:1013400082E892E09F938F934ADF0F900F90089569
:1013500088E272D960E081E04CD062E081E049D05F
:1013600061E083E046D063E084E043D062ED79E061
:101370008CE0BFDB60EA79E08DE0BBDB20E040E0A1
:101380006AE087E0FFDE20E040E06CE088E0FADE23
:1013900021E043E068E081E0F5DE20E044E063E046
:1013A00082E0F0CE89E992E09F938F9318DF84EA80
:1013B00092E09F938F9313DF84EB92E09F938F9340
:1013C0000EDF8EED92E09F938F9309DF84EF92E022
:1013D0009F938F9304DF8AE093E09F938F93FFDEC8
:1013E0008DB79EB70C960FB6F8949EBF0FBE8DBFFB
:1013F0000895E82FF0E0EE0FFF1FEA5EFC4F28E0B3
:1014000049E08081918199CB80E293E09F938F9313
:10141000E6DE0F900F90089528E04DE060E084EA4A
:1014200094E08BDB28E04DE062E08CE394E085DB28
:1014300028E04DE061E084ED93E07FDB28E04DE0C3
:1014400063E08CE693E079DB88E2F6D820E040E0C8
:101450006AE08AE097DE20E040E06CE08BE092DE1C
:1014600021E045E061E083E08DDE20E045E06BE0D7
:1014700083E088DE21E043E068E081E083DE21E074
:1014800044E064E082E07EDEDADC11DA64E07AE0F7
:101490008DE02FCB85D9A8D98823E9F3BAD8C82FF6
:1014A000803A29F082E015DBFC018C2F1995CAD80F
:1014B000F2CF97FB072E16F4009406D077FD08D0E4
:1014C00013D007FC05D03EF4909581959F4F089569
:1014D000709561957F4F0895EE0FFF1F881F8BBF9A
:1014E0000790F691E02D1994AA1BBB1B51E107C090
:1014F000AA1FBB1FA617B70710F0A61BB70B881FA4
:10150000991F5A95A9F780959095BC01CD01089532
:10151000DC0101C06D9341505040E0F708952F92D7
:101520003F924F925F926F927F928F929F92AF9273
:10153000BF92CF92DF92EF92FF920F931F93CF93C0
:10154000DF93CDB7DEB72F970FB6F894DEBF0FBE8F
:10155000CDBF7C013B018A01DC0117961C921E92D3
:10156000169713968C9181FFC6C19AE0292EFE0131
:1015700031964F01D70113969C91F30193FD85910C
:1015800093FF81913F01882309F43AC1853239F4F0
:1015900093FD859193FF81913F01853221F4B7013D
:1015A00090E0C2D1E7CFB12C412C512CBFE1B51551
:1015B00038F08B3209F188F4803201F1833221F165
:1015C00057FC3AC020ED280F2A3040F556FE1FC0C8
:1015D000B29C200D1124B22E06C08D3291F08033C2
:1015E00079F7689450F8F30193FD859193FF819109
:1015F0003F018111DBCF20C0689451F8689452F804
:10160000F2CF689453F8EFCF689454F8ECCF429C33
:10161000200D1124422E689455F8E5CF8E3229F41E
:1016200056FCEEC0689456F8DECF8C3619F46894F8
:1016300057F8D9CF8836B9F2982F9F7D95549330BB
:10164000B8F0833671F1833791F1833509F056C0D4
:10165000D801CD90DD908D016B2D70E056FC02C05D
:101660006FEF7FEFC6014AD15C01689457F80AC05A
:101670000C5F1F4FEFE3E983AA24A394B12C64010C
:10168000E89457F853FE26C0342CA114B10439F560
:10169000332009F46FCFB70180E290E045D13A944E
:1016A000F7CFD8018C9189830E5F1F4FE5CFF801EA
:1016B000C190D1908F016B2D70E056FC02C06FEF8E
:1016C0007FEFC60126D15C01DBCFB70180E290E05D
:1016D0002BD14A944A141B0409F0B8F7D5CFF60170
:1016E00057FC859157FE81916F01B70190E01CD1A5
:1016F00031103A94B1E0AB1AB108C7CF843619F073
:10170000893609F06DC0F80157FE63C0619171918F
:10171000819191918F01E52DEF76DE2E97FF09C023
:1017200090958095709561957F4F8F4F9F4F6894EE
:10173000D7F82AE030E0A40127D1C82EC818AC2C75
:101740005D2CD6FE0CC0E89450F8CB1440F4D4FEC7
:1017500005C0D2FC03C05D2D5E7E552EAB2C54FE21
:10176000A4C0FE01EC0DF11D8081803309F096C00C
:10177000652D697E562E752D7870372E53FCA3C0CB
:1017800050FE9DC0BC2CA41410F4B40CBA1854FE26
:10179000A0C0B70180E390E0C7D052FE06C088E742
:1017A00051FC88E590E0B701BFD0CB1408F49DC090
:1017B000CA94D12C8FEFC81AD80AC80CD91CD601EC
:1017C0008E916D01B70190E0AFD08C149D04B9F7F4
:1017D0005FCF61917191072E000C880B990B9ACF06
:1017E000D52CE894D4F82AE08537D1F1F52DF97F8E
:1017F000DF2E803749F100F5883549F18F3679F1D0
:10180000F701868197812F960FB6F894DEBF0FBE41
:10181000CDBFDF91CF911F910F91FF90EF90DF909F
:10182000CF90BF90AF909F908F907F906F905F9080
:101830004F903F902F900895883711F7D4FE02C043
:101840006894D2F820E10CC06894D4F8F7CF54FE25
:1018500003C02F2F2660D22E20E132E002C028E004
:1018600030E0F801D7FE14C041915191619171911E
:101870004C875D876E877F878F01A4016C857D858E
:101880008E859F8581D0C82EC818E894D7F857CF89
:1018900081919191AC0170E060E0EACF52FC02C00E
:1018A000A39469CFA394A39466CF852D867809F479
:1018B00062CFF6CFB70180E290E036D0A394A414B3
:1018C000C8F3312C64CF342C3A18A41408F45FCF39
:1018D000F8CF852D867809F468CF8BE251FE80E23F
:1018E00057FC8DE2B70190E05FCFB70180E390E055
:1018F0001BD0BA945ACF8FEF9FEF85CFFC01059094
:10190000615070400110D8F7809590958E0F9F1F01
:101910000895FC016150704001900110D8F7809546
:1019200090958E0F9F1F08950F931F93CF93DF9372
:10193000182F092FEB018B8181FD09C01FEF0FEFDD
:10194000812F902FDF91CF911F910F91089582FFEA
:1019500014C02E813F818C819D81281739073CF46A
:10196000E881F981CF0101969983888310838E8164
:101970009F8101969F838E83E3CFE885F985812F30
:101980001995892BA1F3DACFFA01AA27283051F152
:10199000203181F1E8946F936E7F6E5F7F4F8F4FA0
:1019A0009F4FAF4FB1E03ED0B4E03CD0670F781FFF
:1019B000891F9A1FA11D680F791F8A1F911DA11DE4
:1019C0006A0F711D811D911DA11D20D009F468941D
:1019D0003F912AE0269F11243019305D3193DEF6C5
:1019E000CF010895462F4770405D4193B3E00FD07B
:1019F000C9F7F6CF462F4F70405D4A3318F0495D66
:101A000031FD4052419302D0A9F7EACFB4E0A69548
:101A10009795879577956795BA95C9F7009761056A
:101A2000710508959B01AC010A2E069457954795C0
:101A300037952795BA95C9F7620F731F841F951FB5
:101A4000A01D0895F894FFCFB202E302E202E10282
:101A5000E002DF02DE02B202DD02DC02DB02DA02B9
:101A6000D902D802D602D402D202D002CE02CC02CF
:101A7000CA02C802C602B202C402C202C002BE0248
:101A8000BC02BA02B802B602B402EF02E702E702F1
:101A9000E702F002F102E702F202F302F402F502B9
:041AA000F602F70251
:101AA4000B0400000C040000140400001C040000DB
:101AB400240400002C040000340400003C04000052
:101AC400440400004C040000F9030000FF0300007C
:101AD400050400000000000200000000F8020000FD
:101AE400000000010201030303035B4B65796D6190
:101AF400703A20636C61737369635D0A00BC012CE6
:101B0400017401E4005B4B65796D61703A204170AA
:101B1400706C6520322028752F6C206361736529F1
:101B24005D005B4B65796D61703A204170706C6546
:101B3400203220434150535D00313020474554202A
:101B440041240D0032302041203D2041534328419F
:101B540024290D0033302049462041203C203332D3
:101B6400205448454E2041243D2243544C2B222BE3
:101B7400434852242841202B203634290D00343088
:101B8400203F2227223B41243B2227203D20223B89
:101B9400413A0D0035302049462041203C3E203357
:101BA40020474F544F2031300D00363020454E44ED
:101BB4000D52554E0D0024034C02DC029402040223
:101BC4005B4B657962643A20536F6C2D32305D0053
:00000001FF

View File

@ -0,0 +1,438 @@
:1000000047C2000061C200005FC200005DC2000084
:100010005BC2000059C2000057C2000055C2000078
:1000200053C2000051C200004FC200004DC2000088
:100030004BC2000049C200008BC3000045C2000053
:1000400043C2000041C200003FC200003DC20000A8
:100050003BC2000039C2000037C2000035C20000B8
:1000600033C2000031C20000A0A1A1A01B09A51C41
:10007000A010A0A0201A0111B12C0D0E0216031819
:10008000A00B0A0807060413A00915191412051776
:10009000A0A6A40D0A0F0CA0A01D1BA0A0C0BFBE4F
:1000A00000BDBCBBBAB9B8B7A8A9AAAB0000ADAC3B
:1000B000A0A1A1A01B09A55C7F503B2F205A415154
:1000C000A02C4D4E42564358A04B4A4847464453F5
:1000D000A049555954524557A0A6A40D0A4F4C2E7D
:1000E0007E5D5B2D3A303938403736353433323126
:1000F000A8A9AAAB0000ADACA0A1A1A01B09A57C3A
:100100007F502B3F205A4151B23C4D4E42564358EE
:10011000A04B4A4847464453A04955595452455765
:10012000A0A6A40D0A4F4C3E7E7D7B3D2A30292897
:100130006027262524232221A8A9AAAB0000ADAC64
:10014000A0A1A1A01B09A55C7F703B2F207A617143
:10015000A02C6D6E62766378A06B6A6867666473C4
:10016000A069757974726577A0A6A40D0A6F6C2ECC
:100170007E5D5B2D3A303938403736353433323195
:10018000A8A9AAAB0000ADACA4A1A1A0A01BA51575
:10019000A010A0A0201A0111A02C0D0E0216031809
:1001A000A00B0A0807060413A00915191412051755
:1001B000A0A0A00DA60F0CA0A0A0B1A0A0C0BFBE83
:1001C00008BDBCBBBAB9B8B7A8A9AAAB0000ADAC12
:1001D000A4A1A1A0A01BA515A0503B2F205A4151BE
:1001E000A02C4D4E42564358A04B4A4847464453D4
:1001F000A049555954524557A0A0A00DA64F4C2ECA
:10020000A0A0A02D3A303938083736353433323192
:10021000A8A9AAAB0000ADACA4A1A1A0A01BA515E4
:10022000A0402B3F205A4151A03C4D5E42564358BE
:10023000A04B4A4847464453A04955595452455744
:10024000A0A0A00DA64F4C3EA0A0B23D2A30292868
:100250000827262524232221A8A9AAAB0000ADAC9B
:10026000A4A1A1A0A01BA515A0502B3F205A41512D
:10027000A03C4D4E42564358A04B4A484746445333
:10028000A049555954524557A0A0A00D404F4C3E8F
:10029000A0A0B23D2A302928082726252423222180
:1002A000A8A9AAAB0000ADACA4A1A1A0A01BA51554
:1002B0007F703B2F207A6171A02C6D6E627663781F
:1002C000A06B6A6867666473A069757974726577F4
:1002D000A0A0A00D5E6F6C2EA0A0A02D3A303938E2
:1002E0000837363534333231A8A9AAAB0000ADAC9B
:1002F000A5A20113040607080A0B0C0B0A7FB1A57F
:10030000A4A11A180316020E0D0C0E0FA180A0A0B6
:100310001B010203040506070809000D1E1B1C1D16
:10032000B20911170512141915090F10000D0A8CC6
:10033000A8A9AAAB0000ADACB3978120939A8E8B8D
:100340002D372A382F39A0A0343135323633A0A0CA
:10035000302E2BA0A0A0A0A0A5A241534446474800
:100360004A4B4C3B3A5FA6A5A4A15A584356424E6D
:100370004D3C3E3FA180A0A01B21222324252627FF
:100380002829203D7E5B5C5DB20951574552545986
:1003900055494F50600D0A8CA8A9AAAB0000ADAC1E
:1003A000B3978120939A8E8B2D372A382F39A0A0AE
:1003B000343135323633A0A0302E2BA0A0A0A0A01F
:1003C000A5A24153444647484A4B4C3B3A7FA6A519
:1003D000A4A15A584356424E4D2C2E2FA180A0A0C6
:1003E0001B313233343536373839302D5E5B5C5D46
:1003F000B20951574552545955494F50400D0A8C36
:10040000A8A9AAAB0000ADACB3978120939A8E8BBC
:100410002D372A382F39A0A0343135323633A0A0F9
:10042000302E2BA0A0A0A0A0A5A26173646667686F
:100430006A6B6C3B3A7FA6A5A4A17A786376626E5C
:100440006D2C2E2FA180A0A01B31323334353637CE
:100450003839302D5E5B5C5DB209717765727479F5
:1004600075696F70400D0A8CA8A9AAAB0000ADACED
:10047000B3978120939A8E8B2D372A382F39A0A0DD
:10048000343135323633A0A0302E2BA0A0A0A0A04E
:1004900011241FBECFEFD8E0DEBFCDBF12E0A0E039
:1004A000B1E0EAE1FAE102C005900D92A033B10794
:1004B000D9F723E0A0E3B2E001C01D92A43CB2074B
:1004C000E1F799D70C94DD0C9BCD805A813208F06E
:1004D0000895E82FF0E0E152F34FAFC784E09BC2EC
:1004E0008DE099C28CE097C28BE095C28AE093C2FE
:1004F00089E091C288E08FC287E08DC286E08BC21E
:1005000085E089C286E0E7C585E0E5C584E0E3C50E
:1005100083E0E1C582E0DFC581E0DDC589E0DBC5C0
:1005200088E0D9C587E0D7C56BC11FC5D7C396C3BF
:1005300055C314C330C540C433C427C41EC417C434
:10054000815A8D3008F00895E82FF0E0E050F34F25
:1005500074C736C43AC437C5E1C220C35FC39EC363
:10056000F0C451C1CF93C82F8A3041F06C2F8091D5
:1005700032020CD28C2F90E0CF9108956DE08091E3
:10058000320204D2F3CFCF938091320221D2C82F0E
:10059000803A41F0809130029091310246D18C2F07
:1005A000CF91089580913302CF9112C290E0909341
:1005B00031028093300208955F926F927F928F9202
:1005C0009F92AF92BF92CF92DF92EF92FF920F93E2
:1005D0001F93CF93DF9381E02DD25C0183E01BD288
:1005E00000E03AE0732E88248394912C50EA652E23
:1005F00068D2081708F06BC0802FF5010995D82F35
:10060000802F90E09C012B543D4F6901F90110812E
:100610001D27C0E0880F991F880F991F880F991F09
:100620009C012B5C3D4F790105C0811115C01695C9
:10063000D695CF5F51D2C81708F044C08D2F817076
:1006400010FFF3CFF701EC0FF11D90812FEF290F71
:100650009130F9F02083EBCFBBD3482F6C2F802F44
:100660005DD3909134029813E2CFBAD48823F9F283
:1006700050903402F0EAF51510F1652D80913302A7
:1006800085D180913402581691F25092340250D4A0
:10069000CECF7082F601908194010C2E01C0220F02
:1006A0000A94EAF7882319F1922B908391D3482F6B
:1006B0006C2F802F33D3582EF0EAF817F0F6852DE3
:1006C00004DFB5CF0F5FFDD1081708F495CFDF9198
:1006D000CF911F910F91FF90EF90DF90CF90BF903F
:1006E000AF909F908F907F906F905F90089520952E
:1006F000292320836DD3482F6C2F802F0FD3813A6D
:1007000038F490913402981392CF609234028FCFD4
:1007100017DF8DCF80EA8093340204D1FAD3E7D17A
:1007200080E190E006D18093330280E890E001D12F
:1007300080933202E5EBF2E080E1DF011D928A95C1
:10074000E9F740E850E06AE070E085E392E08FC6A8
:100750008F9381E08093C6028F9118958091C60295
:100760001092C6020895882311F044980895449A7F
:100770000895882311F02D9A08952D9808958823BF
:1007800011F02C9A08952C980895882319F0459A11
:100790003D9A089545983D9A0895882319F03D980B
:1007A000459A089545983D9A0895882319F0459AE9
:1007B0003D9A08953D9845980895882319F02B98FF
:1007C000239A08952B9A239A0895089508950895D9
:1007D000882319F02F9A279A08952F98279A089519
:1007E000882319F027982F9A08952F98279A08950B
:1007F000882319F02F9A279A089527982F980895FB
:100800002E98269A08952E9A269A08958AE18A9516
:10081000F1F700C008952FE788E391E02150804070
:100820009040E1F700C0000008959C01892B61F021
:1008300090E080E0EFECF7E03197F1F700C00000C6
:10084000019628173907B1F70895F8941092C60257
:1008500087E0809361001092C6028CE787BD15BCCB
:1008600082E084BD80936E0083E085BD8091C502E7
:100870008BB98FEF8AB91092C5022E98269A3C9AAE
:10088000259A249A3C9A259A249A88B1807F88B91F
:1008900087B18F6087B92A98229A299A219A20983D
:1008A00028987894089598B1907F8F70982B98B974
:1008B00029982A9A2A98299A30E020E080E093B17A
:1008C0009095492F417050E0BA01022E01C0660F89
:1008D0000A94EAF7862B2A9A2A982F5F3F4F2830EE
:1008E000310569F708959091C50289278BB91E9A41
:1008F0008AE18A95F1F700C01E9A0895833049F085
:1009000028F4813041F0823029F4A0C4843011F4FD
:1009100034C5CFC42CC45DC4982F81E0953008F055
:1009200080E008951092C9021092C8021092C70286
:1009300008959C018091C702843034F54091C8022B
:100940005091C90260E970E0641B750B6217730770
:10095000DCF091E0980F9093C70297E08902F001D4
:100960001124E653FD4F33832283BA016A517D4F30
:1009700071836083148215821682420F531F509335
:10098000C9024093C80208958FEF089587FD1EC0E5
:100990009091C7028917DCF497E08902F0011124D5
:1009A000E653FD4F2681428153812417150674F4C6
:1009B000848190E0A081B181A80FB91F6C9301964A
:1009C000BA0128D584832F5F26830895089508955A
:1009D00087FD04C09091C70289171CF030EA832F6D
:1009E000089597E08902F0011124E653FD4F268116
:1009F0002223A1F3858190E0A081B181A80FB91FC6
:100A00003C9101966281738105D5858321502683AF
:100A1000832F089508959FEF980F9D3050F4E82F8D
:100A2000F0E0EE0FFF1FEA58FC4F0190F081E02D3F
:100A3000099408959FEF980F9D3048F4E82FF0E057
:100A4000EE0FFF1FEA58FC4F8081918108958AE0E4
:100A500095E008959FEF980F9D3040F4E82FF0E067
:100A6000EE0FFF1FEA58FC4F608371830895E6E79D
:100A7000F3E08AE095E08193919323E0E239F20775
:100A8000D1F783E594E0909379038093780383E72B
:100A900094E090937B0380937A030895643080F40C
:100AA000413170F4293060F4E62FF0E0EE0FFF1FC3
:100AB000EE0FFF1FED56FC4F80839183428323830B
:100AC000089586D1E82FF0E0EE0FFF1FEE0FFF1F15
:100AD000ED56FC4F828108957BD1E82FF0E0EE0FB8
:100AE000FF1FEE0FFF1FED56FC4F8381089580E03E
:100AF00013DF811101C0089510929203A6DEE3E98D
:100B0000F3E01182108212821382349683E0E33A7A
:100B1000F807B9F70AD3ABDF80E0F0CECF9380912E
:100B20009203C82FCE7F80FD02C0CF9108958C2FF5
:100B3000F3DE8823D1F3C093920387DEE3E9F3E089
:100B40001182108212821382349683E0E33AF8070E
:100B5000B9F7EBD28CDF8C2FCF91D0CECF93809191
:100B60009203C82FC16080FF02C0CF9108958C2FDF
:100B7000D3DE8823D1F3C093920367DEE3E9F3E089
:100B80001182108212821382349683E0E33AF807CE
:100B9000B9F7CBD26CDF8C2FCF91B0CECF938091B1
:100BA0009203C82FCD7F81FD02C0CF9108958C2F75
:100BB000B3DE8823D1F3C093920347DEE3E9F3E089
:100BC0001182108212821382349683E0E33AF8078E
:100BD000B9F7ABD24CDF8C2FCF9190CECF938091D1
:100BE0009203C82FC26081FF02C0CF9108958C2F5D
:100BF00093DE8823D1F3C093920327DEE3E9F3E089
:100C00001182108212821382349683E0E33AF8074D
:100C1000B9F78BD22CDF8C2FCF9170CECF938091F0
:100C20009203C82FCB7F82FD02C0CF9108958C2FF5
:100C300073DE8823D1F3C093920307DEE3E9F3E088
:100C40001182108212821382349683E0E33AF8070D
:100C5000B9F76BD20CDF8C2FCF9150CECF93809110
:100C60009203C82FC46082FF02C0CF9108958C2FD9
:100C700053DE8823D1F3C0939203E7DDE3E9F3E089
:100C80001182108212821382349683E0E33AF807CD
:100C9000B9F74BD2ECDE8C2FCF9130CECF93809131
:100CA0009203C82FC77F83FD02C0CF9108958C2F78
:100CB00033DE8823D1F3C0939203C7DDE3E9F3E089
:100CC0001182108212821382349683E0E33AF8078D
:100CD000B9F72BD2CCDE8C2FCF9110CECF93809151
:100CE0009203C82FC86083FF02C0CF9108958C2F54
:100CF00013DE8823D1F3C0939203A7DDE3E9F3E089
:100D00001182108212821382349683E0E33AF8074C
:100D1000B9F70BD2ACDE8C2FCF91F0CD982FA091EC
:100D20009203B0E0AA0FBB1FAA0FBB1FAD56BC4F6A
:100D300013968C9113978823C9F012962C91222335
:100D4000A1F0E42FF0E0EE0FFF1FEE0FFF1FED56B6
:100D5000FC4F70E0899F600D711D11240190F0819E
:100D6000E02DE60FF71F8491089580E0089581E05B
:100D70008093A50362E08BE049C18091A503826066
:100D80008093A50361E08BE041C18091A50392E0CF
:100D900089278093A50362E081FD61E08BE036C185
:100DA0009091A40381E089278093A40362E09130AD
:100DB00009F061E08AE02AC181E08093A3030895ED
:100DC0001092A50362E08BE021C11092A303089565
:100DD000E1E08091A503811101C0E0E08091A403CE
:100DE0008111E2608091A3038111E460F0E0EE5B89
:100DF000FE4F80810895CF93DF93C82FD0E0CC0FB2
:100E0000DD1FCC0FDD1FC050DF4FE881F98181E08D
:100E1000099581E08A83DF91CF910895CF93DF9385
:100E2000C82FD0E0CC0FDD1FCC0FDD1FC050DF4F2F
:100E3000E881F98180E009951A82DF91CF910895C8
:100E40001F93CF93DF93C82FD0E0CC0FDD1FCC0FC3
:100E5000DD1FFE01E050FF4F11E08281811110E0A3
:100E6000C050DF4FE881F981812F09951A83DF9106
:100E7000CF911F910895E82FF0E0EE0FFF1FEE0FC6
:100E8000FF1FE050FF4F83810895582F8091030189
:100E9000882391F0581303C027C0581771F0282FEA
:100EA00030E0982F220F331F220F331FF901E0503B
:100EB000FF4F83818111F1CF089581508C30B8F4B8
:100EC0009D30A9F0E52FF0E0EE0FFF1FEE0FFF1FA2
:100ED000E050FF4F838120503F4FD90113968C93F0
:100EE0006383428381E0089581508C3010F080E06C
:100EF000089530E020E0E6CFE2E0F1E080E091E02C
:100F000090838F5F818334968D30D1F710923301B7
:100F100008958DE092E09093A9038093A8039093A5
:100F2000AB038093AA039093A7038093A60308952D
:100F30008091AA039091AB039093A7038093A6039B
:100F400008951092A9031092A8038091AA0390918A
:100F5000AB038234910541F01092AB031092AA03C7
:100F60001092A7031092A60308958DE092E090934B
:100F7000A9038093A8032091AA033091AB032234E4
:100F8000310541F09093AB038093AA039093A7039C
:100F90008093A60308958091A6039091A7038334BC
:100FA000910530F48091AA039091AB03892B51F401
:100FB00082E490E09093AB038093AA039093A703FD
:100FC0008093A60308958091A8039091A90390931C
:100FD000AB038093AA039093A7038093A60308957D
:100FE0008091A6039091A703009771F0019741F4B7
:100FF00082E490E09093A7038093A60381E0089594
:101000009093A7038093A60380E00895CF93DF9386
:10101000E82FF0E0EE0FFF1FE455FC4FC081633076
:1010200051F180F0643009F43BC0653031F007C005
:101030008C2F06DF8C2F1FDFC82FC111F9CFDF9156
:10104000CF910895613091F0623031F0F8CF8C2F5C
:10105000E5DE8C2F10DFC82FC111F9CFDF91CF91C2
:1010600008958C2FC8DE8C2F06DFC82FC111F9CF51
:10107000DF91CF910895DC2FCC2339F18D2FE0DE65
:101080008D2FF9DED82F8111F9CFC0DB8C2FD8DE60
:101090008C2FF1DEC82F8111F9CFDF91CF91089508
:1010A000DC2FCC23A9F08D2FCBDE8D2FE4DED82FC3
:1010B0008111F9CFB0DB8C2FC3DE8C2FDCDEC82F83
:1010C0008111F9CFDF91CF910895DF91CF919ECB20
:1010D000DF91CF91A0CBE82FF0E0EE0FFF1FE4559A
:1010E000FC4F618193CF0F931F93CF93DF93162F04
:1010F000042F9FEF980F9B3028F0DF91CF911F9125
:101100000F910895C82FD0E0CC0FDD1FC455DC4FE0
:10111000422F6881812FB9DE882379F318830983F0
:10112000DF91CF911F910F910895E6DEECEAF3E095
:1011300011821082329683E0E43CF807C9F70895E3
:10114000CF93DF93CDB7DEB7FE01359661917191F4
:10115000AF0184E391E092D1DF91CF9108958AE4C9
:1011600091E09F938F93ECDF0F900F90089588E2AA
:101170001DDA60E080E057D062E081E054D061E0A9
:1011800082E051D063E083E04ED06FEA78E08DE0FA
:1011900061DC63E879E08CE05DDC21E040E06AE05E
:1011A00087E0A1DF20E040E06CE08AE09CDF21E006
:1011B00043E068E081E097DF20E044E063E082E024
:1011C00092CF8AE491E09F938F93BADF0F900F90B4
:1011D000089588E2EBD960E081E025D062E081E00B
:1011E00022D061E082E01FD063E083E01CD061EE9A
:1011F00078E08DE02FDC63E879E08CE02BDC21E007
:1012000040E06AE087E06FDF20E040E06CE087E0EC
:101210006ADF21E043E068E081E065DF20E044E050
:1012200063E082E060CFE82FF0E0EE0FFF1FE35AAB
:10123000FE4F28E049E08081918130CC85E691E045
:101240009F938F937DDF0F900F90089588E2AED922
:1012500060E080E07FD062E081E07CD061E082E00D
:1012600079D063E084E076D063E879E08CE0F2DB6B
:101270006EE179E08DE0EEDB20E040E06AE08AE0BC
:1012800032DF20E040E06CE088E02DDF21E043E049
:1012900068E081E028DF20E044E063E082E023DFD3
:1012A0007FCD82E891E09F938F934ADF0F900F905C
:1012B000089588E27BD960E081E04CD062E081E073
:1012C00049D061E083E046D063E084E043D063E846
:1012D00079E08CE0BFDB61E579E08DE0BBDB20E00D
:1012E00040E06AE087E0FFDE20E040E06CE088E07C
:1012F000FADE21E043E068E081E0F5DE20E044E052
:1013000063E082E0F0CE89E991E09F938F9318DF4C
:1013100084EA91E09F938F9313DF84EB91E09F9396
:101320008F930EDF8EED91E09F938F9309DF84EF13
:1013300091E09F938F9304DF8AE092E09F938F93D5
:10134000FFDE8DB79EB70C960FB6F8949EBF0FBE0A
:101350008DBF0895E82FF0E0EE0FFF1FEA5EFD4F0E
:1013600028E049E08081918199CB80E292E09F93CF
:101370008F93E6DE0F900F90089528E04DE060E037
:1013800088E294E08BDB28E04DE062E080EC93E0C3
:1013900085DB28E04DE061E088E593E07FDB28E035
:1013A0004DE063E080EF92E079DB88E2FFD820E057
:1013B00040E06AE08AE097DE20E040E06CE08BE00D
:1013C00092DE21E045E061E083E08DDE20E045E053
:1013D0006BE083E088DE21E043E068E081E083DECB
:1013E00021E044E064E082E07EDEDADC0CDA65EBEA
:1013F00079E08DE02FCB8ED9B1D98823E9F3C3D81A
:10140000C82F803A29F082E015DBFC018C2F09956A
:10141000D3D8F2CF97FB072E16F4009406D077FDB1
:1014200008D011D007FC05D03EF4909581959F4FD0
:101430000895709561957F4F0895EE0FFF1F0590F9
:10144000F491E02D0994AA1BBB1B51E107C0AA1F10
:10145000BB1FA617B70710F0A61BB70B881F991F55
:101460005A95A9F780959095BC01CD010895DC01AE
:1014700001C06D9341505040E0F70895AFE0B0E0F7
:10148000E3E4FAE063C27C013B018A01DC011796C8
:101490001C921E92169713968C9181FFB0C19AE010
:1014A000292EFE0131964F01D70113969C91F3012D
:1014B00093FD859193FF81913F01882309F43AC1FF
:1014C000853239F493FD859193FF81913F018532F7
:1014D00021F4B70190E0ACD1E7CFB12C412C512CD5
:1014E000BFE1B51538F08B3209F188F4803201F193
:1014F000833221F157FC3AC020ED280F2A3040F505
:1015000056FE1FC0B29C200D1124B22E06C08D3293
:1015100091F0803379F7689450F8F30193FD859149
:1015200093FF81913F018111DBCF20C0689451F876
:10153000689452F8F2CF689453F8EFCF689454F857
:10154000ECCF429C200D1124422E689455F8E5CF33
:101550008E3229F456FCEEC0689456F8DECF8C36F5
:1015600019F4689457F8D9CF8836B9F2982F9F7D2F
:1015700095549330B8F0833671F1833791F1833508
:1015800009F056C0D801CD90DD908D016B2D70E033
:1015900056FC02C06FEF7FEFC60134D15C01689446
:1015A00057F80AC00C5F1F4FEFE3E983AA24A39406
:1015B000B12C6401E89457F853FE26C0342CA114D2
:1015C000B10439F5332009F46FCFB70180E290E020
:1015D0002FD13A94F7CFD8018C9189830E5F1F4F9A
:1015E000E5CFF801C190D1908F016B2D70E056FCD2
:1015F00002C06FEF7FEFC60110D15C01DBCFB701F6
:1016000080E290E015D14A944A141B0409F0B8F71F
:10161000D5CFF60157FC859157FE81916F01B70137
:1016200090E006D131103A94B1E0AB1AB108C7CFBF
:10163000843619F0893609F06DC0F80157FE63C091
:1016400061917191819191918F01E52DEF76DE2E5F
:1016500097FF09C090958095709561957F4F8F4F4A
:101660009F4F6894D7F82AE030E0A40111D1C82E2A
:10167000C818AC2C5D2CD6FE0CC0E89450F8CB14E6
:1016800040F4D4FE05C0D2FC03C05D2D5E7E552E15
:10169000AB2C54FE8EC0FE01EC0DF11D8081803319
:1016A00009F080C0652D697E562E752D7870372E15
:1016B00053FC8DC050FE87C0BC2CA41410F4B40C95
:1016C000BA1854FE8AC0B70180E390E0B1D052FE50
:1016D00006C088E751FC88E590E0B701A9D0CB149B
:1016E00008F487C0CA94D12C8FEFC81AD80AC80C46
:1016F000D91CD6018E916D01B70190E099D08C1460
:101700009D04B9F75FCF61917191072E000C880B92
:10171000990B9ACFD52CE894D4F82AE0853721F19B
:10172000F52DF97FDF2E803799F050F4883599F048
:101730008F36C9F0F701868197812F96E2E122C1A9
:101740008837C1F7D4FE02C06894D2F820E10CC0FB
:101750006894D4F8F7CF54FE03C02F2F2660D22E02
:1017600020E132E002C028E030E0F801D7FE14C0EA
:1017700041915191619171914C875D876E877F870F
:101780008F01A4016C857D858E859F8581D0C82EB3
:10179000C818E894D7F86DCF81919191AC0170E0B1
:1017A00060E0EACF52FC02C0A3947FCFA394A3943D
:1017B0007CCF852D867809F478CFF6CFB70180E20B
:1017C00090E036D0A394A414C8F3312C7ACF342CF3
:1017D0003A18A41408F475CFF8CF852D867809F44B
:1017E0007ECF8BE251FE80E257FC8DE2B70190E0A4
:1017F00075CFB70180E390E01BD0BA9470CF8FEF24
:101800009FEF9BCFFC010590615070400110D8F70D
:10181000809590958E0F9F1F0895FC016150704038
:1018200001900110D8F7809590958E0F9F1F089515
:101830000F931F93CF93DF93182F092FEB018B8109
:1018400081FD09C01FEF0FEF812F902FDF91CF9106
:101850001F910F91089582FF14C02E813F818C81CA
:101860009D81281739073CF4E881F981CF01019661
:101870009983888310838E819F8101969F838E83B5
:10188000E3CFE885F985812F0995892BA1F3DACF7C
:10189000FA01AA27283051F1203181F1E8946F93A1
:1018A0006E7F6E5F7F4F8F4F9F4FAF4FB1E03ED047
:1018B000B4E03CD0670F781F891F9A1FA11D680FE5
:1018C000791F8A1F911DA11D6A0F711D811D911D18
:1018D000A11D20D009F468943F912AE0269F11248D
:1018E0003019305D3193DEF6CF010895462F4770F1
:1018F000405D4193B3E00FD0C9F7F6CF462F4F704C
:10190000405D4A3318F0495D31FD4052419302D0A9
:10191000A9F7EACFB4E0A69597958795779567954F
:10192000BA95C9F700976105710508959B01AC014F
:101930000A2E06945795479537952795BA95C9F776
:10194000620F731F841F951FA01D08952F923F9251
:101950004F925F926F927F928F929F92AF92BF92BF
:10196000CF92DF92EF92FF920F931F93CF93DF936B
:10197000CDB7DEB7CA1BDB0B0FB6F894DEBF0FBEC8
:10198000CDBF09942A88398848885F846E847D8415
:101990008C849B84AA84B984C884DF80EE80FD8017
:1019A0000C811B81AA81B981CE0FD11D0FB6F8948D
:1019B000DEBF0FBECDBFED010895F894FFCF6E02DC
:1019C0009F029E029D029C029B029A026E02990255
:1019D00098029702960295029402920290028E0259
:1019E0008C028A0288028602840282026E028002CF
:1019F0007E027C027A02780276027402720270021F
:101A0000A902A302A302A302AA02AB02A302AC0290
:0A1A1000AD02AE02AF02B002B10257
:101A1A00E5030000C5030000CD030000D503000064
:101A2A00DD030000E6030000E7030000E80300000E
:101A3A00F0030000F8030000B3030000B90300003C
:101A4A00BF0300000000000200000000B202000014
:101A5A00000000010201030303035B4B65796D611A
:101A6A00703A20636C61737369635D0A004001B068
:101A7A0000F80068005B4B65796D61703A2041702F
:101A8A00706C6520322028752F6C2063617365297C
:101A9A005D005B4B65796D61703A204170706C65D1
:101AAA00203220434150535D0031302047455420B5
:101ABA0041240D0032302041203D2041534328412A
:101ACA0024290D0033302049462041203C2033325E
:101ADA00205448454E2041243D2243544C2B222B6E
:101AEA00434852242841202B203634290D00343013
:101AFA00203F2227223B41243B2227203D20223B14
:101B0A00413A0D0035302049462041203C3E2033E1
:101B1A0020474F544F2031300D00363020454E4477
:101B2A000D52554E0D00A802D0016002180288011C
:101B3A005B4B657962643A20536F6C2D32305D00DD
:00000001FF

View File

@ -1,4 +1,4 @@
Unified Retro Keyboard firmware (ASDF) rev @CMAKE_PROJECT_VERSION@
Unified Retro Keyboard firmware (ASDF) rev 1.6.3
=======================================================================
.. toctree::

View File

@ -0,0 +1,7 @@
.. _atmega2560 Rev 1.6.3:
ASDF Rev 1.6.3 hex file (atmega2560)
----------------------------------------------------------------------------------
:ASDF Firmware 1.6.3-atmega2560:
:download:`asdf-v1.6.3-atmega2560.hex`

View File

@ -0,0 +1,7 @@
.. _atmega328p Rev 1.6.3:
ASDF Rev 1.6.3 hex file (atmega328p)
----------------------------------------------------------------------------------
:ASDF Firmware 1.6.3-atmega328p:
:download:`asdf-v1.6.3-atmega328p.hex`

View File

@ -0,0 +1,134 @@
/*
* _sphinx_javascript_frameworks_compat.js
* ~~~~~~~~~~
*
* Compatability shim for jQuery and underscores.js.
*
* WILL BE REMOVED IN Sphinx 6.0
* xref RemovedInSphinx60Warning
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/
jQuery.urldecode = function(x) {
if (!x) {
return x
}
return decodeURIComponent(x.replace(/\+/g, ' '));
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var bbox = node.parentElement.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}

899
_static/basic.css Normal file
View File

@ -0,0 +1,899 @@
/*
* basic.css
* ~~~~~~~~~
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
div.section::after {
display: block;
content: '';
clear: left;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
word-wrap: break-word;
overflow-wrap : break-word;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar #searchbox form.search {
overflow: hidden;
}
div.sphinxsidebar #searchbox input[type="text"] {
float: left;
width: 80%;
padding: 0.25em;
box-sizing: border-box;
}
div.sphinxsidebar #searchbox input[type="submit"] {
float: left;
width: 20%;
border-left: none;
padding: 0.25em;
box-sizing: border-box;
}
img {
border: 0;
max-width: 100%;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li p.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
margin-left: auto;
margin-right: auto;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable ul {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
table.indextable > tbody > tr > td > ul {
padding-left: 0em;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- domain module index --------------------------------------------------- */
table.modindextable td {
padding: 2px;
border-collapse: collapse;
}
/* -- general body styles --------------------------------------------------- */
div.body {
min-width: 360px;
max-width: 800px;
}
div.body p, div.body dd, div.body li, div.body blockquote {
-moz-hyphens: auto;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
a.headerlink {
visibility: hidden;
}
a.brackets:before,
span.brackets > a:before{
content: "[";
}
a.brackets:after,
span.brackets > a:after {
content: "]";
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink,
caption:hover > a.headerlink,
p.caption:hover > a.headerlink,
div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
img.align-left, figure.align-left, .figure.align-left, object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
img.align-right, figure.align-right, .figure.align-right, object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
img.align-center, figure.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
img.align-default, figure.align-default, .figure.align-default {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-default {
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar,
aside.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px;
background-color: #ffe;
width: 40%;
float: right;
clear: right;
overflow-x: auto;
}
p.sidebar-title {
font-weight: bold;
}
div.admonition, div.topic, blockquote {
clear: left;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- content of sidebars/topics/admonitions -------------------------------- */
div.sidebar > :last-child,
aside.sidebar > :last-child,
div.topic > :last-child,
div.admonition > :last-child {
margin-bottom: 0;
}
div.sidebar::after,
aside.sidebar::after,
div.topic::after,
div.admonition::after,
blockquote::after {
display: block;
content: '';
clear: both;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
margin-top: 10px;
margin-bottom: 10px;
border: 0;
border-collapse: collapse;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
table.align-default {
margin-left: auto;
margin-right: auto;
}
table caption span.caption-number {
font-style: italic;
}
table caption span.caption-text {
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
th > :first-child,
td > :first-child {
margin-top: 0px;
}
th > :last-child,
td > :last-child {
margin-bottom: 0px;
}
/* -- figures --------------------------------------------------------------- */
div.figure, figure {
margin: 0.5em;
padding: 0.5em;
}
div.figure p.caption, figcaption {
padding: 0.3em;
}
div.figure p.caption span.caption-number,
figcaption span.caption-number {
font-style: italic;
}
div.figure p.caption span.caption-text,
figcaption span.caption-text {
}
/* -- field list styles ----------------------------------------------------- */
table.field-list td, table.field-list th {
border: 0 !important;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.field-name {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual;
}
/* -- hlist styles ---------------------------------------------------------- */
table.hlist {
margin: 1em 0;
}
table.hlist td {
vertical-align: top;
}
/* -- object description styles --------------------------------------------- */
.sig {
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
}
.sig-name, code.descname {
background-color: transparent;
font-weight: bold;
}
.sig-name {
font-size: 1.1em;
}
code.descname {
font-size: 1.2em;
}
.sig-prename, code.descclassname {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.sig-paren {
font-size: larger;
}
.sig-param.n {
font-style: italic;
}
/* C++ specific styling */
.sig-inline.c-texpr,
.sig-inline.cpp-texpr {
font-family: unset;
}
.sig.c .k, .sig.c .kt,
.sig.cpp .k, .sig.cpp .kt {
color: #0033B3;
}
.sig.c .m,
.sig.cpp .m {
color: #1750EB;
}
.sig.c .s, .sig.c .sc,
.sig.cpp .s, .sig.cpp .sc {
color: #067D17;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
:not(li) > ol > li:first-child > :first-child,
:not(li) > ul > li:first-child > :first-child {
margin-top: 0px;
}
:not(li) > ol > li:last-child > :last-child,
:not(li) > ul > li:last-child > :last-child {
margin-bottom: 0px;
}
ol.simple ol p,
ol.simple ul p,
ul.simple ol p,
ul.simple ul p {
margin-top: 0;
}
ol.simple > li:not(:first-child) > p,
ul.simple > li:not(:first-child) > p {
margin-top: 0;
}
ol.simple p,
ul.simple p {
margin-bottom: 0;
}
dl.footnote > dt,
dl.citation > dt {
float: left;
margin-right: 0.5em;
}
dl.footnote > dd,
dl.citation > dd {
margin-bottom: 0em;
}
dl.footnote > dd:after,
dl.citation > dd:after {
content: "";
clear: both;
}
dl.field-list {
display: grid;
grid-template-columns: fit-content(30%) auto;
}
dl.field-list > dt {
font-weight: bold;
word-break: break-word;
padding-left: 0.5em;
padding-right: 5px;
}
dl.field-list > dt:after {
content: ":";
}
dl.field-list > dd {
padding-left: 0.5em;
margin-top: 0em;
margin-left: 0em;
margin-bottom: 0em;
}
dl {
margin-bottom: 15px;
}
dd > :first-child {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dl > dd:last-child,
dl > dd:last-child > :last-child {
margin-bottom: 0;
}
dt:target, span.highlighted {
background-color: #fbe54e;
}
rect.highlighted {
fill: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa;
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
.classifier:before {
font-style: normal;
margin: 0 0.5em;
content: ":";
display: inline-block;
}
abbr, acronym {
border-bottom: dotted 1px;
cursor: help;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
overflow-y: hidden; /* fixes display issues on Chrome browsers */
}
pre, div[class*="highlight-"] {
clear: both;
}
span.pre {
-moz-hyphens: none;
-ms-hyphens: none;
-webkit-hyphens: none;
hyphens: none;
white-space: nowrap;
}
div[class*="highlight-"] {
margin: 1em 0;
}
td.linenos pre {
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
display: block;
}
table.highlighttable tbody {
display: block;
}
table.highlighttable tr {
display: flex;
}
table.highlighttable td {
margin: 0;
padding: 0;
}
table.highlighttable td.linenos {
padding-right: 0.5em;
}
table.highlighttable td.code {
flex: 1;
overflow: hidden;
}
.highlight .hll {
display: block;
}
div.highlight pre,
table.highlighttable pre {
margin: 0;
}
div.code-block-caption + div {
margin-top: 0;
}
div.code-block-caption {
margin-top: 1em;
padding: 2px 5px;
font-size: small;
}
div.code-block-caption code {
background-color: transparent;
}
table.highlighttable td.linenos,
span.linenos,
div.highlight span.gp { /* gp: Generic.Prompt */
user-select: none;
-webkit-user-select: text; /* Safari fallback only */
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
}
div.code-block-caption span.caption-number {
padding: 0.1em 0.3em;
font-style: italic;
}
div.code-block-caption span.caption-text {
}
div.literal-block-wrapper {
margin: 1em 0;
}
code.xref, a code {
background-color: transparent;
font-weight: bold;
}
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
span.eqno a.headerlink {
position: absolute;
z-index: 1;
}
div.math:hover a.headerlink {
visibility: visible;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}

View File

@ -0,0 +1 @@
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

4
_static/css/theme.css Normal file

File diff suppressed because one or more lines are too long

264
_static/doctools.js Normal file
View File

@ -0,0 +1,264 @@
/*
* doctools.js
* ~~~~~~~~~~~
*
* Base JavaScript utilities for all Sphinx HTML documentation.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
"use strict";
const _ready = (callback) => {
if (document.readyState !== "loading") {
callback();
} else {
document.addEventListener("DOMContentLoaded", callback);
}
};
/**
* highlight a given string on a node by wrapping it in
* span elements with the given class name.
*/
const _highlight = (node, addItems, text, className) => {
if (node.nodeType === Node.TEXT_NODE) {
const val = node.nodeValue;
const parent = node.parentNode;
const pos = val.toLowerCase().indexOf(text);
if (
pos >= 0 &&
!parent.classList.contains(className) &&
!parent.classList.contains("nohighlight")
) {
let span;
const closestNode = parent.closest("body, svg, foreignObject");
const isInSVG = closestNode && closestNode.matches("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.classList.add(className);
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
parent.insertBefore(
span,
parent.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling
)
);
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
const rect = document.createElementNS(
"http://www.w3.org/2000/svg",
"rect"
);
const bbox = parent.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute("class", className);
addItems.push({ parent: parent, target: rect });
}
}
} else if (node.matches && !node.matches("button, select, textarea")) {
node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
}
};
const _highlightText = (thisNode, text, className) => {
let addItems = [];
_highlight(thisNode, addItems, text, className);
addItems.forEach((obj) =>
obj.parent.insertAdjacentElement("beforebegin", obj.target)
);
};
/**
* Small JavaScript module for the documentation.
*/
const Documentation = {
init: () => {
Documentation.highlightSearchWords();
Documentation.initDomainIndexTable();
Documentation.initOnKeyListeners();
},
/**
* i18n support
*/
TRANSLATIONS: {},
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
LOCALE: "unknown",
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext: (string) => {
const translated = Documentation.TRANSLATIONS[string];
switch (typeof translated) {
case "undefined":
return string; // no translation
case "string":
return translated; // translation exists
default:
return translated[0]; // (singular, plural) translation tuple exists
}
},
ngettext: (singular, plural, n) => {
const translated = Documentation.TRANSLATIONS[singular];
if (typeof translated !== "undefined")
return translated[Documentation.PLURAL_EXPR(n)];
return n === 1 ? singular : plural;
},
addTranslations: (catalog) => {
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
Documentation.PLURAL_EXPR = new Function(
"n",
`return (${catalog.plural_expr})`
);
Documentation.LOCALE = catalog.locale;
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords: () => {
const highlight =
new URLSearchParams(window.location.search).get("highlight") || "";
const terms = highlight.toLowerCase().split(/\s+/).filter(x => x);
if (terms.length === 0) return; // nothing to do
// There should never be more than one element matching "div.body"
const divBody = document.querySelectorAll("div.body");
const body = divBody.length ? divBody[0] : document.querySelector("body");
window.setTimeout(() => {
terms.forEach((term) => _highlightText(body, term, "highlighted"));
}, 10);
const searchBox = document.getElementById("searchbox");
if (searchBox === null) return;
searchBox.appendChild(
document
.createRange()
.createContextualFragment(
'<p class="highlight-link">' +
'<a href="javascript:Documentation.hideSearchWords()">' +
Documentation.gettext("Hide Search Matches") +
"</a></p>"
)
);
},
/**
* helper function to hide the search marks again
*/
hideSearchWords: () => {
document
.querySelectorAll("#searchbox .highlight-link")
.forEach((el) => el.remove());
document
.querySelectorAll("span.highlighted")
.forEach((el) => el.classList.remove("highlighted"));
const url = new URL(window.location);
url.searchParams.delete("highlight");
window.history.replaceState({}, "", url);
},
/**
* helper function to focus on search bar
*/
focusSearchBar: () => {
document.querySelectorAll("input[name=q]")[0]?.focus();
},
/**
* Initialise the domain index toggle buttons
*/
initDomainIndexTable: () => {
const toggler = (el) => {
const idNumber = el.id.substr(7);
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
if (el.src.substr(-9) === "minus.png") {
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
toggledRows.forEach((el) => (el.style.display = "none"));
} else {
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
toggledRows.forEach((el) => (el.style.display = ""));
}
};
const togglerElements = document.querySelectorAll("img.toggler");
togglerElements.forEach((el) =>
el.addEventListener("click", (event) => toggler(event.currentTarget))
);
togglerElements.forEach((el) => (el.style.display = ""));
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
},
initOnKeyListeners: () => {
// only install a listener if it is really needed
if (
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
)
return;
const blacklistedElements = new Set([
"TEXTAREA",
"INPUT",
"SELECT",
"BUTTON",
]);
document.addEventListener("keydown", (event) => {
if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements
if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys
if (!event.shiftKey) {
switch (event.key) {
case "ArrowLeft":
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
const prevLink = document.querySelector('link[rel="prev"]');
if (prevLink && prevLink.href) {
window.location.href = prevLink.href;
event.preventDefault();
}
break;
case "ArrowRight":
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
const nextLink = document.querySelector('link[rel="next"]');
if (nextLink && nextLink.href) {
window.location.href = nextLink.href;
event.preventDefault();
}
break;
case "Escape":
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
Documentation.hideSearchWords();
event.preventDefault();
}
}
// some keyboard layouts may need Shift to get /
switch (event.key) {
case "/":
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
Documentation.focusSearchBar();
event.preventDefault();
}
});
},
};
// quick alias for translations
const _ = Documentation.gettext;
_ready(Documentation.init);

View File

@ -0,0 +1,14 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',
FILE_SUFFIX: '.html',
LINK_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt',
NAVIGATION_WITH_KEYS: false,
SHOW_SEARCH_SUMMARY: true,
ENABLE_SEARCH_SHORTCUTS: true,
};

BIN
_static/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

10881
_static/jquery-3.6.0.js vendored Normal file

File diff suppressed because it is too large Load Diff

2
_static/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

1
_static/js/badge_only.js Normal file
View File

@ -0,0 +1 @@
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}});

4
_static/js/html5shiv-printshiv.min.js vendored Normal file
View File

@ -0,0 +1,4 @@
/**
* @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document);

4
_static/js/html5shiv.min.js vendored Normal file
View File

@ -0,0 +1,4 @@
/**
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);

1
_static/js/theme.js Normal file

File diff suppressed because one or more lines are too long

199
_static/language_data.js Normal file
View File

@ -0,0 +1,199 @@
/*
* language_data.js
* ~~~~~~~~~~~~~~~~
*
* This script contains the language-specific data used by searchtools.js,
* namely the list of stopwords, stemmer, scorer and splitter.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
/* Non-minified version is copied as a separate JS file, is available */
/**
* Porter Stemmer
*/
var Stemmer = function() {
var step2list = {
ational: 'ate',
tional: 'tion',
enci: 'ence',
anci: 'ance',
izer: 'ize',
bli: 'ble',
alli: 'al',
entli: 'ent',
eli: 'e',
ousli: 'ous',
ization: 'ize',
ation: 'ate',
ator: 'ate',
alism: 'al',
iveness: 'ive',
fulness: 'ful',
ousness: 'ous',
aliti: 'al',
iviti: 'ive',
biliti: 'ble',
logi: 'log'
};
var step3list = {
icate: 'ic',
ative: '',
alize: 'al',
iciti: 'ic',
ical: 'ic',
ful: '',
ness: ''
};
var c = "[^aeiou]"; // consonant
var v = "[aeiouy]"; // vowel
var C = c + "[^aeiouy]*"; // consonant sequence
var V = v + "[aeiou]*"; // vowel sequence
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
var s_v = "^(" + C + ")?" + v; // vowel in stem
this.stemWord = function (w) {
var stem;
var suffix;
var firstch;
var origword = w;
if (w.length < 3)
return w;
var re;
var re2;
var re3;
var re4;
firstch = w.substr(0,1);
if (firstch == "y")
w = firstch.toUpperCase() + w.substr(1);
// Step 1a
re = /^(.+?)(ss|i)es$/;
re2 = /^(.+?)([^s])s$/;
if (re.test(w))
w = w.replace(re,"$1$2");
else if (re2.test(w))
w = w.replace(re2,"$1$2");
// Step 1b
re = /^(.+?)eed$/;
re2 = /^(.+?)(ed|ing)$/;
if (re.test(w)) {
var fp = re.exec(w);
re = new RegExp(mgr0);
if (re.test(fp[1])) {
re = /.$/;
w = w.replace(re,"");
}
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
re2 = new RegExp(s_v);
if (re2.test(stem)) {
w = stem;
re2 = /(at|bl|iz)$/;
re3 = new RegExp("([^aeiouylsz])\\1$");
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re2.test(w))
w = w + "e";
else if (re3.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
else if (re4.test(w))
w = w + "e";
}
}
// Step 1c
re = /^(.+?)y$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(s_v);
if (re.test(stem))
w = stem + "i";
}
// Step 2
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step2list[suffix];
}
// Step 3
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step3list[suffix];
}
// Step 4
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
re2 = /^(.+?)(s|t)(ion)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
if (re.test(stem))
w = stem;
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1] + fp[2];
re2 = new RegExp(mgr1);
if (re2.test(stem))
w = stem;
}
// Step 5
re = /^(.+?)e$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
re2 = new RegExp(meq1);
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
w = stem;
}
re = /ll$/;
re2 = new RegExp(mgr1);
if (re.test(w) && re2.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
// and turn initial Y back to y
if (firstch == "y")
w = firstch.toLowerCase() + w.substr(1);
return w;
}
}

BIN
_static/minus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

BIN
_static/plus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

74
_static/pygments.css Normal file
View File

@ -0,0 +1,74 @@
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; }
.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #9C6500 } /* Comment.Preproc */
.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #E40000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #008400 } /* Generic.Inserted */
.highlight .go { color: #717171 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #687822 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #767600 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #666666 } /* Literal.Number.Bin */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #A45A77 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0000FF } /* Name.Function.Magic */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .vm { color: #19177C } /* Name.Variable.Magic */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

530
_static/searchtools.js Normal file
View File

@ -0,0 +1,530 @@
/*
* searchtools.js
* ~~~~~~~~~~~~~~~~
*
* Sphinx JavaScript utilities for the full-text search.
*
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
"use strict";
/**
* Simple result scoring code.
*/
if (typeof Scorer === "undefined") {
var Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [docname, title, anchor, descr, score, filename]
// and returns the new score.
/*
score: result => {
const [docname, title, anchor, descr, score, filename] = result
return score
},
*/
// query matches the full name of an object
objNameMatch: 11,
// or matches in the last dotted part of the object name
objPartialMatch: 6,
// Additive scores depending on the priority of the object
objPrio: {
0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5, // used to be unimportantResults
},
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query found in title
title: 15,
partialTitle: 7,
// query found in terms
term: 5,
partialTerm: 2,
};
}
const _removeChildren = (element) => {
while (element && element.lastChild) element.removeChild(element.lastChild);
};
/**
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
*/
const _escapeRegExp = (string) =>
string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
const _displayItem = (item, highlightTerms, searchTerms) => {
const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT;
const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
const [docName, title, anchor, descr] = item;
let listItem = document.createElement("li");
let requestUrl;
let linkUrl;
if (docBuilder === "dirhtml") {
// dirhtml builder
let dirname = docName + "/";
if (dirname.match(/\/index\/$/))
dirname = dirname.substring(0, dirname.length - 6);
else if (dirname === "index/") dirname = "";
requestUrl = docUrlRoot + dirname;
linkUrl = requestUrl;
} else {
// normal html builders
requestUrl = docUrlRoot + docName + docFileSuffix;
linkUrl = docName + docLinkSuffix;
}
const params = new URLSearchParams();
params.set("highlight", [...highlightTerms].join(" "));
let linkEl = listItem.appendChild(document.createElement("a"));
linkEl.href = linkUrl + "?" + params.toString() + anchor;
linkEl.innerHTML = title;
if (descr)
listItem.appendChild(document.createElement("span")).innerHTML =
" (" + descr + ")";
else if (showSearchSummary)
fetch(requestUrl)
.then((responseData) => responseData.text())
.then((data) => {
if (data)
listItem.appendChild(
Search.makeSearchSummary(data, searchTerms, highlightTerms)
);
});
Search.output.appendChild(listItem);
};
const _finishSearch = (resultCount) => {
Search.stopPulse();
Search.title.innerText = _("Search Results");
if (!resultCount)
Search.status.innerText = Documentation.gettext(
"Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
);
else
Search.status.innerText = _(
`Search finished, found ${resultCount} page(s) matching the search query.`
);
};
const _displayNextItem = (
results,
resultCount,
highlightTerms,
searchTerms
) => {
// results left, load the summary and display it
// this is intended to be dynamic (don't sub resultsCount)
if (results.length) {
_displayItem(results.pop(), highlightTerms, searchTerms);
setTimeout(
() => _displayNextItem(results, resultCount, highlightTerms, searchTerms),
5
);
}
// search finished, update title and status message
else _finishSearch(resultCount);
};
/**
* Default splitQuery function. Can be overridden in ``sphinx.search`` with a
* custom function per language.
*
* The regular expression works by splitting the string on consecutive characters
* that are not Unicode letters, numbers, underscores, or emoji characters.
* This is the same as ``\W+`` in Python, preserving the surrogate pair area.
*/
if (typeof splitQuery === "undefined") {
var splitQuery = (query) => query
.split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
.filter(term => term) // remove remaining empty strings
}
/**
* Search Module
*/
const Search = {
_index: null,
_queued_query: null,
_pulse_status: -1,
htmlToText: (htmlString) => {
const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html');
htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() });
const docContent = htmlElement.querySelector('[role="main"]');
if (docContent !== undefined) return docContent.textContent;
console.warn(
"Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template."
);
return "";
},
init: () => {
const query = new URLSearchParams(window.location.search).get("q");
document
.querySelectorAll('input[name="q"]')
.forEach((el) => (el.value = query));
if (query) Search.performSearch(query);
},
loadIndex: (url) =>
(document.body.appendChild(document.createElement("script")).src = url),
setIndex: (index) => {
Search._index = index;
if (Search._queued_query !== null) {
const query = Search._queued_query;
Search._queued_query = null;
Search.query(query);
}
},
hasIndex: () => Search._index !== null,
deferQuery: (query) => (Search._queued_query = query),
stopPulse: () => (Search._pulse_status = -1),
startPulse: () => {
if (Search._pulse_status >= 0) return;
const pulse = () => {
Search._pulse_status = (Search._pulse_status + 1) % 4;
Search.dots.innerText = ".".repeat(Search._pulse_status);
if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
};
pulse();
},
/**
* perform a search for something (or wait until index is loaded)
*/
performSearch: (query) => {
// create the required interface elements
const searchText = document.createElement("h2");
searchText.textContent = _("Searching");
const searchSummary = document.createElement("p");
searchSummary.classList.add("search-summary");
searchSummary.innerText = "";
const searchList = document.createElement("ul");
searchList.classList.add("search");
const out = document.getElementById("search-results");
Search.title = out.appendChild(searchText);
Search.dots = Search.title.appendChild(document.createElement("span"));
Search.status = out.appendChild(searchSummary);
Search.output = out.appendChild(searchList);
const searchProgress = document.getElementById("search-progress");
// Some themes don't use the search progress node
if (searchProgress) {
searchProgress.innerText = _("Preparing search...");
}
Search.startPulse();
// index already loaded, the browser was quick!
if (Search.hasIndex()) Search.query(query);
else Search.deferQuery(query);
},
/**
* execute search (requires search index to be loaded)
*/
query: (query) => {
// stem the search terms and add them to the correct list
const stemmer = new Stemmer();
const searchTerms = new Set();
const excludedTerms = new Set();
const highlightTerms = new Set();
const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
splitQuery(query.trim()).forEach((queryTerm) => {
const queryTermLower = queryTerm.toLowerCase();
// maybe skip this "word"
// stopwords array is from language_data.js
if (
stopwords.indexOf(queryTermLower) !== -1 ||
queryTerm.match(/^\d+$/)
)
return;
// stem the word
let word = stemmer.stemWord(queryTermLower);
// select the correct list
if (word[0] === "-") excludedTerms.add(word.substr(1));
else {
searchTerms.add(word);
highlightTerms.add(queryTermLower);
}
});
// console.debug("SEARCH: searching for:");
// console.info("required: ", [...searchTerms]);
// console.info("excluded: ", [...excludedTerms]);
// array of [docname, title, anchor, descr, score, filename]
let results = [];
_removeChildren(document.getElementById("search-progress"));
// lookup as object
objectTerms.forEach((term) =>
results.push(...Search.performObjectSearch(term, objectTerms))
);
// lookup as search terms in fulltext
results.push(...Search.performTermsSearch(searchTerms, excludedTerms));
// let the scorer override scores with a custom scoring function
if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item)));
// now sort the results by score (in opposite order of appearance, since the
// display function below uses pop() to retrieve items) and then
// alphabetically
results.sort((a, b) => {
const leftScore = a[4];
const rightScore = b[4];
if (leftScore === rightScore) {
// same score: sort alphabetically
const leftTitle = a[1].toLowerCase();
const rightTitle = b[1].toLowerCase();
if (leftTitle === rightTitle) return 0;
return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
}
return leftScore > rightScore ? 1 : -1;
});
// remove duplicate search results
// note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
let seen = new Set();
results = results.reverse().reduce((acc, result) => {
let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(',');
if (!seen.has(resultStr)) {
acc.push(result);
seen.add(resultStr);
}
return acc;
}, []);
results = results.reverse();
// for debugging
//Search.lastresults = results.slice(); // a copy
// console.info("search results:", Search.lastresults);
// print the results
_displayNextItem(results, results.length, highlightTerms, searchTerms);
},
/**
* search for object names
*/
performObjectSearch: (object, objectTerms) => {
const filenames = Search._index.filenames;
const docNames = Search._index.docnames;
const objects = Search._index.objects;
const objNames = Search._index.objnames;
const titles = Search._index.titles;
const results = [];
const objectSearchCallback = (prefix, match) => {
const name = match[4]
const fullname = (prefix ? prefix + "." : "") + name;
const fullnameLower = fullname.toLowerCase();
if (fullnameLower.indexOf(object) < 0) return;
let score = 0;
const parts = fullnameLower.split(".");
// check for different match types: exact matches of full name or
// "last name" (i.e. last dotted part)
if (fullnameLower === object || parts.slice(-1)[0] === object)
score += Scorer.objNameMatch;
else if (parts.slice(-1)[0].indexOf(object) > -1)
score += Scorer.objPartialMatch; // matches in last name
const objName = objNames[match[1]][2];
const title = titles[match[0]];
// If more than one term searched for, we require other words to be
// found in the name/title/description
const otherTerms = new Set(objectTerms);
otherTerms.delete(object);
if (otherTerms.size > 0) {
const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
if (
[...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
)
return;
}
let anchor = match[3];
if (anchor === "") anchor = fullname;
else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
const descr = objName + _(", in ") + title;
// add custom score for some objects according to scorer
if (Scorer.objPrio.hasOwnProperty(match[2]))
score += Scorer.objPrio[match[2]];
else score += Scorer.objPrioDefault;
results.push([
docNames[match[0]],
fullname,
"#" + anchor,
descr,
score,
filenames[match[0]],
]);
};
Object.keys(objects).forEach((prefix) =>
objects[prefix].forEach((array) =>
objectSearchCallback(prefix, array)
)
);
return results;
},
/**
* search for full-text terms in the index
*/
performTermsSearch: (searchTerms, excludedTerms) => {
// prepare search
const terms = Search._index.terms;
const titleTerms = Search._index.titleterms;
const docNames = Search._index.docnames;
const filenames = Search._index.filenames;
const titles = Search._index.titles;
const scoreMap = new Map();
const fileMap = new Map();
// perform the search on the required terms
searchTerms.forEach((word) => {
const files = [];
const arr = [
{ files: terms[word], score: Scorer.term },
{ files: titleTerms[word], score: Scorer.title },
];
// add support for partial matches
if (word.length > 2) {
const escapedWord = _escapeRegExp(word);
Object.keys(terms).forEach((term) => {
if (term.match(escapedWord) && !terms[word])
arr.push({ files: terms[term], score: Scorer.partialTerm });
});
Object.keys(titleTerms).forEach((term) => {
if (term.match(escapedWord) && !titleTerms[word])
arr.push({ files: titleTerms[word], score: Scorer.partialTitle });
});
}
// no match but word was a required one
if (arr.every((record) => record.files === undefined)) return;
// found search word in contents
arr.forEach((record) => {
if (record.files === undefined) return;
let recordFiles = record.files;
if (recordFiles.length === undefined) recordFiles = [recordFiles];
files.push(...recordFiles);
// set score for the word in each file
recordFiles.forEach((file) => {
if (!scoreMap.has(file)) scoreMap.set(file, {});
scoreMap.get(file)[word] = record.score;
});
});
// create the mapping
files.forEach((file) => {
if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1)
fileMap.get(file).push(word);
else fileMap.set(file, [word]);
});
});
// now check if the files don't contain excluded terms
const results = [];
for (const [file, wordList] of fileMap) {
// check if all requirements are matched
// as search terms with length < 3 are discarded
const filteredTermCount = [...searchTerms].filter(
(term) => term.length > 2
).length;
if (
wordList.length !== searchTerms.size &&
wordList.length !== filteredTermCount
)
continue;
// ensure that none of the excluded terms is in the search result
if (
[...excludedTerms].some(
(term) =>
terms[term] === file ||
titleTerms[term] === file ||
(terms[term] || []).includes(file) ||
(titleTerms[term] || []).includes(file)
)
)
break;
// select one (max) score for the file.
const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w]));
// add result to the result list
results.push([
docNames[file],
titles[file],
"",
null,
score,
filenames[file],
]);
}
return results;
},
/**
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words, highlightWords is the list of normal, unstemmed
* words. the first one is used to find the occurrence, the
* latter for highlighting it.
*/
makeSearchSummary: (htmlText, keywords, highlightWords) => {
const text = Search.htmlToText(htmlText);
if (text === "") return null;
const textLower = text.toLowerCase();
const actualStartPosition = [...keywords]
.map((k) => textLower.indexOf(k.toLowerCase()))
.filter((i) => i > -1)
.slice(-1)[0];
const startWithContext = Math.max(actualStartPosition - 120, 0);
const top = startWithContext === 0 ? "" : "...";
const tail = startWithContext + 240 < text.length ? "..." : "";
let summary = document.createElement("p");
summary.classList.add("context");
summary.textContent = top + text.substr(startWithContext, 240).trim() + tail;
highlightWords.forEach((highlightWord) =>
_highlightText(summary, highlightWord, "highlighted")
);
return summary;
},
};
_ready(Search.init);

2042
_static/underscore-1.13.1.js Normal file

File diff suppressed because it is too large Load Diff

6
_static/underscore.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,67 +0,0 @@
cmake_minimum_required(VERSION 3.19)
set(KEYMAPFILE keymaps.txt)
# Set up the toolchain and other architecture specific details
if(ARCH MATCHES atmega328p)
message(STATUS "setting up for atmega328p")
set(AVF_H_FUSE 0xd9)
set(AVR_L_FUSE 0xd2)
set(AVR_MCU ${ARCH})
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/generic-gcc-avr.cmake)
set (PROJECT_OUT_TARGET ${PROJECT_TARGET}.elf)
elseif(ARCH MATCHES atmega2560)
message(STATUS "setting up for atmega2560")
set(AVF_H_FUSE 0x99)
set(AVR_L_FUSE 0xe7)
set(AVR_MCU ${ARCH})
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/generic-gcc-avr.cmake)
set (PROJECT_OUT_TARGET ${PROJECT_TARGET}.elf)
endif()
project("asdf"
VERSION 1.6.3
DESCRIPTION "A customizable keyboard matrix controller for retrocomputers"
LANGUAGES C)
set_property(GLOBAL PROPERTY C_STANDARD 99)
set(PROJECT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
message("SRC Dir is ${PROJECT_SRC_DIR}")
#set(PYTHON_SCRIPTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/scripts)
#message("Python scripts Dir is ${PYTHON_SCRIPTS_DIR}")
set(DOC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/docs)
message("Documentation and web page directory is ${DOC_DIR}")
set (PROJECT_TARGET_NAME asdf-v${PROJECT_VERSION}-${ARCH})
set (PROJECT_EXECUTABLE_TARGET_NAME ${PROJECT_TARGET_NAME})
if(ARCH MATCHES test)
add_subdirectory(test)
else()
if((ARCH MATCHES atmega328p) OR (ARCH MATCHES atmega2560))
set (PROJECT_EXECUTABLE_TARGET_NAME ${PROJECT_TARGET_NAME}.elf)
function(custom_add_library EXECUTABLE_NAME)
add_avr_library(${EXECUTABLE_NAME} ${ARGN})
endfunction(custom_add_library)
function(custom_add_executable EXECUTABLE_NAME)
add_avr_executable(${EXECUTABLE_NAME} ${ARGN})
endfunction(custom_add_executable)
endif()
add_subdirectory(src)
endif()
# generate reStructuredText index file for project version: Note: this may be
# rebuilt for each target, but as long as all have the same project version, the
# build is idempotent, so no issues.
configure_file(${DOC_DIR}/source/_templates/index.rst.in ${DOC_DIR}/source/index.rst)

View File

@ -1,20 +0,0 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
black = "*"
flake8 = "*"
pylint = "*"
mypy = "*"
[packages]
sphinx = "*"
sphinx-autodoc-typehints = "*"
sphinx-rtd-theme = "*"
toml = "*"
intelhex = "*"
[requires]
python_version = "3"

View File

@ -1,124 +0,0 @@
ASDF Keyboard scanning firmware
-
This is a key matrix scanner that can detect and debounce keypress and release
events on a key matrix and either send codes or perform actions on keypress or
release. Keymaps are defined per application and may, for example, generate
ASCII codes, special keyscan codes, etc. The code is modular and may be
integrated into a larger system easily.
By default, the code supports any number of rows by 8 columns, which will give
the bestperformance on an 8-bit microcontroller. For more than 8 columns per
row, the row datatype would need to be changed to uint16_t to support 16
columns, etc.
The first supported application is a parallel ASCII output keyboard. If you want
serial or USB output, you can supply your own routines.
ASDF supports basic keyboard functionality and is configurable via a few
boolean variables, and via the key maps. The key maps are organized in
row,column format, with separate keymaps shift, capslock, and control-key modes.
Features:
--
* modifiers: A set of modifier keys may be specified. When only a few modifiers
are used, this mechanism is a low-overhead alternative to a keymap overlay for
keyboard states that only change the key codes produced by a keypress, such as
SHIFT, CAPS LOCK, CONTROL, etc. The state of each modifier key is kept in a
state variable. In most cases, pressing the key will set the value to a
"pressed" state, and releasing will reset the value to an "unpressed" state.
However some functions interact. For example, Shift Lock is sticky, so
pressing Shift Lock toggles the Shift Lock state, and Releasing Shift Lock
does nothing; but pressing "Shift" will reset the "Shift Lock" state.
All modifier state variables are kept in a modifier state variable array. On a
regular keypress, all of the modifier state variables are OR'ed together to
produce an index into a value array for the standard key, to determine the
value sent by the standard keypress.
* DIP switches: DIP switches are implemented by adding them into the key
matrix, and providing activate() and deactivate() functions for the on and off
positions.
* Multiple keymaps. DIP switches 0-4 select the map. The current version
includes:
* (0): ADM-style ASCII keyboard
* (1): ADM-style ASCII keyboard (all caps)
* (2): Apple 2 ASCII keyboard (upper/lower)
* (3): Apple 2 ASCII keyboard (standard all caps)
* (4): Sol-20 ASCII keyboard
* Debounce and Repeat functions: The main keyscan logic implements key
debouncing. Multiple keys may be debounced simultaneously using a separate
debounce counter for each key in the matrix.
* Repeat key and Autorepeat: This is provided by the repeat module. Autorepeat
may be disabled or enabled either by configuration, by activate()/deactivate()
functions, or other keyboard logic. Repeat and autorepeat only apply to the
most recently pressed key.
* ASCII output - supported via output_value function.
* Virtual Output layer: Indicator LEDs and other direct logic-level hardware controls: supported via
a virtual output layer. The keymaps (and certain functions such as shiftlock and capslock) may bind virtual outputs. The keymaps may then specify how the virtual outputs map to the available physical resources. This allows one keymap to place the capslock LED in one position, and another keymap may place the capslock LED elswhere. This simplifies support of multiple keyboards and keymaps.
Compiling and configuration
--
The source files are in the ./src directory. The final build files go in the ./build directory.
To build, enter the ./src directory. You should be able to build a binary and
hex file suitable for programming a microcontroller by typing "Make". You may
edit the Makefile to specify your target platform (default is Atmega328P ASCII
controller). You may also wish to edit your preferences in "asdf_config.h" to
specify repeat timings, optimize the debounce setting (if you have very bounce
keys), and specify the character output buffer size (if you are implementing
macros, etc.)
Porting
--
This firmware was written in modular, portable C99, to be compiled with GCC
(avr-gcc for the Atmega). The hardware-sepecific files are in Arch/*.[ch]. To
adapt the Atmega port for additional hardware, enter the ./src/Arch directory,
and copy the files asdf_arch_atmega2560.c and asdf_arch_astmeg2560.h to new
filenames, and edit them to suit the hardware changes.
The firmware is designed to run from ROM on a slow vintage processor, with a
small RAM footprint, and is not re-entrant. It is designed to compile on small
architectures, or to be hand-translated to assembly on small processors, or to
an HDL for a CPLD or FPGA.
The code was written to favor readability over cleverness. While tempted to
optimize bit testing via bithacks, I opted for code simplicity since the
performance benefit was not there for 8-bit values.
To port to a new processor architecture, you may use the atmega2560 files as an
example, and create a pair of architecture-specific .c and .h files for the new
hardware, exporting the following functions:
- asdf_arch_init: initializes the CPU and hardware
- asdf_arch_read_row: given a row number, output the row to the matrix, and read
all the columns on that row asdf_arch_send_code
- asdf_arch_send_code: given a key code, output the code to the computer, via
serial, parallel, I2C, whatever is appropriate.
- asdf_arch_tick: true once every 1ms. This tests a flag set in an interrupt
routine that is triggered every 1ms. The function return value is polled and a
keyscan initiated when true. An alternative, if you have an RTOS, or even just
a scheduler, would be to schedule the keyscan every 1 ms, rather than poll. In
that case, this function is not needed, and the "superloop" in main.c would
contain a call to the scheduler.
- asdf_arch_XXXX_set: The hardware provides a number of physical resources, such
as TTL or tri-state outputs, which can be used to drive LEDs, TTL logic output
lines, etc. These are driven by a virtual output layer. The virtual layer
requires a function to set the state of the physical resources. One function
is provided for each such resource. For example, if a TTL output is called
OUT1, then the function asdf_arch_out1_set() must be defined. For now, the
required devices are:
- LED1, LED2, LED3 (LED outputs)
- OUT1, OUT2, OUT3 (TTL outputs)
- OUT1\_OPEN\_HI, OUT2\_OPEN\_HI, OUT3\_OPEN\_HI (Open collector outputs)
- OUT1\_OPEN\_LO, OUT2\_OPEN\_LO, OUT3\_OPEN\_LO (Open emitter outputs)

View File

@ -1,474 +0,0 @@
##########################################################################
# "THE ANY BEVERAGE-WARE LICENSE" (Revision 42 - based on beer-ware
# license):
# <dev@layer128.net> wrote this file. As long as you retain this notice
# you can do whatever you want with this stuff. If we meet some day, and
# you think this stuff is worth it, you can buy me a be(ve)er(age) in
# return. (I don't like beer much.)
#
# Matthias Kleemann
##########################################################################
##########################################################################
# The toolchain requires some variables set.
#
# AVR_MCU (default: atmega8)
# the type of AVR the application is built for
# AVR_L_FUSE (NO DEFAULT)
# the LOW fuse value for the MCU used
# AVR_H_FUSE (NO DEFAULT)
# the HIGH fuse value for the MCU used
# AVR_UPLOADTOOL (default: avrdude)
# the application used to upload to the MCU
# NOTE: The toolchain is currently quite specific about
# the commands used, so it needs tweaking.
# AVR_UPLOADTOOL_PORT (default: usb)
# the port used for the upload tool, e.g. usb
# AVR_PROGRAMMER (default: avrispmkII)
# the programmer hardware used, e.g. avrispmkII
##########################################################################
##########################################################################
# options
##########################################################################
#option(WITH_MCU "Add the mCU type to the target file name." OFF)
##########################################################################
# executables in use
##########################################################################
find_program(AVR_CC avr-gcc)
find_program(AVR_CXX avr-g++)
find_program(AVR_OBJCOPY avr-objcopy)
find_program(AVR_SIZE_TOOL avr-size)
find_program(AVR_OBJDUMP avr-objdump)
##########################################################################
# toolchain starts with defining mandatory variables
##########################################################################
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR avr)
set(CMAKE_C_COMPILER ${AVR_CC})
set(CMAKE_CXX_COMPILER ${AVR_CXX})
##########################################################################
# c_toolchain_flags
# - Adds a list of compiler-specific flags to the CFLAGS variable in the
# parent scope.
##########################################################################
function(c_toolchain_flags)
# fix array base indexing beginning in AVR-GCC 12:
list(APPEND TOOLCHAIN_FLAGS
-std=c99
# -Wa,-adhln
-Wall
-funsigned-char
-funsigned-bitfields
-ffunction-sections
-fdata-sections
-fpack-struct
-fshort-enums
-O2
-Wall
-Wextra
-Wpointer-arith
-Wcast-align
-Wwrite-strings
-Wswitch-default
-Wunreachable-code
-Winit-self
-Wmissing-field-initializers
-Wno-unknown-pragmas
-Wstrict-prototypes
-Wundef
-Wold-style-definition
)
if(CMAKE_C_COMPILER_VERSION GREATER_EQUAL "11.3")
message(STATUS "Appending page size fix for GCC >= 11.3")
list(APPEND TOOLCHAIN_FLAGS --param=min-pagesize=0)
endif()
set(CFLAGS ${TOOLCHAIN_FLAGS} PARENT_SCOPE)
endfunction(c_toolchain_flags)
##########################################################################
# Macros for setting optimization flag:
# - optimization_off: turn off optimization for RTOS
# - optimization_full: set optimization to desired level for app.
##########################################################################
macro(optimization_off)
set(CMAKE_CFLAGS_RELEASE "-O0" "-NDEBUG")
set(CMAKE_CFLAGS "-O0" "-NDEBUG")
endmacro(optimization_off)
macro(optimization_full)
set(CMAKE_CFLAGS_RELEASE "-O3" "-NDEBUG")
set(CMAKE_CFLAGS "-O3" "-NDEBUG")
endmacro(optimization_full)
##########################################################################
# Identification
##########################################################################
set(AVR 1)
##########################################################################
# some necessary tools and variables for AVR builds, which may not
# defined yet
# - AVR_UPLOADTOOL
# - AVR_UPLOADTOOL_PORT
# - AVR_PROGRAMMER
# - AVR_MCU
# - AVR_SIZE_ARGS
##########################################################################
# default upload tool
if(NOT AVR_UPLOADTOOL)
set(
AVR_UPLOADTOOL avrdude
CACHE STRING "Set default upload tool: avrdude"
)
find_program(AVR_UPLOADTOOL avrdude)
endif(NOT AVR_UPLOADTOOL)
# default upload tool port
if(NOT AVR_UPLOADTOOL_PORT)
set(
AVR_UPLOADTOOL_PORT usb
CACHE STRING "Set default upload tool port: usb"
)
endif(NOT AVR_UPLOADTOOL_PORT)
# default programmer (hardware)
if(NOT AVR_PROGRAMMER)
set(
AVR_PROGRAMMER avrispmkII
CACHE STRING "Set default programmer hardware model: avrispmkII"
)
endif(NOT AVR_PROGRAMMER)
# default MCU (chip)
if(NOT AVR_MCU)
set(
AVR_MCU atmega8
CACHE STRING "Set default MCU: atmega8 (see 'avr-gcc --target-help' for valid values)"
)
endif(NOT AVR_MCU)
#default avr-size args
if(NOT AVR_SIZE_ARGS)
set(AVR_SIZE_ARGS -B)
endif(NOT AVR_SIZE_ARGS)
# prepare base flags for upload tool
set(AVR_UPLOADTOOL_BASE_OPTIONS -p ${AVR_MCU} -c ${AVR_PROGRAMMER})
# use AVR_UPLOADTOOL_BAUDRATE as baudrate for upload tool (if defined)
if(AVR_UPLOADTOOL_BAUDRATE)
set(AVR_UPLOADTOOL_BASE_OPTIONS ${AVR_UPLOADTOOL_BASE_OPTIONS} -b ${AVR_UPLOADTOOL_BAUDRATE})
endif()
##########################################################################
# check build types:
# - Debug
# - Release
# - RelWithDebInfo
#
# Release is chosen, because of some optimized functions in the
# AVR toolchain, e.g. _delay_ms().
##########################################################################
if(NOT ((CMAKE_BUILD_TYPE MATCHES Release) OR
(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) OR
(CMAKE_BUILD_TYPE MATCHES Debug) OR
(CMAKE_BUILD_TYPE MATCHES MinSizeRel)))
set(
CMAKE_BUILD_TYPE Release
CACHE STRING "Choose cmake build type: Debug Release RelWithDebInfo MinSizeRel"
FORCE
)
endif(NOT ((CMAKE_BUILD_TYPE MATCHES Release) OR
(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) OR
(CMAKE_BUILD_TYPE MATCHES Debug) OR
(CMAKE_BUILD_TYPE MATCHES MinSizeRel)))
##########################################################################
##########################################################################
# target file name add-on
##########################################################################
if(WITH_MCU)
set(MCU_TYPE_FOR_FILENAME "-${AVR_MCU}")
else(WITH_MCU)
set(MCU_TYPE_FOR_FILENAME "")
endif(WITH_MCU)
##########################################################################
# add_avr_executable
# - IN_VAR: EXECUTABLE_NAME
#
# Creates targets and dependencies for AVR toolchain, building an
# executable. Calls add_executable with ELF file as target name, so
# any link dependencies need to be using that target, e.g. for
# target_link_libraries(<EXECUTABLE_NAME>-${AVR_MCU}.elf ...).
#
##########################################################################
function(add_avr_executable EXECUTABLE_NAME)
message(STATUS "target name: ${EXECUTABLE_NAME}")
if(NOT ARGN)
message(FATAL_ERROR "No source files given for ${EXECUTABLE_NAME}.")
endif(NOT ARGN)
# set file names
set(basename ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME})
set(elf_file ${basename}.elf)
set(hex_file ${basename}.hex)
set(lst_file ${basename}.lst)
set(map_file ${basename}.map)
set(eeprom_image ${basename}-eeprom.hex)
message(STATUS "elf name: ${elf_file}")
message(STATUS "project target name: ${PROJECT_TARGET_NAME}")
set(sphinx_file ${CMAKE_CURRENT_BINARY_DIR}/toc_${PROJECT_TARGET_NAME}.rst)
configure_file(${DOC_DIR}/source/_templates/hexfile_link.in ${sphinx_file})
message(STATUS "sphinx file: ${sphinx_file}")
install(FILES ${sphinx_file} DESTINATION docs/source)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${basename}.hex DESTINATION dist)
# elf file
add_executable(${elf_file} EXCLUDE_FROM_ALL ${ARGN})
set_target_properties(
${elf_file}
PROPERTIES
COMPILE_FLAGS "-mmcu=${AVR_MCU}"
LINK_FLAGS "-mmcu=${AVR_MCU} -Wl,--gc-sections -mrelax -Wl,-Map,${map_file}"
)
add_custom_command(
OUTPUT ${hex_file}
COMMAND
${AVR_OBJCOPY} -j .text -j .data -O ihex ${elf_file} ${hex_file}
COMMAND
${AVR_SIZE_TOOL} ${AVR_SIZE_ARGS} ${elf_file}
DEPENDS ${elf_file}
)
add_custom_command(
OUTPUT ${lst_file}
COMMAND
${AVR_OBJDUMP} -d ${elf_file} > ${lst_file}
DEPENDS ${elf_file}
)
# eeprom
add_custom_command(
OUTPUT ${eeprom_image}
COMMAND
${AVR_OBJCOPY} -j .eeprom --set-section-flags=.eeprom=alloc,load
--change-section-lma .eeprom=0 --no-change-warnings
-O ihex ${elf_file} ${eeprom_image}
DEPENDS ${elf_file}
)
add_custom_target(
${EXECUTABLE_NAME}
ALL
DEPENDS ${hex_file} ${lst_file} ${eeprom_image}
)
set_target_properties(
${EXECUTABLE_NAME}
PROPERTIES
OUTPUT_NAME "${elf_file}"
)
# clean
get_directory_property(clean_files ADDITIONAL_MAKE_CLEAN_FILES)
set_directory_properties(
PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "${map_file}"
)
# upload - with avrdude
add_custom_target(
upload_${EXECUTABLE_NAME}
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} ${AVR_UPLOADTOOL_OPTIONS}
-U flash:w:${hex_file}
-P ${AVR_UPLOADTOOL_PORT}
DEPENDS ${hex_file}
COMMENT "Uploading ${hex_file} to ${AVR_MCU} using ${AVR_PROGRAMMER}"
)
# upload eeprom only - with avrdude
# see also bug http://savannah.nongnu.org/bugs/?40142
add_custom_target(
upload_${EXECUTABLE_NAME}_eeprom
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} ${AVR_UPLOADTOOL_OPTIONS}
-U eeprom:w:${eeprom_image}
-P ${AVR_UPLOADTOOL_PORT}
DEPENDS ${eeprom_image}
COMMENT "Uploading ${eeprom_image} to ${AVR_MCU} using ${AVR_PROGRAMMER}"
)
# disassemble
add_custom_target(
disassemble_${EXECUTABLE_NAME}
${AVR_OBJDUMP} -h -S ${elf_file} > ${EXECUTABLE_NAME}.lst
DEPENDS ${elf_file}
)
endfunction(add_avr_executable)
##########################################################################
# add_avr_library
# - IN_VAR: LIBRARY_NAME
#
# Calls add_library with an optionally concatenated name
# <LIBRARY_NAME>${MCU_TYPE_FOR_FILENAME}.
# This needs to be used for linking against the library, e.g. calling
# target_link_libraries(...).
##########################################################################
function(add_avr_library LIBRARY_NAME)
if(NOT ARGN)
message(FATAL_ERROR "No source files given for ${LIBRARY_NAME}.")
endif(NOT ARGN)
set(lib_file ${LIBRARY_NAME}${MCU_TYPE_FOR_FILENAME})
add_library(${lib_file} STATIC ${ARGN})
set_target_properties(
${lib_file}
PROPERTIES
COMPILE_FLAGS "-mmcu=${AVR_MCU}"
OUTPUT_NAME "${lib_file}"
)
if(NOT TARGET ${LIBRARY_NAME})
add_custom_target(
${LIBRARY_NAME}
ALL
DEPENDS ${lib_file}
)
set_target_properties(
${LIBRARY_NAME}
PROPERTIES
OUTPUT_NAME "${lib_file}"
)
endif(NOT TARGET ${LIBRARY_NAME})
endfunction(add_avr_library)
##########################################################################
# avr_target_link_libraries
# - IN_VAR: EXECUTABLE_TARGET
# - ARGN : targets and files to link to
#
# Calls target_link_libraries with AVR target names (concatenation,
# extensions and so on.
##########################################################################
function(avr_target_link_libraries EXECUTABLE_TARGET)
if(NOT ARGN)
message(FATAL_ERROR "Nothing to link to ${EXECUTABLE_TARGET}.")
endif(NOT ARGN)
get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME)
foreach(TGT ${ARGN})
if(TARGET ${TGT})
get_target_property(ARG_NAME ${TGT} OUTPUT_NAME)
list(APPEND NON_TARGET_LIST ${ARG_NAME})
else(TARGET ${TGT})
list(APPEND NON_TARGET_LIST ${TGT})
endif(TARGET ${TGT})
endforeach(TGT ${ARGN})
target_link_libraries(${TARGET_LIST} ${NON_TARGET_LIST})
endfunction(avr_target_link_libraries EXECUTABLE_TARGET)
##########################################################################
# avr_target_include_directories
#
# Calls target_include_directories with AVR target names
##########################################################################
function(avr_target_include_directories EXECUTABLE_TARGET)
if(NOT ARGN)
message(FATAL_ERROR "No include directories to add to ${EXECUTABLE_TARGET}.")
endif()
get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME)
set(extra_args ${ARGN})
target_include_directories(${TARGET_LIST} ${extra_args})
endfunction()
##########################################################################
# avr_target_compile_definitions
#
# Calls target_compile_definitions with AVR target names
##########################################################################
function(avr_target_compile_definitions EXECUTABLE_TARGET)
if(NOT ARGN)
message(FATAL_ERROR "No compile definitions to add to ${EXECUTABLE_TARGET}.")
endif()
get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME)
set(extra_args ${ARGN})
target_compile_definitions(${TARGET_LIST} ${extra_args})
endfunction()
function(avr_generate_fixed_targets)
# get status
add_custom_target(
get_status
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} -n -v
COMMENT "Get status from ${AVR_MCU}"
)
# get fuses
add_custom_target(
get_fuses
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} -n
-U lfuse:r:-:b
-U hfuse:r:-:b
COMMENT "Get fuses from ${AVR_MCU}"
)
# set fuses
add_custom_target(
set_fuses
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT}
-U lfuse:w:${AVR_L_FUSE}:m
-U hfuse:w:${AVR_H_FUSE}:m
COMMENT "Setup: High Fuse: ${AVR_H_FUSE} Low Fuse: ${AVR_L_FUSE}"
)
# get oscillator calibration
add_custom_target(
get_calibration
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT}
-U calibration:r:${AVR_MCU}_calib.tmp:r
COMMENT "Write calibration status of internal oscillator to ${AVR_MCU}_calib.tmp."
)
# set oscillator calibration
add_custom_target(
set_calibration
${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT}
-U calibration:w:${AVR_MCU}_calib.hex
COMMENT "Program calibration status of internal oscillator from ${AVR_MCU}_calib.hex."
)
endfunction()

View File

@ -1,20 +0,0 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View File

@ -1,35 +0,0 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View File

@ -1,7 +0,0 @@
.. _@ARCH@ Rev @CMAKE_PROJECT_VERSION@:
ASDF Rev @CMAKE_PROJECT_VERSION@ hex file (@ARCH@)
----------------------------------------------------------------------------------
:ASDF Firmware @CMAKE_PROJECT_VERSION@-@ARCH@:
:download:`@hex_file@`

View File

@ -1,63 +0,0 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
import re
import toml
# -- Project information -----------------------------------------------------
project = "ASDF - Unified Retro Keyboard Firmware"
copyright = "2022 Osiweb.org"
author = "David F"
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.napoleon",
"sphinx.ext.autodoc", # Core library for html generation from docstrings
"sphinx_autodoc_typehints",
"sphinx.ext.viewcode",
"sphinx.ext.autosectionlabel",
"sphinx.ext.autosummary", # Create neat summary tables
]
autosummary_generate = True # Turn on sphinx.ext.autosummary
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = [
"_static"
] # Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

View File

@ -1,25 +0,0 @@
* EEPROM management
** Uses
*** Store current keyboard ID
*** Store status of various options
**** key repeat rates and delays
**** communications delays
**** serial baud rates
**** keyboard macros
**** keyboard specific options
***** all caps / upper+lower
***** handling of special keys
** Allocate on demand
** System block does not change as keyboards are changed
*** Items include:
**** current keyboard
*** All system block allocation must occur before any keyboard allocation may occur.
*** Once system EEPROM is allocated, system EEPROM is "locked"
*** If system EEPROM is locked, then EEPROM cannot be reallocated, although the parameters may be re-written.
*** provision to unlock EEPROM, for example, when firmware is updated, or during development
** Keyboard block is reset whenever the keyboard changes
*** Any parameters specific to a keyboard, such as macros, keymap-specific settings, etc. are stored here.
*** This section is erased when keymap changes, but not when a keymap is loaded from EEPROM at powerup.
*

View File

@ -1,9 +0,0 @@
list(APPEND keymap_list
"<classic:0>"
"<classic_caps:1>"
"<apple2:2>"
"<apple2_caps:3>"
"<sol:4>"
)

View File

@ -1,229 +0,0 @@
#!/bin/bash
GENERATOR="Unix Makefiles"
NUM_VALID_TARGETS=0
BUILD_TYPE=RELEASE
INSTALL_DIR="dist"
MAKE_TARGETS="all"
DOC_DIR=docs
LINKS_DIR="$DOC_DIR/source"
add_valid_target() {
VALID_TARGETS[$NUM_VALID_TARGETS]=$1
HW_SIGS[$NUM_VALID_TARGETS]=$2
((NUM_VALID_TARGETS++))
}
add_valid_target test
add_valid_target atmega328p
add_valid_target atmega2560
check_valid_target() {
result="false"
for (( i = 0; i < NUM_VALID_TARGETS; i++ ))
do
if [[ ${VALID_TARGETS[$i]} == $1 ]]
then
result=$i
fi
done
echo $result
}
do_pipenv_clean() {
echo removing old python virtual environment...
pipenv --rm
}
do_pipenv_install() {
echo installing python virtual environment...
pipenv install
}
clean_arch() {
target_arch="$1"
echo "Removing pre-existing build directory: $target_arch..."
rm -rf "build-$target_arch"
echo "Removing any build artifacts"
rm -f $INSTALL_DIR/*"$1"*
echo "Removing any download links"
rm -f $LINKS_DIR/*$1*
}
build_arch() {
local target_arch="$1"
local hardware_sig="$2"
if [[ ! -d "build-$target_arch" ]]
then
mkdir "build-$target_arch"
fi
if [[ -d "build-$target_arch" ]]
then
(cd "build-$target_arch" \
&& cmake -G "$GENERATOR" -DCMAKE_INSTALL_PREFIX=".." -DARCH="$target_arch" \
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" ..)
fi
}
deploy_arch() {
local target_arch="$1"
if [[ -d "build-$target_arch" ]]
then
(cd "build-$target_arch" \
&& make install)
fi
}
clean_all() {
echo "- Removing install dir \"$INSTALL_DIR\"..."
rm -rvf "$INSTALL_DIR"
echo "- Removing download links..."
rm -vf $DOC_DIR/source/toc_*
echo "- Removing versioned index file"
rm -vf "$DOC_DIR/source/index.rst"
}
syntax() {
echo "Usage:"
echo " $0 -t target [-t target] ..."
echo " $0 -a"
echo " $0 -h"
echo ""
echo "Options:"
echo " -h. Display this help message"
echo " -x Before creating a build directgory or virtual env, remove"
echo " any pre-existing version"
echo " -t add an architecture directory"
echo " -a Add all valid architecture directories"
echo " -i Build each specified target and install to dist directory"
echo " -p Install pipenv virtual environment for python scripts"
echo " -c Clean all artifacts"
echo " -s Copy dist files to sphinx directory"
echo "Valid targets: ${VALID_TARGETS[*]}"
}
parse() {
local SYNTAX=""
local ALL=""
local i
local valid_index
NUM_CMAKE_TARGETS=0
CLEAN_BEFORE_BUILD=""
DO_PIPENV_INSTALL=""
DEPLOY=""
CLEAN_ALL=""
COPY_DIST_TO_DOCS=""
while getopts "t:ahipxcs" optname
do
case "$optname" in
h)
SYNTAX="yes"
;;
a)
ALL="yes"
;;
t)
# Test that target is valid
valid_index=$(check_valid_target $OPTARG)
if [[ $valid_index != "false" ]]
then
CMAKE_TARGETS[$NUM_CMAKE_TARGETS]=$valid_index
((NUM_CMAKE_TARGETS++))
else
echo Unknown target \"$OPTARG\"
SYNTAX="yes"
fi
;;
p)
DO_PIPENV_INSTALL="yes"
;;
x)
CLEAN_BEFORE_BUILD="yes"
;;
i) DEPLOY="yes"
;;
s) COPY_DIST_TO_DOCS="yes"
;;
c) CLEAN_ALL="yes"
esac
done
if [[ "$SYNTAX" == "yes" ]]; then
syntax && die
fi
if [[ "$ALL" == "yes" ]]
then
for (( i=0; i<NUM_VALID_TARGETS; i++ ))
do
CMAKE_TARGETS[i]=$i
done
NUM_CMAKE_TARGETS=$NUM_VALID_TARGETS
fi
}
die() {
builtin echo $@
exit 1
}
main() {
local TARGET
local i
parse $@
if [[ "$DO_PIPENV_INSTALL" == "yes" ]]
then
if [[ "$CLEAN_BEFORE_BUILD" == "yes" ]]
then
do_pipenv_clean
fi
do_pipenv_install
fi
if [[ "$CLEAN_ALL" == "yes" ]]
then
clean_all
fi
echo Valid Targets: "${VALID_TARGETS[*]}"
for (( i=0; $i<$NUM_CMAKE_TARGETS; i++ ))
do
TARGET=${CMAKE_TARGETS[$i]}
if [[ "$CLEAN_BEFORE_BUILD" == "yes" ]]
then
clean_arch ${VALID_TARGETS[$TARGET]}
fi
build_arch ${VALID_TARGETS[$TARGET]} ${HW_SIGS[$TARGET]}
if [[ "$DEPLOY" == "yes" ]]
then
deploy_arch ${VALID_TARGETS[$TARGET]}
fi
done
if [[ $COPY_DIST_TO_DOCS == "yes" && -d "$INSTALL_DIR" ]]
then
cp -av "$INSTALL_DIR"/* docs/source
fi
}
main $@
exit 0

View File

@ -1,33 +0,0 @@
* Keymap architecture
** Keymap definition modules are in src/Keymaps
** Each keymap has its own keymap setup routine
*** void setup_mapname_keymap(void) - keymap setup function
**** register a keycode map for each modifier combination
***** The keycode maps are in flash (ROM)
**** set up virtual devices for the keymap
***** virtual device to physical device mapping
***** associated virtual device function on activate/deactivate
***** initial state
**** set up function hooks used by keymap
** Keymap definition API
*** mapping keys
#include "asdf_keymaps.h"
**** asdf_keymaps_add_map() - called from
Assigns a specified keymap matrix (ptr to FLASH) to a given keymap and modifier type.
*** adding virtual devices - called from keymap setup routine
**** asdf_virtual_init()
***** Clears the virtual device table for the keymap
***** initialize first entry in virtual device table to NULL
**** asdf_virtual_add_device()
***** Accept a virtual device code, a physical device code, a default function, and a default initial value, and create a new entry in the virtual device table.
***** increment the virtual device table pointer and set next (last) entry to NULL
* DIP SWITCHES
Note that the DIP switches are keys in the key matrix, which is initialized to
the all unpressed state at startup. Since the keymap is initialized to 0, the
keymap is consistent with the presumed initial state of the DIP switches. If
the DIP switches are not set to Keymap 0, then their position will be detected
as keypresses, and the correct keymap will be set.

View File

@ -1,869 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch.c
//
// This file contains all the architecture dependent code, including register
// setup, I/O, timers, etc.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// Wiring Information:
// Chip: {Microcontroller type and version}
//
// Example:
// PIN NAME FUNCTION
// 14-19,9,10 PORTB COLUMN inputs (1 bit per column)
// 23-25 PORTC0-2 ROW outputs (row number)
// 27 PORTC4
#include "asdf_arch.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
#include "asdf_config.h"
// Tick is true every 1 ms.
static volatile uint8_t tick = 0;
// data polarity may be changed with a DIP switch, so we use a static instead of a constant
static uint8_t data_polarity = ASDF_DEFAULT_DATA_POLARITY;
// PROCEDURE: ISR for Timer 0 overflow
// INPUTS: none
// OUTPUTS:none
//
// DESCRIPTION: Occurs every 1 ms. Set tick flag, kick watchdog.
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
ISR(TIMER0_COMPA_vect)
{
tick = 1;
}
// PROCEDURE: set_bit
// INPUTS: port: pointer to a (uint8) port
// bit: bit position to be set
// OUTPUTS: none
//
// DESCRIPTION: Give a port address and bit position, set the bit position.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES: Declared inline. Will only be inlined for functions in this module, so
// also declared static.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static inline void set_bit(volatile uint8_t *port, uint8_t bit)
{
*port |= (1 << bit);
}
// PROCEDURE: clear_bit
// INPUTS: port: pointer to a (uint8) port
// bit: bit position to be cleared
// OUTPUTS: none
//
// DESCRIPTION: Give a port address and bit position, clear the bit position.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES: Declared inline. Will only be inlined for functions in this module, so
// also declared static.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static inline void clear_bit(volatile uint8_t *port, uint8_t bit)
{
*port &= ~(1 << bit);
}
// PROCEDURE: arch_timer0_config
//
// INPUTS: bits: a 4 byte field containing the configuration values for the
// 8-bit timer0 A and B control registers, and the interrupt mask register.
//
// OUTPUTS: none
//
// DESCRIPTION: Takes a 4 byte value with settings for all the control
// registers for the 8-bit counter/timer (timer 0), and writes them all
// to the respective registers.
//
// SIDE EFFECTS: see above
//
// NOTES: Setting all the bits together, and writing all the registers from a
// single word permits more clear initialization of control fields that are
// spread across more than one word.
//
// COMPLEXITY: 1
//
// SCOPE: private
//
static void arch_timer0_config(uint32_t bits)
{
TCCR0B = 0; // first turn off timer.
TCCR0A = (bits >> TMR0A_POS) & 0xff;
TIMSK0 = (bits >> TMR0IMSK_POS) & 0xff;
TCCR0B = (bits >> TMR0B_POS) & 0xff; // Set the mode (and turn on timer) last
}
// PROCEDURE: arch_tick_timer_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up 1ms tick timer.
//
// SIDE EFFECTS:
//
// NOTES: Set up Timer 0 in CTC mode for 1 ms overflow.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_tick_timer_init(void)
{
tick = 0;
// set compare register first, so timer can operate correctly as soon as it is
// enabled.
OCR0A = TICK_COUNT;
// operate in CTC mode to overflow at exactly 1 ms
// prescaler = 64 and output compare value is 250
arch_timer0_config(TIMER0_WFM_CTC | TIMER0_DIV64 | TIMER0_INT_ON_COMA);
}
// PROCEDURE: asdf_arch_tick
// INPUTS: none
// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise
//
// DESCRIPTION: See Outputs.
//
// SIDE EFFECTS: Zeroes out the 1 ms timer flag.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
uint8_t asdf_arch_tick(void)
{
uint8_t retval = tick;
tick = 0;
return retval;
}
// PROCEDURE: asdf_arch_init_timers
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up timer for 1 ms intervals
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_clock(void)
{
CLKPR = (CLKPCE | SYSCLK_DIV1);
}
// PROCEDURE: asdf_arch_init_outputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize all LED ports as outputs. Values are not set here.
// They are set by the keymap code
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_leds(void)
{
set_bit(&ASDF_LED1_DDR, ASDF_LED1_BIT);
set_bit(&ASDF_LED2_DDR, ASDF_LED2_BIT);
set_bit(&ASDF_LED3_DDR, ASDF_LED3_BIT);
}
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED1 port drives the LED directly by pulling the cathode low, so
// clearing the bit turns the LED on.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led1_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
}
else {
set_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
}
}
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED2 output drives the LED via an inverter buffer, so a high
// output pulls the LED cathode low, lighting the LED.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led2_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
}
else {
set_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
}
}
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED3 output drives the LED via an inverter buffer, so a high
// output pulls the LED cathode low, lighting the LED.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led3_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
}
else {
set_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
}
}
// PROCEDURE: asdf_arch_null_output
// INPUTS: (uint8_t) value - ignored
// OUTPUTS: none
//
// DESCRIPTION: Does nothing.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_null_output(uint8_t value)
{
(void) value;
}
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
else {
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
// PROCEDURE: asdf_arch_out1_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_open_hi_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
else {
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
}
// PROCEDURE: asdf_arch_out1_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit to high if value is true, and hi-z if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_open_lo_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
else {
clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
}
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
}
else {
clear_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
}
set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
}
// PROCEDURE: asdf_arch_out2_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_open_hi_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
}
else {
clear_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
}
}
// PROCEDURE: asdf_arch_out2_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit to high if value is true, and hi-z if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_open_lo_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
}
else {
clear_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
clear_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
}
}
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
else {
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
// PROCEDURE: asdf_arch_out3_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_open_hi_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
else {
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
}
// PROCEDURE: asdf_arch_out3_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit to high if value is true, and hi-z if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_open_lo_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
else {
clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
}
// PROCEDURE: asdf_arch_pos_strobe
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize strobe output to positive polarity. Initial state is
// LOW
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_set_pos_strobe(void)
{
clear_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT);
set_bit(&ASDF_STROBE_DDR, ASDF_STROBE_BIT);
}
// PROCEDURE: asdf_arch_neg_strobe
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize strobe output
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
void asdf_arch_set_neg_strobe(void)
{
set_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT);
set_bit(&ASDF_STROBE_DDR, ASDF_STROBE_BIT);
}
// PROCEDURE: asdf_arch_init_ascii_output
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up output port for ASCII output
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_ascii_output(void)
{
// set all outputs
ASDF_ASCII_PORT = data_polarity;
ASDF_ASCII_DDR = ALL_OUTPUTS;
}
// PROCEDURE: asdf_arch_init_columns
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up columns port as input and enable weak pullups.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_columns(void)
{
ASDF_COLUMNS_DDR = ALL_INPUTS;
ASDF_COLUMNS_PORT = ALL_PULLUPS;
}
// PROCEDURE: asdf_arch_init_row_outputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up output port to latch keyboard matrix row for scanning.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_row_outputs(void)
{
ASDF_HIROW_DDR = ALL_OUTPUTS;
ASDF_LOROW_DDR = ALL_OUTPUTS;
}
// PROCEDURE: asdf_arch_pulse_delay_short
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by
// ASDF_PULSE_DELAY_SHORT_US
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_pulse_delay_short(void)
{
_delay_us(ASDF_PULSE_DELAY_SHORT_US);
}
// PROCEDURE: asdf_arch_pulse_delay_long
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by
// ASDF_PULSE_DELAY_LONG_MS
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_pulse_delay_long(void)
{
_delay_ms(ASDF_PULSE_DELAY_LONG_MS);
}
// PROCEDURE: asdf_arch_delay_ms
// INPUTS: (uint16) delay_ms - the delay in msec.
// OUTPUTS: none
//
// DESCRIPTION: Delays a specified number of milliseconds
//
// SIDE EFFECTS: see above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_delay_ms(uint16_t delay_ms)
{
for (uint16_t i=0; i < delay_ms; i++) {
_delay_ms(1);
}
}
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets up all the hardware for the keyboard
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_init(void)
{
// disable interrupts:
cli();
// clear the 1ms timer flag;
tick = 0;
// set up timers for 1 msec intervals
asdf_arch_init_clock();
asdf_arch_tick_timer_init();
// set up ASCII output port
asdf_arch_init_ascii_output();
// initialize keyboard data polarity and strobe polarity
data_polarity = ASDF_DEFAULT_DATA_POLARITY;
if (ASDF_DEFAULT_STROBE_POLARITY == ASDF_POSITIVE_POLARITY) {
asdf_arch_set_pos_strobe();
} else {
asdf_arch_set_neg_strobe();
}
asdf_arch_init_leds();
// set up row and column ports
asdf_arch_init_row_outputs();
asdf_arch_init_columns();
// enable interrupts:
sei();
}
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
// OUTPUTS: returns a word containing the active (pressed) columns
//
// DESCRIPTION: Outputs the argument to the ROW ports, then reads the column
// port and returns the value. The value is a binary representation of the keys
// pressed within the row, with 1=pressed, 0=released.
//
// SIDE EFFECTS: Sets ROW output port.
//
// NOTES:
//
// 1) The keymap represents an unpressed key as a "0" and a pressed key as a
// "1". So, if a keypress pulls the column line low, then the reading of the
// physical bits must be inverted.
//
// 2) A small delay (2usec) is required between setting the keyboard row outputs
// and reading the columns, which I think is due to capacitance across the
// reverse-biased diodes.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
asdf_cols_t asdf_arch_read_row(uint8_t row)
{
uint32_t rows = ~(1L << row);
ASDF_LOROW_PORT = (uint8_t)(rows & 0xff);
_delay_us(ASDF_KEYBOARD_ROW_SETTLING_TIME_US);
ASDF_HIROW_PORT = (uint8_t)((rows >> 8) & 0xff);
_delay_us(ASDF_KEYBOARD_ROW_SETTLING_TIME_US);
return ~(asdf_cols_t) ASDF_COLUMNS_PIN;
}
// PROCEDURE: asdf_arch_osi_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
// OUTPUTS: returns a word containing the active (pressed) columns
//
// DESCRIPTION: Outputs the argument to the ROW ports, then reads the column
// port and returns the value. The value is a binary representation of the keys
// pressed within the row, with 1=pressed, 0=released.
//
// SIDE EFFECTS: Sets ROW output port.
//
// NOTES:
//
// 1) The keymap represents an unpressed key as a "0" and a pressed key as a
// "1". So, if a keypress pulls the column line low, then the reading of the
// physical bits must be inverted.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
asdf_cols_t asdf_arch_osi_read_row(uint8_t row)
{
asdf_cols_t cols;
if (row > 7) {
cols = asdf_arch_read_row(row);
}
else {
// enable the OSI keyboard
clear_bit(&ASDF_OSI_KBE_PORT, ASDF_OSI_KBE_BIT);
// register the row to be read
ASDF_COLUMNS_DDR = ALL_OUTPUTS;
ASDF_COLUMNS_PORT = (1 << row);
clear_bit(&ASDF_OSI_RW_PORT, ASDF_OSI_RW_BIT);
set_bit(&ASDF_OSI_RW_PORT, ASDF_OSI_RW_BIT);
// Read in the columns
ASDF_COLUMNS_DDR = ALL_INPUTS;
return ASDF_COLUMNS_PIN;
ASDF_LOROW_PORT = row & 0xff;
cols = (asdf_cols_t) ASDF_COLUMNS_PORT;
}
return cols;
}
// PROCEDURE: asdf_arch_send_code
// INPUTS: (keycode_t) code - the 7-bit ASCII code to be output by the keyboard
// OUTPUTS: none
//
// DESCRIPTION: Takes a character code and outputs the code on a parallel ASCII
// port, with a strobe. This routine could be replaced with UART, I2C, USB, or
// other output mechanism, of course.
//
// SIDE EFFECTS: See above.
//
// NOTES: The strobe is set by the ASDF_STROBE_LENGTH definition. The data
// output and strobe polarity are set by the static data_polarity and static
// strobe_polarity variables.
//
// SCOPE:
//
// COMPLEXITY:
//
void asdf_arch_send_code(asdf_keycode_t code)
{
ASDF_ASCII_PORT = (code ^ data_polarity);
// toggle strobe. Must test before setting to avoid spurious strobe
set_bit(&ASDF_STROBE_PIN, ASDF_STROBE_BIT);
_delay_us(ASDF_STROBE_LENGTH_US);
set_bit(&ASDF_STROBE_PIN, ASDF_STROBE_BIT);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.
//

View File

@ -1,506 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch_atmega2560.h
//
// Contains architecture-specific definitions for the atmega 2560
//
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
#if !defined(ASDF_ARCH_H)
#define ASDF_ARCH_H
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "asdf.h"
// ASDF keyboard definitions:
#define F_CPU 16000000L
#define ASDF_STROBE_LENGTH_US 10 // strobe length in microseconds
#define ASDF_KEYBOARD_ROW_SETTLING_TIME_US 4 // time for keyboard capacitance to
// settle before sampling
// Clock definitions:
#define SYSCLK_DIV1 0
#define SYSCLK_DIV2 (CLKPS0)
#define SYCCLK_DIV4 (CLKPS1)
#define SYSCLK_DIV8 (CLKPS1 | CLKPS0)
#define SYSCLK_DIV16 (CLKPS2)
#define SYSCLK_DIV32 (CLKPS2 | CLKPS0)
#define SYSCLK_DIV64 (CLKPS2 | CLKPS1)
#define SYSCLK_DIV128 (CLKPS2 | CLKPS1 | CLKPS0)
#define SYSCLK_DIV256 (CLKPS3)
// Timer 0 definitions
// Define fields for register A, B, interrupt mask as 8-bit masks, and
// as masks offset into a combined config word
#define TMR0A_POS 0
#define TMR0B_POS 8
#define TMR0IMSK_POS 16
#define TMR0A (1L << TMR0A_POS)
#define TMR0B (1L << TMR0B_POS)
#define TMR0IMSK (1L << TMR0IMSK_POS)
#define TIMER0_COM_A_DISCONNECTED 0
#define TIMER0_COM_B_DISCONNECTED 0
#define TIMER0_WFM_CTC (TMR0A << WGM01)
#define TIMER0_DIV64 ((TMR0B << CS01) | (TMR0B << CS00))
#define TIMER0_INT_ON_COMA (TMR0IMSK << OCIE0A)
#define TIMER0_INT_ON_COMB (TMR0IMSK << OCIE0B)
#define TIMER0_INT_OV_ENABLE (TMR0IMSK << TOIE0)
// Macros for 16-bit timers 1, 3, 4, 5. Datasheet section 17, p. 133
//
// Define fields for Registers A, B, C, INT Mask registers as 8-bit
// masks, and as masks offset into a 32-bit combined config word.
//
// Macro definitions for individual registers are named TMRXA_*,
// TMRXB_*, and TMRXC_*.
//
// Macros for the one-step combined timer config functions are named
// TMRX_*.
//
//
// Examples:
// // Use TMRXB_* definition to set TCCR4B register
// TCCR4B |= TMRXB_DIV1;
//
// // Use TMRX_* definitions to configure timer with config function
// processor_timer4_config(TMRX_WFM_CTC | TMRX_INT_ON_CMPA);
//
#define TMRXA_POS 0
#define TMRXB_POS 8
#define TMRXC_POS 16
#define TMRXIMSK_POS 24
#define TMRXA (1L << TMRXA_POS)
#define TMRXB (1L << TMRXB_POS)
#define TMRXC (1L << TMRXC_POS)
#define TMRXIMSK (1L << TMRXIMSK_POS)
// 16-bit timer reg A - Datasheet 17.11.1, p. 154
#define TMRXA_CMPA_CLR_MATCH_SET_BOTTOM (1 << COM1A1)
#define TMRXA_CMPB_CLR_MATCH_SET_BOTTOM (1 << COM1B1)
#define TMRXA_CMPC_CLR_MATCH_SET_BOTTOM (1 << COM1C1)
#define TMRX_CMPA_CLR_MATCH_SET_BOTTOM (TMRXA << COM1A1)
#define TMRX_CMPB_CLR_MATCH_SET_BOTTOM (TMRXA << COM1B1)
#define TMRX_CMPC_CLR_MATCH_SET_BOTTOM (TMRXA << COM1C1)
// 16-bit timer reg B - Datasheet 17.11.6, p. 156
#define TMRXB_IN_CAP_POS 0x40L
#define TMRXB_IN_CAP_NEG 0L
#define TMRXB_IN_CAP_NOISE_CANCEL 0x80L
// 16-bit timer reg C -- see datasheet, 17.11.9, p. 157
#define TMRXC_FOCA 0x80L
#define TMRXC_FOCB 0x40L
#define TMRXC_FOCC 0x20L
// 16-bit timer int mask -- see datasheet 17.11.33, p. 161.
#define TMRXIM_INT_CMP_MATCH_A (1L << OCIE1A)
#define TMRXIM_INT_CMP_MATCH_B (1L << OCIE1B)
#define TMRXIM_INT_CMP_MATCH_C (1L << OCIE1C)
// 16-bit timer all registers:
#define TMRX_CMPA_DISCONNECTED 0L
#define TMRX_CMPB_DISCONNECTED 0L
#define TMRX_CMPC_DISCONNECTED 0L
#define TMRX_INT_ON_CMPA (TMRXIM_INT_CMP_MATCH_A << TMRXIMSK_POS)
// 16-bit timer clock modes - see Datasheet table 17-6, p. 157
#define TMRXB_OFF 0
#define TMRX_OFF 0
#define TMRXB_DIV1 (0x01L << CS10)
#define TMRXB_DIV8 (0x02L << CS10)
#define TMRXB_DIV64 (0x03L << CS10)
#define TMRXB_DIV256 (0x04L << CS10)
#define TMRXB_DIV1024 (0x05L << CS10)
#define TMRXB_EXT_FALLING_EDGE (0x06L << CS10)
#define TMRXB_EXT_RISING_EDGE (0x07L << CS10)
#define TMRXB_CLK_MASK 0x07L
#define TMRX_DIV1 (TMRXB_DIV1 << TMRXB_POS)
#define TMRX_DIV8 (TMRXB_DIV8 << TMRXB_POS)
#define TMRX_DIV64 (TMRXB_DIV64 << TMRXB_POS)
#define TMRX_DIV256 (TMRXB_DIV256 << TMRXB_POS)
#define TMRX_DIV1024 (TMRXB_DIV1024 << TMRXB_POS)
#define TMRX_EXT_FALLING_EDGE (TMRXB_EXT_FALLING_EDGE << TMRXB_POS)
#define TMRX_EXT_RISING_EDGE (TMRXB_EXT_RISING_EDGE << TMRXB_POS)
#define TMRXB_EDGE_SEL_POSITIVE (1 << ICES1)
#define TMRXB_EDGE_SEL_NEGATIVE 0L
#define TMRX_EDGE_SEL_POSITIVE (TMRXB << ICES1)
#define TMRX_EDGE_SEL_NEGATIVE 0L
// 16-bit waveform modes (across reg A and B) Datasheet Table 17.2, p 145
#define TMRX_WFM_NORMAL 0L
#define TMRX_WFM_PWM_PC8 (TMRXA << WGM10) // PWM Phase Correct 8-bit
#define TMRX_WFM_PWM_PC9 (TMRXA << WGM11) // PWM Phase COrrect 9-bit
#define TMRX_WFM_PWM_PC10 ((TMRXA << WGM11) | (TMRXA << WGM10)) // PWM Phase Correct 10-bit
#define TMRX_WFM_CTC (TMRXB << WGM12) // CTC
#define TMRX_WFM_PWM_FAST8 ((TMRXB << WGM12) | (TMRXA << WGM10)) // PWM Fast 8-bit
#define TMRX_WFM_PWM_FAST9 ((TMRXB << WGM12) | (TMRXA << WGM11)) // PWM Fast 9-bit
#define TMRX_WFM_PWM_FAST10 \
((TMRXB << WGM12) | (TMRXA << WGM11) | (TMRXA << WGM10)) // PWM Fast 10-bit
#define TMRX_WFM_PWM_PFC_ICR (TMRXB << WGM13) // PWM Phase and Freq Correct, TpOP=ICR
#define TMRX_WFM_PWM_PFC_OCRA \
((TMRXB << WGM13) | (TMRXA << WGM10)) // PWM Phase and Freq Correct, TOP = OCRA
#define TMRX_WFM_PWM_PC_ICR ((TMRXB << WGM13) | (TMRXA << WGM11)) // PWM PhaseCorrect, TOP = ICR
#define TMRX_WFM_PWM_PC_OCRA \
((TMRXB << WGM13) | (TMRXA << WGM11) | (TMRXA << WGM12)) // PWM PhaseCorrect, TOP=OCRA
#define TMRX_WFM_CTC_ICR ((TMRXB << WGM13) | (TMRXB << WGM12)) // CTC, TOP = ICR
#define TMRX_WFM_PWM_FAST_ICR \
((TMRXB << WGM13) | (TMRXB << WGM12) | (TMRXA << WGM11)) // PWM Fast, TOP = ICR
#define TMRX_WFM_PWM_FAST_OCRA \
((TMRXB << WGM13) | (TMRXB << WGM12) | (TMRXA << WGM11) \
| (TMRXA << WGM10)) // PWM Fast, TOP = OCRA
// USART configuration (Datasheet section 22, p. 200)
//
// Macro definitions for individual registers are named USARTA_*,
// USARTB_*, and USARTC_*.
//
// Macros for the one-step combined timer config functions are named
// USART_*.
//
//
// Examples:
// // Use USARTB_* definition to set UCSR1B register
// UCSR1B |= USARTB_DATA_REG_EMPTY_INT_EN; // enable interrupt on tx reg empty
//
// // Use USART_* definitions to configure usart with config function
// processor_usart3_config(USART_SIZE_8 | USART_PARITY_NONE | USART_STOP_1 | USART_DATA_TXEN |
// USART_DATA_RXEN | USART_RX_COMPLETE_INT_EN);
//
#define USARTA_POS 0
#define USARTB_POS 8
#define USARTC_POS 16
#define USARTA (1L << USARTA_POS)
#define USARTB (1L << USARTB_POS)
#define USARTC (1L << USARTC_POS)
// USART Register A, Datasheet 22.10.2, p. 219
#define USARTA_DATA_REG_EMPTY (1 << UDR0)
#define USARTA_FRAME_ERROR (1 << FE0)
#define USARTA_DATA_OVERRUN (1 << DOR0)
#define USARTA_PARITY_ERROR (1 << UPE0)
#define USARTA_DOUBLE_SPEED (1 << U2X0)
#define USARTA_MULTI_PROCESSOR (1 << MPCM0)
#define USART_DATA_REG_EMPTY (USARTA << UDR0)
#define USART_FRAME_ERROR (USARTA << FE0)
#define USART_DATA_OVERRUN (USARTA << DOR0)
#define USART_PARITY_ERROR (USARTA << UPE0)
#define USART_DOUBLE_SPEED (USARTA << U2X0)
#define USART_MULTI_PROCESSOR (USARTA << MPCM0)
// USART Register B, Datasheet 22.10.3, p. 220
#define USARTB_RX_COMPLETE_INT_EN (1 << RXCIE0)
#define USARTB_TX_COMPLETE_INT_EN (1 << TXCIE0)
#define USARTB_DATA_REG_EMPTY_INT_EN (1 << UDRIE0)
#define USARTB_DATA_RXEN (1 << RXEN0)
#define USARTB_DATA_TXEN (1 << TXEN0)
#define USARTB_SIZE_9 (1 << UCSZ02)
#define USARTB_RX_BIT_8 (1 << RXB80)
#define USARTB_TX_BIT_8 (1 << TXB80)
#define USART_RX_COMPLETE_INT_EN (USARTB << RXCIE0)
#define USART_TX_COMPLETE_INT_EN (USARTB << TXCIE0)
#define USART_DATA_REG_EMPTY_INT_EN (USARTB << UDRIE0)
#define USART_DATA_RXEN (USARTB << RXEN0)
#define USART_DATA_TXEN (USARTB << TXEN0)
#define USART_RX_BIT_8 (USARTB << RXB80)
#define USART_TX_BIT_8 (USARTB << TXB80)
// USART Register C, Datasheet 22.10.4, p.221
#define USARTC_MODE_ASYNC_USART (0x00L << UMSEL00)
#define USARTC_MODE_SYNC_USART (0x01L << UMSEL00)
#define USARTC_MODE_MSPIM (0x03L << UMSEL00)
#define USART_MODE_ASYNC_USART (USARTC_MODE_ASYNC_USART << USARTC_POS)
#define USART_MODE_SYNC_USART (USARTC_MODE_SYNC_USART << USARTC_POS)
#define USART_MODE_MSPIM (USARTC_MODE_MSPIM << USARTC_POS)
#define USARTC_PARITY_NONE 0
#define USARTC_PARITY_EVEN (0x01L << UPM00)
#define USARTC_PARITY_ODD (0x03 << UPM00)
#define USART_PARITY_NONE 0
#define USART_PARITY_EVEN (USARTC_PARITY_EVEN << USARTC_POS)
#define USART_PARITY_ODD (USARTC_PARITY_ODD << USARTC_POS)
#define USARTC_STOP_1 0
#define USARTC_STOP_2 (1 << USBS0)
#define USART_STOP_1 0
#define USART_STOP_2 (USARTC << USBS0)
#define USARTC_SIZE_5 0
#define USARTC_SIZE_6 (0x01L << UCSZ00)
#define USARTC_SIZE_7 (0x02L << UCSZ00)
#define USARTC_SIZE_8 (0x03L << UCSZ00)
#define USARTC_SIZE_9 USARTC_SIZE_8
#define USART_SIZE_5 0
#define USART_SIZE_6 (USARTC_SIZE_6 << USARTC_POS)
#define USART_SIZE_7 (USARTC_SIZE_7 << USARTC_POS)
#define USART_SIZE_8 (USARTC_SIZE_8 << USARTC_POS)
#define USART_SIZE_9 ((USARTB_SIZE_9 << USARTB_POS) | (USARTC_SIZE_9 << USARTC_POS))
#define USARTC_CLK_TX_RISING 0
#define USART_CLK_TX_RISING 0
#define USARTC_CLK_TX_FALLING (1 << UCPOL0)
#define USART_CLK_TX_FALLING (USARTC << UCPOL0)
// I/O port definitions:
#define PIN_INPUT 0
#define PIN_OUTPUT 1
#define ALL_INPUTS 0
#define ALL_OUTPUTS 0xff
#define ALL_PULLUPS 0xff
#define ASDF_HIROW_PORT PORTA
#define ASDF_HIROW_DDR DDRA
#define ASDF_HIROW_PIN PINA
#define ASDF_LOROW_PORT PORTJ
#define ASDF_LOROW_DDR DDRJ
#define ASDF_LOROW_PIN PINJ
#define ASDF_COLUMNS_PORT PORTC
#define ASDF_COLUMNS_PIN PINC
#define ASDF_COLUMNS_DDR DDRC
#define ASDF_ASCII_PORT PORTH
#define ASDF_ASCII_DDR DDRH
#define ASDF_LED1_PORT PORTD
#define ASDF_LED1_DDR DDRD
#define ASDF_LED1_BIT 5
#define ASDF_LED2_PORT PORTD
#define ASDF_LED2_DDR DDRD
#define ASDF_LED2_BIT 6
#define ASDF_LED3_PORT PORTD
#define ASDF_LED3_DDR DDRD
#define ASDF_LED3_BIT 7
#define ASDF_OUT1_PORT PORTB
#define ASDF_OUT1_PIN PINB
#define ASDF_OUT1_DDR DDRB
#define ASDF_OUT1_BIT 5
#define ASDF_OUT2_PORT PORTB
#define ASDF_OUT2_PIN PINB
#define ASDF_OUT2_DDR DDRB
#define ASDF_OUT2_BIT 6
#define ASDF_OUT3_PORT PORTB
#define ASDF_OUT3_PIN PINB
#define ASDF_OUT3_DDR DDRB
#define ASDF_OUT3_BIT 7
#define ASDF_STROBE_PORT PORTB
#define ASDF_STROBE_PIN PINB
#define ASDF_STROBE_DDR DDRB
#define ASDF_STROBE_BIT 4
#define ASDF_OSI_KBE_PORT ASDF_HIROW_PORT
#define ASDF_OSI_KBE_DDR ASDF_HIROW_DDR
#define ASDF_OSI_KBE_BIT 1
#define ASDF_OSI_RW_PORT ASDF_HIROW_PORT
#define ASDF_OSI_RW_DDR ASDF_HIROW_DDR
#define ASDF_OSI_RW_BIT 2
#define ASDF_ARCH_DIP_SWITCH_ROW 8
#define FUSE_INTERNAL_8MHZ_OSC_4MS (FUSE_CKSEL1 | FUSE_SUT0)
#define FUSE_INTERNAL_8MHZ_OSC_65MS (FUSE_CKSEL1 | FUSE_SUT1)
#define FUSE_XTAL_16MHZ_4MS (FUSE_CKSEL2 | FUSE_CKSEL1 | CKSEL0 | FUSE_SUT1)
#define FUSE_XTAL_16MHZ_65MS (FUSE_CKSEL2 | FUSE_CKSEL1 | CKSEL0 | FUSE_SUT1 | FUSE_SUT0)
#define FLASH PROGMEM
// not implemented with do-while(0) because this is a function call that returns
// a value, and parameters are expanded inside the parameter list, so this will
// be valid when substituting for function-like syntax.
#define FLASH_READ (a) pgm_read_byte((a))
#define FLASH_READ_MATRIX_ELEMENT(matrix, row, col) pgm_read_byte(&((matrix)[(row)][(col)]))
// For 1 ms tick, (16000000 / 64(prescale)) / 1000(usec) - 1 = 249
#define TICK_COUNT 249
// Default key matrix row scanner
#define ASDF_ARCH_DEFAULT_SCANNER &asdf_arch_read_row
// Default keyboard output
#define ASDF_ARCH_DEFAULT_OUTPUT &asdf_arch_send_code
// DIP switch is on row 8
#define ASDF_ARCH_DIPSWITCH_ROW 8
// PROCEDURE: asdf_arch_pos_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output to positive polarity. Initial state is
// LOW
void asdf_arch_set_pos_strobe(void);
// PROCEDURE: asdf_arch_neg_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output
void asdf_arch_set_neg_strobe(void);
// PROCEDURE: asdf_arch_null_output
// INPUTS: (uint8_t) value - ignored
// OUTPUTS: none
// DESCRIPTION: null/dummy output function
// NOTES: Not supported for the ATMega-328 ASCII interface.
void asdf_arch_null_output(uint8_t value);
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
void asdf_arch_led1_set(uint8_t value);
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
void asdf_arch_led2_set(uint8_t value);
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
void asdf_arch_led3_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
void asdf_arch_out1_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out1_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out1_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
void asdf_arch_out2_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false.
// NOTES: Not supported for the ATMega-328 ASCII interface.
void asdf_arch_out2_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit to high if value is true, and hi-z if value is false.
void asdf_arch_out2_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
void asdf_arch_out3_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out3_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out3_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
// OUTPUTS: returns a word containing the active (pressed) columns
// DESCRIPTION: Outputs the argument to the ROW port, then reads the column port
// and returns the value. The value is a binary representation of the keys
// pressed within the row, with 1=pressed, 0=released.
asdf_cols_t asdf_arch_read_row(uint8_t row);
// PROCEDURE: asdf_arch_pulse_delay_short
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by
// ASDF_PULSE_DELAY_SHORT_US
void asdf_arch_pulse_delay_short(void);
// PROCEDURE: asdf_arch_pulse_delay_long
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by
// ASDF_PULSE_DELAY_LONG_MS
void asdf_arch_pulse_delay_long(void);
// PROCEDURE: asdf_arch_delay_ms
// INPUTS: (uint16) delay_ms - the delay in msec.
// OUTPUTS: none
// DESCRIPTION: Delays a specified number of milliseconds
void asdf_arch_delay_ms(uint16_t delay_ms);
// PROCEDURE: asdf_arch_tick
// INPUTS: none
// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise
uint8_t asdf_arch_tick(void);
// PROCEDURE: asdf_arch_send_code
// INPUTS: (keycode_t) code - the code to be output by the keyboard
// OUTPUTS: none
// DESCRIPTION: Takes a character code and outputs the code on a parallel ASCII
// port, with a strobe. This routine could be replaced with UART, I2C, USB, or
// other output mechanism, of course.
void asdf_arch_send_code(asdf_keycode_t code);
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: sets up all the hardware for the keyboard
void asdf_arch_init(void);
#endif /* !defined (ASDF_ARCH_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,838 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch.c
//
// This file contains all the architecture dependent code, including register
// setup, I/O, timers, etc.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// Wiring Information:
// Chip: {Microcontroller type and version}
//
// Example:
// PIN NAME FUNCTION
// 14-19,9,10 PORTB COLUMN inputs (1 bit per column)
// 23-25 PORTC0-2 ROW outputs (row number)
// 27 PORTC4
#include "asdf_arch.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
#include "asdf.h"
#include "asdf_config.h"
static volatile uint8_t tick = 0;
static uint8_t data_polarity = ASDF_DEFAULT_DATA_POLARITY;
// PROCEDURE: ISR for Timer 0 overflow
// INPUTS: none
// OUTPUTS:none
//
// DESCRIPTION: Occurs every 1 ms. Set tick flag, kick watchdog.
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
ISR(TIMER0_COMPA_vect)
{
tick = 1;
}
// PROCEDURE: set_bit
// INPUTS: port: pointer to a (uint8) port
// bit: bit position to be set
// OUTPUTS: none
//
// DESCRIPTION: Give a port address and bit position, set the bit position.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES: Declared inline. Will only be inlined for functions in this module, so
// also declared static.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static inline void set_bit(volatile uint8_t *port, uint8_t bit)
{
*port |= (1 << bit);
}
// PROCEDURE: clear_bit
// INPUTS: port: pointer to a (uint8) port
// bit: bit position to be cleared
// OUTPUTS: none
//
// DESCRIPTION: Give a port address and bit position, clear the bit position.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES: Declared inline. Will only be inlined for functions in this module, so
// also declared static.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static inline void clear_bit(volatile uint8_t *port, uint8_t bit)
{
*port &= ~(1 << bit);
}
// PROCEDURE: arch_timer0_config
//
// INPUTS: bits: a 4 byte field containing the configuration values for the
// 8-bit timer0 A and B control registers, and the interrupt mask register.
//
// OUTPUTS: none
//
// DESCRIPTION: Takes a 4 byte value with settings for all the control
// registers for the 8-bit counter/timer (timer 0), and writes them all
// to the respective registers.
//
// SIDE EFFECTS: see above
//
// NOTES: Setting all the bits together, and writing all the registers from a
// single word permits more clear initialization of control fields that are
// spread across more than one word.
//
// COMPLEXITY: 1
//
// SCOPE: private
//
static void arch_timer0_config(uint32_t bits)
{
TCCR0B = 0; // first turn off timer.
TCCR0A = (bits >> TMR0A_POS) & 0xff;
TIMSK0 = (bits >> TMR0IMSK_POS) & 0xff;
TCCR0B = (bits >> TMR0B_POS) & 0xff; // Set the mode (and turn on timer) last
}
// PROCEDURE: arch_tick_timer_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up 1ms tick timer.
//
// SIDE EFFECTS:
//
// NOTES: Set up Timer 0 in CTC mode for 1 ms overflow.
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_tick_timer_init(void)
{
tick = 0;
// set compare register first, so timer can operate correctly as soon as it is
// enabled.
OCR0A = TICK_COUNT;
// operate in CTC mode to overflow at exactly 1 ms
// prescaler = 64 and output compare value is 250
arch_timer0_config(TIMER0_WFM_CTC | TIMER0_DIV64 | TIMER0_INT_ON_COMA);
}
// PROCEDURE: asdf_arch_tick
// INPUTS: none
// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise
//
// DESCRIPTION: See Outputs.
//
// SIDE EFFECTS: Zeroes out the 1 ms timer flag.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
uint8_t asdf_arch_tick(void)
{
uint8_t retval = tick;
tick = 0;
return retval;
}
// PROCEDURE: asdf_arch_init_timers
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up timer for 1 ms intervals
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_clock(void)
{
CLKPR = (CLKPCE | SYSCLK_DIV1);
}
// PROCEDURE: asdf_arch_init_outputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize all LED ports as outputs. Values are not set here.
// They are set by the keymap code
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_leds(void)
{
set_bit(&ASDF_LED1_DDR, ASDF_LED1_BIT);
set_bit(&ASDF_LED2_DDR, ASDF_LED2_BIT);
set_bit(&ASDF_LED3_DDR, ASDF_LED3_BIT);
}
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED1 port drives the LED directly by pulling the cathode low, so
// clearing the bit turns the LED on.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led1_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
}
else {
set_bit(&ASDF_LED1_PORT, ASDF_LED1_BIT);
}
}
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED2 output drives the LED via an inverter buffer, so a high
// output pulls the LED cathode low, lighting the LED.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led2_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
}
else {
clear_bit(&ASDF_LED2_PORT, ASDF_LED2_BIT);
}
}
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
//
// SIDE EFFECTS: See above.
//
// NOTES: The LED3 output drives the LED via an inverter buffer, so a high
// output pulls the LED cathode low, lighting the LED.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_led3_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
}
else {
clear_bit(&ASDF_LED3_PORT, ASDF_LED3_BIT);
}
}
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
else {
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
// PROCEDURE: asdf_arch_out1_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_open_hi_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
else {
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
}
// PROCEDURE: asdf_arch_out1_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit to high if value is true, and hi-z if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out1_open_lo_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
set_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
}
else {
clear_bit(&ASDF_OUT1_DDR, ASDF_OUT1_BIT);
clear_bit(&ASDF_OUT1_PORT, ASDF_OUT1_BIT);
}
}
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES: OUT2 is inverted by the 7404 buffer, so clearing the bit sets the output high. OUT2
// cannot be high impedance.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
}
else {
set_bit(&ASDF_OUT2_PORT, ASDF_OUT2_BIT);
}
set_bit(&ASDF_OUT2_DDR, ASDF_OUT2_BIT);
}
// PROCEDURE: asdf_arch_null_output
// INPUTS: (uint8_t) value - ignored
// OUTPUTS: none
//
// DESCRIPTION: Does nothing.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_null_output(uint8_t value)
{
(void) value;
}
// PROCEDURE: asdf_arch_out2_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES: Not supported for the ATMega-328 ASCII interface.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_open_hi_set(uint8_t value)
{
asdf_arch_null_output(value);
}
// PROCEDURE: asdf_arch_out2_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit to high if value is true, and hi-z if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES: Not supported for the ATMega-328 ASCII interface.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_open_lo_set(uint8_t value)
{
asdf_arch_null_output(value);
}
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
else {
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
// PROCEDURE: asdf_arch_out3_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_open_hi_set(uint8_t value)
{
if (value) {
clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
else {
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
}
// PROCEDURE: asdf_arch_out3_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit to high if value is true, and hi-z if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out3_open_lo_set(uint8_t value)
{
if (value) {
set_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
set_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
}
else {
clear_bit(&ASDF_OUT3_DDR, ASDF_OUT3_BIT);
clear_bit(&ASDF_OUT3_PORT, ASDF_OUT3_BIT);
}
}
// PROCEDURE: asdf_arch_pos_strobe
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize strobe output to positive polarity. Initial state is
// LOW
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_set_pos_strobe(void)
{
clear_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT);
set_bit(&ASDF_STROBE_DDR, ASDF_STROBE_BIT);
}
// PROCEDURE: asdf_arch_neg_strobe
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize strobe output
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
void asdf_arch_set_neg_strobe(void)
{
set_bit(&ASDF_STROBE_PORT, ASDF_STROBE_BIT);
set_bit(&ASDF_STROBE_DDR, ASDF_STROBE_BIT);
}
// PROCEDURE: asdf_arch_init_ascii_output
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up output port for ASCII output
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_ascii_output(void)
{
// set all outputs
ASDF_ASCII_PORT = data_polarity;
ASDF_ASCII_DDR = ALL_OUTPUTS;
}
// PROCEDURE: asdf_arch_init_column_inputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: configure the shift register control lines. The MODE control is
// LOW for shift and HIGH for load. Shift or Load occurs when CLK goes high.
//
// SIDE EFFECTS: Cont
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_column_control(void)
{
// COLCLK is output and initialized LOW
clear_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
set_bit(&ASDF_COLCLK_DDR, ASDF_COLCLK_BIT);
// COLMODE is output and initialized HIGH
set_bit(&ASDF_COLMODE_PORT, ASDF_COLMODE_BIT);
set_bit(&ASDF_COLMODE_DDR, ASDF_COLMODE_BIT);
// COL is input, no weak pullup.
clear_bit(&ASDF_COL_DDR, ASDF_COL_BIT);
clear_bit(&ASDF_COL_PORT, ASDF_COL_BIT);
}
// PROCEDURE: asdf_arch_init_row_outputs
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Sets up output port to latch keyboard matrix row for scanning.
//
// SIDE EFFECTS: See DESCRIPTION
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void asdf_arch_init_row_outputs(void)
{
ASDF_ROW_PORT &= ~ASDF_ROW_MASK;
ASDF_ROW_DDR |= ASDF_ROW_MASK;
}
// PROCEDURE: asdf_arch_pulse_delay_short
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by ASDF_PULSE_DELAY_SHORT_US
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_pulse_delay_short(void)
{
_delay_us(ASDF_PULSE_DELAY_SHORT_US);
}
// PROCEDURE: asdf_arch_pulse_delay_long
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by ASDF_PULSE_DELAY_LONG_MS
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_pulse_delay_long(void)
{
_delay_ms(ASDF_PULSE_DELAY_LONG_MS);
}
// PROCEDURE: asdf_arch_delay_ms
// INPUTS: (uint16) delay_ms - the delay in msec.
// OUTPUTS: none
//
// DESCRIPTION: Delays a specified number of milliseconds
//
// SIDE EFFECTS: see above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_delay_ms(uint16_t delay_ms)
{
for (uint16_t i=0; i < delay_ms; i++) {
_delay_ms(1);
}
}
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets up all the hardware for the keyboard
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_init(void)
{
// disable interrupts:
cli();
// clear the 1ms timer flag;
tick = 0;
// set up timers for 1 msec intervals
asdf_arch_init_clock();
asdf_arch_tick_timer_init();
// set up ASCII output port
asdf_arch_init_ascii_output();
// initialize keyboard data polarity and strobe polarity
data_polarity = ASDF_DEFAULT_DATA_POLARITY;
if (ASDF_DEFAULT_STROBE_POLARITY == ASDF_POSITIVE_POLARITY) {
asdf_arch_set_pos_strobe();
} else {
asdf_arch_set_neg_strobe();
}
asdf_arch_init_leds();
asdf_arch_init_leds();
// set up row output port
asdf_arch_init_row_outputs();
// set up column control lines
asdf_arch_init_column_control();
// enable interrupts:
sei();
}
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
// OUTPUTS: returns a word containing the active (pressed) columns
//
// DESCRIPTION: Outputs the argument to the ROW port, then reads the column port
// and returns the value. The value is a binary representation of the keys
// pressed within the row, with 1=pressed, 0=released.
//
// SIDE EFFECTS: Sets ROW output port.
//
// NOTES:
//
// 1) The keymap represents an unpressed key as a "0" and a pressed key as a
// "1". So, if a keypress pulls the column line low, then the reading of the
// physical bits must be inverted.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
asdf_cols_t asdf_arch_read_row(uint8_t row)
{
asdf_cols_t cols = 0;
// first, output the new row value:
ASDF_ROW_PORT = (ASDF_ROW_PORT & ~ASDF_ROW_MASK)
| ((row & ASDF_ROW_MASK) << ASDF_ROW_OFFSET);
// read in the columns. Set LOAD mode and pulse clock.
clear_bit(&ASDF_COLMODE_PORT, ASDF_COLMODE_BIT);
set_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
clear_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
// set back to SHIFT mode
set_bit(&ASDF_COLMODE_PORT, ASDF_COLMODE_BIT);
// After the load operation, the LSB is already at the output pin, so there
// will be one fewer read than clock pulse. Continue reading the bits until
// the leader bit is in the boundary position.
for (uint8_t i = 0; i < ASDF_MAX_COLS; i++) {
// invert the bits as they are read (see note 1)
cols |= (((~(ASDF_COL_PIN) >> ASDF_COL_BIT) & 1) << i);
set_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
clear_bit(&ASDF_COLCLK_PORT, ASDF_COLCLK_BIT);
}
return cols;
}
// PROCEDURE: asdf_arch_send_code
// INPUTS: (keycode_t) code - the 7-bit ASCII code to be output by the keyboard
// OUTPUTS: none
//
// DESCRIPTION: Takes a character code and outputs the code on a parallel ASCII
// port, with a strobe. This routine could be replaced with UART, I2C, USB, or
// other output mechanism, of course.
//
// SIDE EFFECTS: See above.
//
// NOTES: The strobe is set by the ASDF_STROBE_LENGTH definition. The data
// output and strobe polarity are set by the static data_polarity and static
// strobe_polarity variables.
//
// SCOPE:
//
// COMPLEXITY:
//
void asdf_arch_send_code(asdf_keycode_t code)
{
ASDF_ASCII_PORT = (code ^ data_polarity);
// toggle strobe. Must test before setting to avoid spurious strobe
set_bit(&ASDF_STROBE_PIN, ASDF_STROBE_BIT);
_delay_us(ASDF_STROBE_LENGTH_US);
set_bit(&ASDF_STROBE_PIN, ASDF_STROBE_BIT);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.
//

View File

@ -1,407 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch_atmega328p.h
//
// Contains architecture-specific definitions for the atmega 328p.
//
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
#if !defined(ASDF_ARCH_H)
#define ASDF_ARCH_H
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "asdf.h"
// ASDF keyboard definitions:
#define F_CPU 8000000L
#define ASDF_STROBE_LENGTH_US 10 // strobe length in microseconds
// Clock definitions:
#define SYSCLK_DIV1 0
#define SYSCLK_DIV2 (CLKPS0)
#define SYCCLK_DIV4 (CLKPS1)
#define SYSCLK_DIV8 (CLKPS1 | CLKPS0)
#define SYSCLK_DIV16 (CLKPS2)
#define SYSCLK_DIV32 (CLKPS2 | CLKPS0)
#define SYSCLK_DIV64 (CLKPS2 | CLKPS1)
#define SYSCLK_DIV128 (CLKPS2 | CLKPS1 | CLKPS0)
#define SYSCLK_DIV256 (CLKPS3)
// Define fields for register A, B, interrupt mask as 8-bit masks, and
// as masks offset into a combined config word
#define TMR0A_POS 0
#define TMR0B_POS 8
#define TMR0IMSK_POS 16
#define TMR0A (1L << TMR0A_POS)
#define TMR0B (1L << TMR0B_POS)
#define TMR0IMSK (1L << TMR0IMSK_POS)
#define TIMER0_COM_A_DISCONNECTED 0
#define TIMER0_COM_B_DISCONNECTED 0
#define TIMER0_WFM_CTC (TMR0A << WGM01)
#define TIMER0_DIV64 ((TMR0B << CS01) | (TMR0B << CS00))
#define TIMER0_INT_ON_COMA (TMR0IMSK << OCIE0A)
#define TIMER0_INT_ON_COMB (TMR0IMSK << OCIE0B)
#define TIMER0_INT_OV_ENABLE (TMR0IMSK << TOIE0)
// Macros for 16-bit timer 1. ATmega328P datasheet section 15, p. 108
//
// Define fields for Registers A, B, C, INT Mask registers as 8-bit
// masks, and as masks offset into a 32-bit combined config word.
//
// Macro definitions for individual registers are named TMR1A_*,
// TMR1B_*, and TMR1C_*.
//
// Macros for the one-step combined timer config functions are named
// TMR1_*.
//
//
// Examples:
// // Use TMR1B_* definition to set TCCR1B register
// TCCR1B |= TMR1B_DIV1;
//
// // Use TMR1_* definitions to configure timer with config function
// timer1_config(TMR1_WFM_CTC | TMR1_INT_ON_CMPA);
//
#define TMR1A_POS 0
#define TMR1B_POS 8
#define TMR1C_POS 16
#define TMR1IMSK_POS 24
#define TMR1A (1L << TMR1A_POS)
#define TMR1B (1L << TMR1B_POS)
#define TMR1C (1L << TMR1C_POS)
#define TMR1IMSK (1L << TMR1IMSK_POS)
// 16-bit timer reg A - Datasheet 17.11.1, p. 154
#define TMR1A_CMPA_CLR_MATCH_SET_BOTTOM (1 << COM1A1)
#define TMR1A_CMPB_CLR_MATCH_SET_BOTTOM (1 << COM1B1)
#define TMR1A_CMPC_CLR_MATCH_SET_BOTTOM (1 << COM1C1)
#define TMR1_CMPA_CLR_MATCH_SET_BOTTOM (TMR1A << COM1A1)
#define TMR1_CMPB_CLR_MATCH_SET_BOTTOM (TMR1A << COM1B1)
#define TMR1_CMPC_CLR_MATCH_SET_BOTTOM (TMR1A << COM1C1)
// 16-bit timer reg B - Datasheet 17.11.6, p. 156
#define TMR1B_IN_CAP_POS 0x40L
#define TMR1B_IN_CAP_NEG 0L
#define TMR1B_IN_CAP_NOISE_CANCEL 0x80L
// 16-bit timer reg C -- see datasheet, 17.11.9, p. 157
#define TMR1C_FOCA 0x80L
#define TMR1C_FOCB 0x40L
#define TMR1C_FOCC 0x20L
// 16-bit timer int mask -- see datasheet 17.11.33, p. 161.
#define TMR1IM_INT_CMP_MATCH_A (1L << OCIE1A)
#define TMR1IM_INT_CMP_MATCH_B (1L << OCIE1B)
#define TMR1IM_INT_CMP_MATCH_C (1L << OCIE1C)
// 16-bit timer all registers:
#define TMR1_CMPA_DISCONNECTED 0L
#define TMR1_CMPB_DISCONNECTED 0L
#define TMR1_CMPC_DISCONNECTED 0L
#define TMR1_INT_ON_CMPA (TMR1IM_INT_CMP_MATCH_A << TMR1IMSK_POS)
// 16-bit timer clock modes - see Datasheet table 17-6, p. 157
#define TMR1B_OFF 0
#define TMR1_OFF 0
#define TMR1B_DIV1 (0x01L << CS10)
#define TMR1B_DIV8 (0x02L << CS10)
#define TMR1B_DIV64 (0x03L << CS10)
#define TMR1B_DIV256 (0x04L << CS10)
#define TMR1B_DIV1024 (0x05L << CS10)
#define TMR1B_EXT_FALLING_EDGE (0x06L << CS10)
#define TMR1B_EXT_RISING_EDGE (0x07L << CS10)
#define TMR1B_CLK_MASK 0x07L
#define TMR1_DIV1 (TMR1B_DIV1 << TMR1B_POS)
#define TMR1_DIV8 (TMR1B_DIV8 << TMR1B_POS)
#define TMR1_DIV64 (TMR1B_DIV64 << TMR1B_POS)
#define TMR1_DIV256 (TMR1B_DIV256 << TMR1B_POS)
#define TMR1_DIV1024 (TMR1B_DIV1024 << TMR1B_POS)
#define TMR1_EXT_FALLING_EDGE (TMR1B_EXT_FALLING_EDGE << TMR1B_POS)
#define TMR1_EXT_RISING_EDGE (TMR1B_EXT_RISING_EDGE << TMR1B_POS)
#define TMR1B_EDGE_SEL_POSITIVE (1 << ICES1)
#define TMR1B_EDGE_SEL_NEGATIVE 0L
#define TMR1_EDGE_SEL_POSITIVE (TMR1B << ICES1)
#define TMR1_EDGE_SEL_NEGATIVE 0L
// 16-bit waveform modes (across reg A and B) Datasheet Table 17.2, p 145
#define TMR1_WFM_NORMAL 0L
#define TMR1_WFM_PWM_PC8 (TMR1A << WGM10) // PWM Phase Correct 8-bit
#define TMR1_WFM_PWM_PC9 (TMR1A << WGM11) // PWM Phase COrrect 9-bit
#define TMR1_WFM_PWM_PC10 ((TMR1A << WGM11) | (TMR1A << WGM10)) // PWM Phase Correct 10-bit
#define TMR1_WFM_CTC (TMR1B << WGM12) // CTC
#define TMR1_WFM_PWM_FAST8 ((TMR1B << WGM12) | (TMR1A << WGM10)) // PWM Fast 8-bit
#define TMR1_WFM_PWM_FAST9 ((TMR1B << WGM12) | (TMR1A << WGM11)) // PWM Fast 9-bit
#define TMR1_WFM_PWM_FAST10 \
((TMR1B << WGM12) | (TMR1A << WGM11) | (TMR1A << WGM10)) // PWM Fast 10-bit
#define TMR1_WFM_PWM_PFC_ICR (TMR1B << WGM13) // PWM Phase and Freq Correct, TpOP=ICR
#define TMR1_WFM_PWM_PFC_OCRA \
((TMR1B << WGM13) | (TMR1A << WGM10)) // PWM Phase and Freq Correct, TOP = OCRA
#define TMR1_WFM_PWM_PC_ICR ((TMR1B << WGM13) | (TMR1A << WGM11)) // PWM PhaseCorrect, TOP = ICR
#define TMR1_WFM_PWM_PC_OCRA \
((TMR1B << WGM13) | (TMR1A << WGM11) | (TMR1A << WGM12)) // PWM PhaseCorrect, TOP=OCRA
#define TMR1_WFM_CTC_ICR ((TMR1B << WGM13) | (TMR1B << WGM12)) // CTC, TOP = ICR
#define TMR1_WFM_PWM_FAST_ICR \
((TMR1B << WGM13) | (TMR1B << WGM12) | (TMR1A << WGM11)) // PWM Fast, TOP = ICR
#define TMR1_WFM_PWM_FAST_OCRA \
((TMR1B << WGM13) | (TMR1B << WGM12) | (TMR1A << WGM11) \
| (TMR1A << WGM10)) // PWM Fast, TOP = OCRA
// I/O port definitions:
#define PIN_INPUT 0
#define PIN_OUTPUT 1
#define ALL_INPUTS 0
#define ALL_OUTPUTS 0xff
#define ASDF_ROW_PORT PORTC
#define ASDF_ROW_DDR DDRC
#define ASDF_ROW_MASK 0x0f
#define ASDF_ROW_OFFSET 0
#define ASDF_COL_PORT PORTB
#define ASDF_COL_PIN PINB
#define ASDF_COL_DDR DDRB
#define ASDF_COL_BIT 0
#define ASDF_COL_PULLUPS 0 // disable weak pullup
#define ASDF_COLCLK_PORT PORTB
#define ASDF_COLCLK_PINS PINB
#define ASDF_COLCLK_DDR DDRB
#define ASDF_COLCLK_BIT 2
#define ASDF_COLMODE_PORT PORTB
#define ASDF_COLMODE_PINS PINB
#define ASDF_COLMODE_DDR DDRB
#define ASDF_COLMODE_BIT 1
#define ASDF_ASCII_PORT PORTD
#define ASDF_ASCII_DDR DDRD
#define ASDF_LED1_PORT PORTC
#define ASDF_LED1_DDR DDRC
#define ASDF_LED1_BIT 4
#define ASDF_LED2_PORT PORTB
#define ASDF_LED2_DDR DDRB
#define ASDF_LED2_BIT 5
#define ASDF_LED3_PORT PORTB
#define ASDF_LED3_DDR DDRB
#define ASDF_LED3_BIT 4
#define ASDF_OUT1_PORT PORTC
#define ASDF_OUT1_PIN PINC
#define ASDF_OUT1_DDR DDRC
#define ASDF_OUT1_BIT 5
#define ASDF_OUT2_PORT PORTB
#define ASDF_OUT2_PIN PINB
#define ASDF_OUT2_DDR DDRB
#define ASDF_OUT2_BIT 3
#define ASDF_OUT3_PORT PORTB
#define ASDF_OUT3_PIN PINB
#define ASDF_OUT3_DDR DDRB
#define ASDF_OUT3_BIT 7
#define ASDF_STROBE_PORT PORTB
#define ASDF_STROBE_PIN PINB
#define ASDF_STROBE_DDR DDRB
#define ASDF_STROBE_BIT 6
#define ASDF_ARCH_DIP_SWITCH_ROW 8
#define FUSE_INTERNAL_8MHZ_OSC_0MS (FUSE_CKSEL0 | FUSE_CKSEL2 | FUSE_CKSEL3 | FUSE_SUT0 | FUSE_SUT1)
#define FUSE_INTERNAL_8MHZ_OSC_4MS (FUSE_CKSEL0 | FUSE_CKSEL2 | FUSE_CKSEL3 | FUSE_SUT1)
#define FUSE_INTERNAL_8MHZ_OSC_65MS (FUSE_CKSEL0 | FUSE_CKSEL2 | FUSE_CKSEL3 | FUSE_SUT0)
#define FLASH PROGMEM
// not implemented with do-while(0) because this is a function call that returns
// a value, and parameters are expanded inside the parameter list, so this will
// be valid when substituting for function-like syntax.
#define FLASH_READ (a) pgm_read_byte((a))
#define FLASH_READ_MATRIX_ELEMENT(matrix, row, col) pgm_read_byte(&((matrix)[(row)][(col)]))
// For 1 ms tick, (8000000 / 64(prescale)) / 1000(usec) - 1 = 124
#define TICK_COUNT 124
// Default key matrix row scanner
#define ASDF_ARCH_DEFAULT_SCANNER asdf_arch_read_row
// Default keyboard output
#define ASDF_ARCH_DEFAULT_OUTPUT asdf_arch_send_code
// DIP switch is on row 8
#define ASDF_ARCH_DIPSWITCH_ROW 8
// PROCEDURE: asdf_arch_pos_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output to positive polarity. Initial state is
// LOW
void asdf_arch_set_pos_strobe(void);
// PROCEDURE: asdf_arch_neg_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output
void asdf_arch_set_neg_strobe(void);
// PROCEDURE: asdf_arch_null_output
// INPUTS: (uint8_t) value - ignored
// OUTPUTS: none
// DESCRIPTION: null/dummy output function
// NOTES: Not supported for the ATMega-328 ASCII interface.
void asdf_arch_null_output(uint8_t value);
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
void asdf_arch_led1_set(uint8_t value);
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
void asdf_arch_led2_set(uint8_t value);
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
void asdf_arch_led3_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
void asdf_arch_out1_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out1_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out1_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
void asdf_arch_out2_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit to hi-z if value is true, and low if value is false.
// NOTES: Not supported for the ATMega-328 ASCII interface.
void asdf_arch_out2_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit to high if value is true, and hi-z if value is false.
void asdf_arch_out2_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
void asdf_arch_out3_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out3_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit to hi-z if value is true, and low if value is false.
void asdf_arch_out3_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
// OUTPUTS: returns a word containing the active (pressed) columns
// DESCRIPTION: Outputs the argument to the ROW port, then reads the column port
// and returns the value. The value is a binary representation of the keys
// pressed within the row, with 1=pressed, 0=released.
asdf_cols_t asdf_arch_read_row(uint8_t row);
// PROCEDURE: asdf_arch_pulse_delay_short
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by ASDF_PULSE_DELAY_SHORT_US
void asdf_arch_pulse_delay_short(void);
// PROCEDURE: asdf_arch_pulse_delay_long
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Delays a fixed amount of time for keyboard output pulses specified by ASDF_PULSE_DELAY_LONG_MS
void asdf_arch_pulse_delay_long(void);
// PROCEDURE: asdf_arch_delay_ms
// INPUTS: (uint16) delay_ms - the delay in msec.
// OUTPUTS: none
// DESCRIPTION: Delays a specified number of milliseconds
void asdf_arch_delay_ms(uint16_t delay_ms);
// PROCEDURE: asdf_arch_tick
// INPUTS: none
// OUTPUTS: returns a 1 if the 1ms timer timed out, 0 otherwise
uint8_t asdf_arch_tick(void);
// PROCEDURE: asdf_arch_send_code
// INPUTS: (keycode_t) code - the code to be output by the keyboard
// OUTPUTS: none
// DESCRIPTION: Takes a character code and outputs the code on a parallel ASCII
// port, with a strobe. This routine could be replaced with UART, I2C, USB, or
// other output mechanism, of course.
void asdf_arch_send_code(asdf_keycode_t code);
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: sets up all the hardware for the keyboard
void asdf_arch_init(void);
#endif /* !defined (ASDF_ARCH_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,623 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch.c
//
// This file contains all the architecture dependent code, including register
// setup, I/O, timers, etc.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// Wiring Information:
// Chip: {Microcontroller type and version}
//
// Example:
// PIN NAME FUNCTION
// 14-19,9,10 PORTB COLUMN inputs (1 bit per column)
// 23-25 PORTC0-2 ROW outputs (row number)
// 27 PORTC4
#include <stdio.h>
#include <stdint.h>
#include "asdf_config.h"
#include "asdf_physical.h"
#include "asdf_arch.h"
typedef enum {
PULSE_EVENT_SET_HIGH,
PULSE_EVENT_SET_LOW,
PULSE_EVENT_DELAY,
NUM_PULSE_EVENTS
} pulse_event_t;
static pulse_state_t pulse_transition_table[PD_ST_NUM_VALID_PULSE_STATES][NUM_PULSE_EVENTS] =
{
[PD_ST_INITIAL_STATE] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_STABLE_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_STABLE_LOW,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_PULSE_FROM_INITIAL_STATE,
},
[PD_ST_STABLE_LOW] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_TRANSITION_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_STABLE_LOW,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_NO_TRANSITION_BEFORE_DELAY,
},
[PD_ST_STABLE_HIGH] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_STABLE_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_TRANSITION_LOW,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_NO_TRANSITION_BEFORE_DELAY,
},
[PD_ST_TRANSITION_LOW] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_TRANSITION_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_STABLE_LOW,
[PULSE_EVENT_DELAY] = PD_ST_PULSE_DELAY_LOW,
},
[PD_ST_TRANSITION_HIGH] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_STABLE_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_TRANSITION_LOW,
[PULSE_EVENT_DELAY] = PD_ST_PULSE_DELAY_HIGH,
},
[PD_ST_PULSE_DELAY_LOW] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_PULSE_LOW_DETECTED,
[PULSE_EVENT_SET_LOW] = PD_ST_ERROR_NO_TRANSITION_AFTER_DELAY,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_DOUBLE_DELAY,
},
[PD_ST_PULSE_DELAY_HIGH] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_ERROR_NO_TRANSITION_AFTER_DELAY,
[PULSE_EVENT_SET_LOW] = PD_ST_PULSE_HIGH_DETECTED,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_DOUBLE_DELAY,
},
[PD_ST_PULSE_HIGH_DETECTED] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_TRANSITION_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_STABLE_LOW,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_NO_TRANSITION_BEFORE_DELAY
},
[PD_ST_PULSE_LOW_DETECTED] =
{
[PULSE_EVENT_SET_HIGH] = PD_ST_STABLE_HIGH,
[PULSE_EVENT_SET_LOW] = PD_ST_TRANSITION_LOW,
[PULSE_EVENT_DELAY] = PD_ST_ERROR_NO_TRANSITION_BEFORE_DELAY
},
};
static uint8_t outputs[ASDF_PHYSICAL_NUM_RESOURCES];
static pulse_state_t pulses[ASDF_PHYSICAL_NUM_RESOURCES];
static asdf_keycode_t code_register;
static uint8_t code_sent;
// PROCEDURE: asdf_arch_send_code
// INPUTS: asdf_keycode_t code
// OUTPUTS: none
// DESCRIPTION: emulates sending a code, by copying code to a register that can
// be tested.
//
// SIDE_EFFECTS: sets code_sent variable and alters code_register
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_send_code(asdf_keycode_t code)
{
code_register = code;
code_sent = 1;
}
// PROCEDURE: asdf_arch_get_sent_code
// INPUTS: none
// OUTPUTS: returns type (asdf_keycode_t) in register and zeros the register.
// DESCRIPTION: faciliates test of sending a code, by reporting contents of the
// "sent register". Resets code_sent variable.
//
// SIDE_EFFECTS: alters code_sent variable
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
asdf_keycode_t asdf_arch_get_sent_code(void)
{
code_sent = 0;
return code_register;
}
// PROCEDURE: asdf_arch_was_code_sent
// INPUTS: none
// OUTPUTS: returns TRUE if a code was sent, FALSE otherwise.
// DESCRIPTION: returns status of code_sent variable.
//
// SIDE_EFFECTS: sets code_sent variable and alters code_register
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
uint8_t asdf_arch_was_code_sent(void){
return code_sent;
}
// PROCEDURE: pulse_detect
// INPUTS: (pulse_state_t) current_state
// (pulse_event_t) event - current input to the state machine
// OUTPUTS: returns new pulse detector state for the output.
//
// DESCRIPTION: Given an output and a new value for the output, calculate the
// next state of the pulse detector for the output.
//
// SIDE EFFECTS: none.
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 2
//
static pulse_state_t pulse_detect(pulse_state_t current_state, pulse_event_t event)
{
pulse_state_t next_state = current_state;
// advance state if current state is valid (not an error state)
if (current_state < PD_ST_NUM_VALID_PULSE_STATES) {
next_state = pulse_transition_table[current_state][event];
}
return next_state;
}
// PROCEDURE: set_output
// INPUTS: (asdf_physical_dev_t) output_dev - the output to set
// (uint8_t) value - value to assert on the output
// OUTPUTS: none
//
// DESCRIPTION: Given an output and a new value for the output, set the output
// and advance the pulse detector state for the output.
//
// SIDE EFFECTS: see above.
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void set_output(asdf_physical_dev_t output_dev, uint8_t value)
{
pulse_event_t pulse_event = value ? PULSE_EVENT_SET_HIGH : PULSE_EVENT_SET_LOW;
outputs[output_dev] = value;
pulses[output_dev] = pulse_detect(pulses[output_dev], pulse_event);
}
// PROCEDURE: asdf_arch_null_output
// INPUTS: (uint8_t) value - ignored
// OUTPUTS: none
//
// DESCRIPTION: Does nothing.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_null_output(uint8_t value)
{
set_output(PHYSICAL_NO_OUT, value);
}
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_led1_set(uint8_t value)
{
set_output(PHYSICAL_LED1, value);
}
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_led2_set(uint8_t value)
{
set_output(PHYSICAL_LED2, value);
}
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_led3_set(uint8_t value)
{
set_output(PHYSICAL_LED3, value);
}
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out1_set(uint8_t value)
{
set_output(PHYSICAL_OUT1, value);
}
// PROCEDURE: asdf_arch_out1_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Emulates setting the OUT1 bit to hi-z if value is true, and low
// if value is false. For testing, set PHYSICAL_OUT1_OPEN_HI to the value.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out1_open_hi_set(uint8_t value)
{set_output(PHYSICAL_OUT1_OPEN_HI, value);
}
// PROCEDURE: asdf_arch_out1_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Emulates setting the OUT1 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT1_OPEN_LO to the value.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out1_open_lo_set(uint8_t value)
{set_output(PHYSICAL_OUT1_OPEN_HI, value);
}
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
//
// SIDE EFFECTS: See above.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
void asdf_arch_out2_set(uint8_t value)
{
set_output(PHYSICAL_OUT2, value);
}
// PROCEDURE: asdf_arch_out2_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Emulates setting the OUT2 bit to hi-z if value is true, and low
// if value is false. For testing, set PHYSICAL_OUT2_OPEN_HI to the value.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out2_open_hi_set(uint8_t value)
{set_output(PHYSICAL_OUT1_OPEN_HI, value);
}
// PROCEDURE: asdf_arch_out2_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Emulates setting the OUT2 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT2_OPEN_LO to the value.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out2_open_lo_set(uint8_t value)
{set_output(PHYSICAL_OUT1_OPEN_HI, value);
}
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out3_set(uint8_t value)
{
set_output(PHYSICAL_OUT3, value);
}
// PROCEDURE: asdf_arch_out3_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Emulates setting the OUT3 bit to hi-z if value is true, and low
// if value is false. For testing, set PHYSICAL_OUT3_OPEN_HI to the value.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out3_open_hi_set(uint8_t value)
{set_output(PHYSICAL_OUT1_OPEN_HI, value);
}
// PROCEDURE: asdf_arch_out3_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
//
// DESCRIPTION: Emulates setting the OUT3 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT3_OPEN_LO to the value.
//
// SIDE EFFECTS: See above.
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_out3_open_lo_set(uint8_t value)
{set_output(PHYSICAL_OUT1_OPEN_HI, value);
}
// PROCEDURE: asdf_arch_check_output
// INPUTS:(asdf_physical_dev_t) device - which device to check
// OUTPUTS: the value of the device setting.
//
// DESCRIPTION: For a given physical device, return the current setting (true or false)
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
uint8_t asdf_arch_check_output(asdf_physical_dev_t device)
{
return outputs[device];
}
// PROCEDURE: asdf_arch_check_pulse
// INPUTS:(asdf_physical_dev_t) device - which device to check
// OUTPUTS: the value of the device pulse detector
//
// DESCRIPTION: For a given physical device, return the state of the pulse detector
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
uint8_t asdf_arch_check_pulse(asdf_physical_dev_t device)
{
return pulses[device];
}
// PROCEDURE: asdf_arch_pulse_delay
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Emulates a delay by advancing the pulse detector state machine
// for each output.
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: private
//
// COMPLEXITY: 2
//
void asdf_arch_pulse_delay(void)
{
for (uint8_t i = 0; i < ASDF_PHYSICAL_NUM_RESOURCES; i++) {
pulses[i] = pulse_detect(pulses[i], PULSE_EVENT_DELAY);
}
}
// PROCEDURE: asdf_arch_pulse_delay_long
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Emulates a long delay by advancing the pulse detector state machine
// for each output.
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_pulse_delay_long(void)
{
asdf_arch_pulse_delay();
}
// PROCEDURE: asdf_arch_delay_ms
// INPUTS: (uint16) delay_ms - the delay in msec.
// OUTPUTS: none
//
// DESCRIPTION: Delays a specified number of milliseconds
//
// SIDE EFFECTS: see above.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_delay_ms(uint16_t delay_ms)
{
asdf_arch_pulse_delay();
}
// PROCEDURE: asdf_arch_pulse_delay_short
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Emulates a short delay by advancing the pulse detector state machine
// for each output.
//
// SIDE EFFECTS: see above.
//
// NOTES: Set ASDF_PULSE_DELAY_US in asdf_config.h
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_pulse_delay_short(void)
{
asdf_arch_pulse_delay();
}
// PROCEDURE: asdf_arch_pos_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output to positive polarity. Initial state is
// LOW
void asdf_arch_set_pos_strobe(void) {}
// PROCEDURE: asdf_arch_neg_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output
void asdf_arch_set_neg_strobe(void) {}
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: sets up all the hardware for the keyboard
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_arch_init(void)
{
for (uint8_t i = 0; i < ASDF_PHYSICAL_NUM_RESOURCES; i++) {
outputs[i] = 0;
pulses[i] = PD_ST_INITIAL_STATE;
}
// initially, no keycodes have been sent via asdf_arch_send_code:
code_sent = 0;
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.
//

View File

@ -1,236 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_arch_test.h
//
// Architecture-dependent definitions for the unit-testing ASDF software.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
#if !defined (ASDF_ARCH_H)
#define ASDF_ARCH_H
#include <stdint.h>
#include "asdf.h"
#include "asdf_config.h"
#include "asdf_physical.h"
#include "asdf_virtual.h"
typedef enum {
PD_ST_INITIAL_STATE = 0,
PD_ST_STABLE_LOW = 1,
PD_ST_STABLE_HIGH = 2,
PD_ST_TRANSITION_LOW = 3,
PD_ST_TRANSITION_HIGH = 4,
PD_ST_PULSE_DELAY_LOW = 5,
PD_ST_PULSE_DELAY_HIGH = 6,
PD_ST_PULSE_HIGH_DETECTED = 7,
PD_ST_PULSE_LOW_DETECTED = 8,
PD_ST_NUM_VALID_PULSE_STATES = 9, // error states below this
PD_ST_ERROR_DOUBLE_DELAY = 10,
PD_ST_ERROR_DOUBLE_SET = 11,
PD_ST_ERROR_NO_TRANSITION_BEFORE_DELAY = 12,
PD_ST_ERROR_NO_TRANSITION_AFTER_DELAY = 13,
PD_ST_ERROR_DOUBLE_TRANSITION = 14, // fast pulse without delay
PD_ST_ERROR_PULSE_FROM_INITIAL_STATE = 15,
} pulse_state_t;
#define FLASH
#define FLASH_READ (a) (*(a))
#define FLASH_READ_MATRIX_ELEMENT(mat,row,col) (mat)[(row)][(col)]
#define ASDF_ARCH_DEFAULT_SCANNER asdf_arch_read_row
#define ASDF_ARCH_DEFAULT_OUTPUT asdf_arch_send_code
// PROCEDURE: asdf_arch_pos_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output to positive polarity. Initial state is
// LOW
void asdf_arch_set_pos_strobe(void);
// PROCEDURE: asdf_arch_neg_strobe
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize strobe output
void asdf_arch_set_neg_strobe(void);
// PROCEDURE: asdf_arch_null_output
// INPUTS: (uint8_t) value - ignored
// OUTPUTS: none
// DESCRIPTION: Does nothing.
void asdf_arch_null_output(uint8_t value);
// PROCEDURE: asdf_arch_led1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED1. If value is false, turn off LED1
void asdf_arch_led1_set(uint8_t value);
// PROCEDURE: asdf_arch_led2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED2. If value is false, turn off LED2
void asdf_arch_led2_set(uint8_t value);
// PROCEDURE: asdf_arch_led3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: If value is true, turn on LED3. If value is false, turn off LED3
void asdf_arch_led3_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT1 bit if value is true, and clear OUT1 if value is false.
void asdf_arch_out1_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Emulates setting the OUT1 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT1_OPEN_LO to the value.
void asdf_arch_out1_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out1_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Emulates setting the OUT1 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT1_OPEN_LO to the value.
void asdf_arch_out1_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT2 bit if value is true, and clear OUT2 if value is false.
void asdf_arch_out2_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Emulates setting the OUT2 bit to hi-z if value is true, and low
// if value is false. For testing, set PHYSICAL_OUT2_OPEN_HI to the value.
void asdf_arch_out2_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out2_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Emulates setting the OUT2 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT2_OPEN_LO to the value.
void asdf_arch_out2_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Sets the OUT3 bit if value is true, and clear OUT3 if value is false.
void asdf_arch_out3_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_open_hi_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Emulates setting the OUT3 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT3_OPEN_LO to the value.
void asdf_arch_out3_open_hi_set(uint8_t value);
// PROCEDURE: asdf_arch_out3_open_lo_set
// INPUTS: (uint8_t) value
// OUTPUTS: none
// DESCRIPTION: Emulates setting the OUT3 bit to high if value is true, and hi-z
// if value is false. For testing, set PHYSICAL_OUT3_OPEN_LO to the value.
void asdf_arch_out3_open_lo_set(uint8_t value);
// PROCEDURE: asdf_arch_check_output
// INPUTS:(asdf_physical_dev_t) device - which device to check
// OUTPUTS: the value of the device setting.
// DESCRIPTION: For a given real device, return the current setting (true or false)
uint8_t asdf_arch_check_output(asdf_physical_dev_t device);
// PROCEDURE: asdf_arch_check_pulse
// INPUTS:(asdf_physical_dev_t) device - which device to check
// OUTPUTS: the value of the device pulse detector
// DESCRIPTION: For a given real device, return the state of the pulse detector
uint8_t asdf_arch_check_pulse(asdf_physical_dev_t device);
// PROCEDURE: asdf_arch_pulse_delay_short
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Emulates a short delay by advancing the pulse detector state machine
// for each output.
void asdf_arch_pulse_delay_short(void);
// PROCEDURE: asdf_arch_pulse_delay_long
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Emulates a long delay by advancing the pulse detector state machine
// for each output.
void asdf_arch_pulse_delay_long(void);
// PROCEDURE: asdf_arch_read_row
// INPUTS: (uint8_t) row: the row number to be scanned
// OUTPUTS: returns a word containing the emulated active (pressed) columns
// DESCRIPTION: reads the word from the key state emulation array and returns
// the value. The value is a binary representation of the keys pressed within
// the row, with 1=pressed, 0=released.
asdf_cols_t asdf_arch_read_row(uint8_t row);
// PROCEDURE: asdf_arch_send_code
// INPUTS: asdf_keycode_t code
// OUTPUTS: none
// DESCRIPTION: emulates sending a code, by copying code to a register that can
// be tested.
void asdf_arch_send_code(asdf_keycode_t);
// PROCEDURE: asdf_arch_delay_ms
// INPUTS: (uint16) delay_ms - the delay in msec.
// OUTPUTS: none
// DESCRIPTION: Delays a specified number of milliseconds
void asdf_arch_delay_ms(uint16_t delay_ms);
// PROCEDURE: asdf_arch_get_sent_code
// INPUTS: none
// OUTPUTS: returns type (asdf_keycode_t) in register and zeros the register.
// DESCRIPTION: faciliates test of sending a code, by reporting contents of the
// "sent register"
asdf_keycode_t asdf_arch_get_sent_code(void);
// PROCEDURE: asdf_arch_was_code_sent
// INPUTS: none
// OUTPUTS: returns TRUE if a code was sent, FALSE otherwise.
uint8_t asdf_arch_was_code_sent(void);
// PROCEDURE: asdf_arch_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: sets up all the hardware for the keyboard
void asdf_arch_init(void);
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.
//
#endif // !defined (ASDF_ARCH_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,109 +0,0 @@
message("C compiler: ${CMAKE_C_COMPILER}")
function(create_keymap_setups keymaps keymap_table)
list(TRANSFORM keymaps REPLACE "<\(.+\):\(.+\)>" "\n case \\2: setup_\\1_keymap();break" OUTPUT_VARIABLE temp_list)
# we can keep the ';' cmake list separators as the C statement separators.
# However, we need to append an extra ';' at the end.
string(APPEND temp_list ";")
set(${keymap_table} "${temp_list}" PARENT_SCOPE)
endfunction(create_keymap_setups)
function(create_keymap_valid keymaps keymap_valid)
list(TRANSFORM keymaps REPLACE "<\(.+\):\(.+\)>" "\n case \\2:" OUTPUT_VARIABLE temp_list)
# we can keep the ';' cmake list separators as the C statement separators.
# However, we need to append an extra ';' at the end.
string(APPEND temp_list ";")
set(${keymap_valid} "${temp_list}" PARENT_SCOPE)
endfunction(create_keymap_valid)
function(create_keymap_declarations keymaps keymap_decl)
list(TRANSFORM keymaps REPLACE "<\(.+\):\(.+\)>" "\n void setup_\\1_keymap(void)" OUTPUT_VARIABLE temp_list)
# we can keep the ';' cmake list separators as the C statement separators.
# However, we need to append an extra ';' at the end.
string(APPEND temp_list ";")
set(${keymap_decl} "${temp_list}" PARENT_SCOPE)
endfunction(create_keymap_declarations)
function(create_keymap_report keymaps keymap_report)
list(TRANSFORM keymaps REPLACE "<\(.+\):\(.+\)>" "\nkeymap [\\2]: \\1" OUTPUT_VARIABLE temp_list)
string(REPLACE ";" "" temp_list2 "${temp_list}")
set(${keymap_report} "${temp_list2}" PARENT_SCOPE)
endfunction(create_keymap_report)
include(../keymap_list.cmake)
create_keymap_setups("${keymap_list}" keymap_table)
create_keymap_valid("${keymap_list}" keymap_valid)
create_keymap_report("${keymap_list}" keymap_report)
create_keymap_declarations("${keymap_list}" keymap_declarations)
# get list length and decrement by one to account for trailing semicolon
list (LENGTH keymap_list num_keymaps)
message("**********************")
message("Keymap table: ${keymap_report}")
message("**********************\n\n")
set (PROJECT_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(${PROJECT_SRC_DIR}/Arch/asdf_arch_${ARCH}.h ${CMAKE_CURRENT_BINARY_DIR}/asdf_arch.h COPYONLY)
configure_file(${PROJECT_SRC_DIR}/Arch/asdf_arch_${ARCH}.c ${CMAKE_CURRENT_BINARY_DIR}/asdf_arch.c COPYONLY)
configure_file(${PROJECT_SRC_DIR}/asdf_keymap_setup.c.in ${CMAKE_CURRENT_BINARY_DIR}/asdf_keymap_setup.c)
configure_file(${PROJECT_SRC_DIR}/asdf_keymap_setup.h.in ${CMAKE_CURRENT_BINARY_DIR}/asdf_keymap_setup.h)
c_toolchain_flags()
list (APPEND SOURCES
asdf.c
${CMAKE_CURRENT_BINARY_DIR}/asdf_arch.c
${CMAKE_CURRENT_BINARY_DIR}/asdf_keymap_setup.c
asdf_buffer.c
asdf_hook.c
asdf_keymap_setup.c
asdf_keymaps.c
asdf_modifiers.c
asdf_physical.c
asdf_repeat.c
asdf_virtual.c
asdf_print.c
Keymaps/asdf_keymap_classic.c
Keymaps/asdf_keymap_classic_caps.c
Keymaps/asdf_keymap_classic_add_map.c
Keymaps/asdf_keymap_apple2.c
Keymaps/asdf_keymap_apple2_caps.c
Keymaps/asdf_keymap_apple2_add_map.c
Keymaps/asdf_keymap_sol.c
main.c
)
# create a library for the keymap modules
#add_subdirectory(Keymaps)
# add the executable
if (COMMAND custom_add_executable)
custom_add_executable(${PROJECT_TARGET_NAME}
${SOURCES}
)
else()
add_executable(${PROJECT_TARGET_NAME}
${SOURCES}
)
endif()
target_include_directories(${PROJECT_EXECUTABLE_TARGET_NAME}
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Keymaps
)
target_compile_options(${PROJECT_EXECUTABLE_TARGET_NAME}
PRIVATE
${CFLAGS}
)
#target_link_libraries(${PROJECT_EXECUTABLE_TARGET_NAME}
# keymaps
# )

View File

@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 3 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, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -1,46 +0,0 @@
---
BasedOnStyle: Mozilla
AlignAfterOpenBracket: Align
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'true'
BinPackArguments: 'true'
BinPackParameters: 'true'
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Stroustrup
ColumnLimit: '100'
ConstructorInitializerIndentWidth: '2'
ContinuationIndentWidth: '2'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
IncludeBlocks: Preserve
IndentCaseLabels: 'true'
IndentPPDirectives: None
IndentWidth: '2'
IndentWrappedFunctionNames: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'true'
Language: Cpp
MaxEmptyLinesToKeep: '2'
PointerAlignment: Right
ReflowComments: 'true'
SortIncludes: 'false'
SpaceAfterCStyleCast: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '1'
SpacesInCStyleCastParentheses: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
TabWidth: '8'
UseTab: Never
...

View File

@ -1,87 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_apple2.c
//
// set up keymaps for Apple II keyboards
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf_print.h"
#include "asdf_keymaps.h"
#include "asdf_virtual.h"
#include "asdf_modifiers.h"
#include "asdf_keymap_apple2_add_map.h"
#include "asdf_keymap_apple2.h"
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
void apple2_id_message(void) {
asdf_print("[Keymap: Apple 2 (u/l case)]");
}
void setup_apple2_keymap(void)
{
asdf_set_print_delay(APPLE2_PRINT_DELAY);
apple_add_map(APPLE_PLAIN_MAP, MOD_PLAIN_MAP);
apple_add_map(APPLE_CAPS_MAP, MOD_CAPS_MAP);
apple_add_map(APPLE_SHIFT_MAP, MOD_SHIFT_MAP);
apple_add_map(APPLE_CTRL_MAP, MOD_CTRL_MAP);
asdf_hook_assign(APPLESOFT_KEYBOARD_TEST, applesoft_keyboard_test);
asdf_hook_assign(APPLE2_ID_MESSAGE, apple2_id_message);
// Attach the physical POWER LED as the CAPS LED. Assign no triggered
// function, and initialize to initial state of the CAPS logic. The CAPS LED
// will be controlled by the state of the CAPSLOCK logic.
asdf_virtual_assign(VCAPS_LED, APPLE_POWER_LED, V_NOFUNC, APPLE_POWER_LED_INIT_VALUE);
// Assign CAPS LED to off (disabled)
asdf_virtual_assign(APPLE_VIRTUAL_DISABLED_LED, APPLE_DISABLED_LED, V_NOFUNC, APPLE_DISABLED_INIT_VALUE);
// assign RESET output to the virtual RESET output, configure to produce a short pulse when activated
asdf_virtual_assign(APPLE_VIRTUAL_RESET, APPLE_RESET_OUTPUT, V_PULSE_SHORT, !APPLE_RESET_ACTIVE_VALUE);
// assign the CLRSCR output to the virtual CLRSCR output, configure to produce a long pulse when activated
asdf_virtual_assign(APPLE_VIRTUAL_CLR_SCR, APPLE_CLR_SCR_OUTPUT, V_PULSE_LONG, !APPLE_CLR_SCR_ACTIVE_VALUE);
asdf_modifier_capslock_activate(); // For Apple 2, start with CAPS active
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,51 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_apple2.h
//
// Apple 2 keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// This file supplies the Apple 2 ASCII keyboard keymap. Two variants are provided:
//
// 1) An Upper/Lowercase variant. This variant moves the @ and ^ symbols from
// the P and N keys to the REPEAT key, since the P and N keys need to reserve
// the shifted value for the uppercase characters. Also, the "Power" key
// doubles as a caps-lock key.
//
// 2) A CAPS only keyboard, following the standard Apple II conventions and
// layout, with ^ above the N key and @ above the P key, and a functioning
// REPEAT key.
//
// For both variants, CTRL+RESET is required for a system reset.
#if !defined(ASDF_KEYMAP_DEFS_APPLE2_H)
#define ASDF_KEYMAP_DEFS_APPLE2_H
#define APPLESOFT_KEYBOARD_TEST ASDF_HOOK_USER_9
#define APPLE2_ID_MESSAGE ASDF_HOOK_USER_10
#define APPLE2_PRINT_DELAY 40 // msec
#endif /* !defined (ASDF_KEYMAP_DEFS_APPLE2_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,178 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_classic.c
//
// defines the keymap matrices used by the "classic" ADM 3A style keymap variants
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf_arch.h"
#include "asdf.h"
#include "asdf_print.h"
#include "asdf_ascii.h"
#include "asdf_keymaps.h"
#include "asdf_keymap_apple2_add_map.h"
// Key Matrix for combination of ASCII controller and Apple ASCII matrix
//
// Col-> 0 1 2 3 4 5 6 7
// Row 0 POWER R-Shift L-Shift (no key) ESC TAB CTRL \(backslash)
// Row 1 Rubout P ; / SPACEBAR Z A Q
// Row 2 Break ,(comma) M N B V C X
// Row 3 Spare K J H G F D A
// Row 4 Rt arrow I U Y T R E W
// Row 5 LT arrow Repeat CapsLock Return LineFeed O(alpha) L .(period)
// Row 6 ~(tilde) ] [ -(dash) :(colon) 0(numeral) 9 8
// Row 7 @(at) 7 6 5 4 3 2 1
//
// Row 15 DIP switches 0-7
//
// Notes:
//
// 1) The keys above correspond to the silk screen on the PCB. For the OSI and
// Apple layouts, the keys may not all match the silk screen. When creating a
// layout different from the silk screen, look up the row and column for the
// silk screen label at the desired position, and then place the desired
// function in the keymap definition at the desired row and column. For
// example, the Apple 2 keymap places the "RESET" key at the "[" silk-screen
// position, Row 6, Col 2. The keymap places ACTION_RESET at Row 6, Col 2 in
// the "ASDF_APPLE2_CTRL_MAP" to map the RESET function to the CTRL-RESET key
// combination.
//
// 2) To ensure consistent DIP switch operation within the keymap, a
// ASDF_ASCII_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3
// definitions in positions 0-3 ensures consistent map selection among all
// keymaps.
#define ASDF_APPLE2_DIP_SWITCHES ASDF_KEYMAP_DIP_SWITCHES
typedef asdf_keycode_t apple_keycode_matrix_t[ASDF_APPLE2_NUM_ROWS][ASDF_APPLE2_NUM_COLS];
const FLASH apple_keycode_matrix_t apple_plain_matrix = {
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING,
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW },
[1] = { ASCII_DEL, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' },
[2] = { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' },
[3] = { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' },
[4] = { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' },
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, '^', 'o', 'l', ASCII_PERIOD },
[6] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, '-', ':', ASCII_ZERO, '9', '8' },
[7] = { APPLE_LEFT_ARROW, '7', '6', '5', '4', '3', '2', '1' },
ASDF_APPLE2_DIP_SWITCHES
};
const FLASH apple_keycode_matrix_t apple_shift_matrix = {
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING,
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW },
[1] = { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' },
[2] = { ACTION_NOTHING, '<', 'M', 'N', 'B', 'V', 'C', 'X' },
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' },
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' },
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, ASCII_AT, 'O', 'L', '>' },
[6] = { ACTION_NOTHING, ACTION_NOTHING, APPLE_ACTION_CLEAR, '=',
'*', ASCII_ZERO, ASCII_RT_PAREN, ASCII_LT_PAREN },
[7] = { APPLE_LEFT_ARROW, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' },
ASDF_APPLE2_DIP_SWITCHES
};
const FLASH apple_keycode_matrix_t apple_caps_shift_matrix = {
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING,
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW },
[1] = { ACTION_NOTHING, ASCII_AT, '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' },
[2] = { ACTION_NOTHING, '<', 'M', '^', 'B', 'V', 'C', 'X' },
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' },
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' },
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, ACTION_REPEAT, 'O', 'L', '>' },
[6] = { ACTION_NOTHING, ACTION_NOTHING, APPLE_ACTION_CLEAR, '=',
'*', ASCII_ZERO, ASCII_RT_PAREN, ASCII_LT_PAREN },
[7] = { APPLE_LEFT_ARROW, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' },
ASDF_APPLE2_DIP_SWITCHES
};
const FLASH apple_keycode_matrix_t apple_caps_matrix = {
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING,
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW },
[1] = { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' },
[2] = { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' },
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' },
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' },
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, ACTION_REPEAT, 'O', 'L', ASCII_PERIOD },
[6] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, '-', ':', ASCII_ZERO, '9', '8' },
[7] = { APPLE_LEFT_ARROW, '7', '6', '5', '4', '3', '2', '1' },
ASDF_APPLE2_DIP_SWITCHES
};
const FLASH apple_keycode_matrix_t apple_ctrl_matrix = {
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING,
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW },
[1] = { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING,
ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q },
[2] = { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N,
ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X },
[3] = { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H,
ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S },
[4] = { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y,
ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W },
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR,
ACTION_REPEAT, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING },
[6] = { ACTION_NOTHING, ACTION_NOTHING, APPLE_ACTION_RESET, ACTION_NOTHING,
ACTION_NOTHING, ACTION_FN_10, ACTION_FN_9, ACTION_FN_8 },
[7] = { APPLE_LEFT_ARROW, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5,
ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_1 },
ASDF_APPLE2_DIP_SWITCHES
};
static const apple_keycode_matrix_t *apple_maps[] = {
[APPLE_CAPS_MAP] = &apple_caps_matrix,
[APPLE_PLAIN_MAP] = &apple_plain_matrix,
[APPLE_SHIFT_MAP] = &apple_shift_matrix,
[APPLE_CTRL_MAP] = &apple_ctrl_matrix,
[APPLE_CAPS_SHIFT_MAP] = &apple_caps_shift_matrix
};
void applesoft_keyboard_test(void)
{
asdf_print("10 GET A$\r");
asdf_print("20 A = ASC(A$)\r");
asdf_print("30 IF A < 32 THEN A$=\"CTL+\"+CHR$(A + 64)\r");
asdf_print("40 ?\"'\";A$;\"' = \";A:\r");
asdf_print("50 IF A <> 3 GOTO 10\r");
asdf_print("60 END\rRUN\r");
}
void apple_add_map(const apple_map_index_t map_index,
modifier_index_t modifier_index)
{
asdf_keycode_t (*matrix)[ASDF_APPLE2_NUM_COLS] =
(asdf_keycode_t (*)[ASDF_APPLE2_NUM_COLS]) apple_maps[map_index];
asdf_keymaps_add_map(&matrix[0][0], modifier_index, (uint8_t) ASDF_APPLE2_NUM_ROWS,
(uint8_t) ASDF_APPLE2_NUM_COLS);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,80 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_apple_add_map.h
//
// defines keymap matrices and add_map() function for apple2 layouts
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// To use this ascii for a new keymap, edit the keymaps definitions as
// desired. The keymaps are organized from row 0, counting upward, and each row
// includes the columns from 0-NUM_COLS.
//
#if !defined(ASDF_KEYMAP_APPLE_ADD_MAP_H)
#define ASDF_KEYMAP_APPLE_ADD_MAP_H
#include "asdf_keymap_defs_dipswitch.h"
#include "asdf_modifiers.h"
#define ASDF_APPLE2_NUM_ROWS 9 // DIP switches are row 8 (zero-based)
#define ASDF_APPLE2_NUM_COLS 8
#define APPLE_ACTION_RESET ACTION_VOUT1
#define APPLE_VIRTUAL_RESET VOUT1
#define APPLE_RESET_OUTPUT PHYSICAL_OUT3_OPEN_HI
#define APPLE_RESET_ACTIVE_VALUE 0
#define APPLE_ACTION_CLEAR ACTION_VOUT2
#define APPLE_VIRTUAL_CLR_SCR VOUT2
#define APPLE_CLR_SCR_OUTPUT PHYSICAL_OUT1_OPEN_LO
#define APPLE_CLR_SCR_ACTIVE_VALUE 1
#define APPLE_VIRTUAL_POWER_LED VLED1
#define APPLE_POWER_LED PHYSICAL_LED1
#define APPLE_POWER_LED_INIT_VALUE 0 // Toggles when caps lock is activated
#define APPLE_VIRTUAL_DISABLED_LED VLED2
#define APPLE_DISABLED_LED PHYSICAL_LED3
#define APPLE_DISABLED_INIT_VALUE 0
#define ASDF_APPLE2_DIP_SWITCHES ASDF_KEYMAP_DIP_SWITCHES
#define APPLE_LEFT_ARROW ASCII_CTRL_H
#define APPLE_RIGHT_ARROW ASCII_CTRL_U
typedef enum {
APPLE_PLAIN_MAP,
APPLE_CAPS_MAP,
APPLE_SHIFT_MAP,
APPLE_CAPS_SHIFT_MAP,
APPLE_CTRL_MAP
} apple_map_index_t;
// function prototypes
void applesoft_keyboard_test(void);
void apple_add_map(const apple_map_index_t map_index, modifier_index_t modifier_index);
#endif /* !defined (ASDF_KEYMAP_APPLE_ADD_MAP_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,80 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_apple2_caps.c
//
// set up keymaps for ALL CAPS Apple II keyboards
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf_print.h"
#include "asdf_keymaps.h"
#include "asdf_virtual.h"
#include "asdf_modifiers.h"
#include "asdf_keymap_apple2_add_map.h"
#include "asdf_keymap_apple2_caps.h"
void apple2_caps_id_message(void) {
asdf_print("[Keymap: Apple 2 CAPS]");
}
// PROCEDURE: setup_apple2_caps_keymap
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Set up keymaps for ALL CAPS apple 2 keyboard
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void setup_apple2_caps_keymap(void)
{
asdf_set_print_delay(APPLE2_PRINT_DELAY);
apple_add_map(APPLE_CAPS_MAP, MOD_PLAIN_MAP);
apple_add_map(APPLE_CAPS_MAP, MOD_CAPS_MAP);
apple_add_map(APPLE_CAPS_SHIFT_MAP, MOD_SHIFT_MAP);
apple_add_map(APPLE_CTRL_MAP, MOD_CTRL_MAP);
asdf_hook_assign(APPLESOFT_KEYBOARD_TEST, applesoft_keyboard_test);
asdf_hook_assign(APPLE2_CAPS_ID_MESSAGE, apple2_caps_id_message);
// Turn the POWER LED on and don't assign to any function
asdf_virtual_assign(APPLE_VIRTUAL_POWER_LED, APPLE_POWER_LED, V_NOFUNC, APPLE_POWER_LED_INIT_VALUE);
// Assign CAPS LED to off (disabled)
asdf_virtual_assign(APPLE_VIRTUAL_DISABLED_LED, APPLE_DISABLED_LED, V_NOFUNC, APPLE_DISABLED_INIT_VALUE);
// assign RESET output to the virtual RESET output, configure to produce a short pulse when activated
asdf_virtual_assign(APPLE_VIRTUAL_RESET, APPLE_RESET_OUTPUT, V_PULSE_SHORT, !APPLE_RESET_ACTIVE_VALUE);
// assign the CLRSCR output to the virtual CLRSCR output, configure to produce a long pulse when activated
asdf_virtual_assign(APPLE_VIRTUAL_CLR_SCR, APPLE_CLR_SCR_OUTPUT, V_PULSE_LONG, !APPLE_CLR_SCR_ACTIVE_VALUE);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,51 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_apple2_caps.h
//
// Apple 2 keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// This file supplies the Apple 2 ASCII keyboard keymap. Two variants are provided:
//
// 1) An Upper/Lowercase variant. This variant moves the @ and ^ symbols from
// the P and N keys to the REPEAT key, since the P and N keys need to reserve
// the shifted value for the uppercase characters. Also, the "Power" key
// doubles as a caps-lock key.
//
// 2) A CAPS only keyboard, following the standard Apple II conventions and
// layout, with ^ above the N key and @ above the P key, and a functioning
// REPEAT key.
//
// For both variants, CTRL+RESET is required for a system reset.
#if !defined(ASDF_KEYMAP_DEFS_APPLE2_CAPS_H)
#define ASDF_KEYMAP_DEFS_APPLE2_CAPS_H
#define APPLESOFT_KEYBOARD_TEST ASDF_HOOK_USER_9
#define APPLE2_CAPS_ID_MESSAGE ASDF_HOOK_USER_10
#define APPLE2_PRINT_DELAY 40 // msec
#endif /* !defined (ASDF_KEYMAP_DEFS_APPLE2_CAPS_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,106 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_apple2.c
//
// set up keymaps for Apple II keyboards
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf_keymap_apple2.h"
#include "asdf_keymap_defs_dipswitch.h"
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
// PROCEDURE: apple_add_map
// INPUTS: asdf_keycode_t (*matrix) - a SOL_NUM_ROWS x SOL_NUM_COLS matrix of
// keycodes for each physical row/column pair
// modifier_index_t modifier index - the modifier state corresponding to
// the keycode matrix
//
// OUTPUTS: none
// DESCRIPTION: Passes the keycode matrix and modifier state through to
// asdf_keymaps_add_map(), along with the row/column dimensions.
//
// SIDE EFFECTS: the matrix is added to the keymap
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void apple_add_map(const asdf_keycode_t (*matrix)[APPLE_NUM_COLS],
modifier_index_t modifier_index)
{
asdf_keymaps_add_map(&matrix[0][0], modifier_index, (uint8_t) APPLE_NUM_ROWS,
(uint8_t) APPLE_NUM_COLS);
}
void setup_classic_keymap(void)
{
apple_add_map(apple_plain_map, MOD_PLAIN_MAP);
apple_add_map(apple_caps_map, MOD_CAPS_MAP);
apple_add_map(apple_shift_map, MOD_SHIFT_MAP);
apple_add_map(apple_ctrl_map, MOD_CTRL_MAP);
asdf_virtual_init();
// Attach the physical POWER LED as the CAPS LED. Assign no triggered
// function, and initialize to initial state of the CAPS logic. The CAPS LED
// will be controlled by the state of the CAPSLOCK logic.
{ .virtual_device = VCAPS_LED, .physical_device = APPLE_POWER_LED, .initial_value = 0 }, \
asdf_virtual_assign(VCAPS_LED, APPLE_POWER_LED, V_NOFUNC, APPLE_POWER_LED_INIT_VALUE);
// Assign CAPS LED to virtual CAPS LED, and initialize to the INIT value, to
// match the initial CAPSLOCK state. The capslock state code will alter the
// virtual LED according to the state.
asdf_virtual_assign(VCAPS_LED, APPLE_CAPS_LED, V_NOFUNC, APPLE_CAPS_LED_INIT_VALUE);
{ .virtual_device = APPLE_VIRTUAL_DISABLED_LED, \
.physical_device = APPLE_DISABLED_LED, \
.initial_value = 0 }, \
// assign RESET output to the virtual RESET output, configure to produce a short pulse when activated
asdf_virtual_assign(APPLE_VIRTUAL_RESET, APPLE_RESET_OUTPUT, V_PULSE_SHORT, !APPLE_RESET_ACTIVE_VALUE);
// assign the CLRSCR output to the virtual CLRSCR output, configure to produce a long pulse when activated
asdf_virtual_assign(APPLE_VIRTUAL_CLR_SCR, APPLE_CLR_SCR_OUTPUT, V_PULSE_LONG, !APPLE_CLR_SCR_ACTIVE_VALUE);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,84 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_classic.c
//
// Implements the "classic" ADM 3A style keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf.h"
#include "asdf_keymaps.h"
#include "asdf_virtual.h"
#include "asdf_modifiers.h"
#include "asdf_print.h"
#include "asdf_keymap_classic.h"
#include "asdf_keymap_classic_add_map.h"
#include "asdf_keymap_apple2_add_map.h"
void classic_id_message(void) {
asdf_print("[Keymap: classic]\n");
}
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
void setup_classic_keymap(void)
{
asdf_set_print_delay(ASDF_CLASSIC_PRINT_SPEED); //msec
classic_add_map(CLASSIC_PLAIN_MAP, MOD_PLAIN_MAP);
classic_add_map(CLASSIC_CAPS_MAP, MOD_CAPS_MAP);
classic_add_map(CLASSIC_SHIFT_MAP, MOD_SHIFT_MAP);
classic_add_map(CLASSIC_CTRL_MAP, MOD_CTRL_MAP);
asdf_hook_assign(CLASSIC_ID_MESSAGE_HOOK, classic_id_message);
asdf_hook_assign(APPLESOFT_KEYBOARD_TEST_HOOK, applesoft_keyboard_test);
// Assign power LED to virtual power LED, and initialize to ON
asdf_virtual_assign(CLASSIC_VIRTUAL_POWER_LED, CLASSIC_POWER_LED, V_NOFUNC, CLASSIC_POWER_LED_INIT_VALUE);
// Assign CAPS LED to virtual CAPS LED, and initialize to the INIT value, to
// match the initial CAPSLOCK state. The capslock state code will alter the
// virtual LED according to the state.
asdf_virtual_assign(VCAPS_LED, CLASSIC_CAPS_LED, V_NOFUNC, CLASSIC_CAPS_LED_INIT_VALUE);
// assign RESET output to the virtual RESET output, configure to produce a short pulse when activated
asdf_virtual_assign(CLASSIC_VIRTUAL_RESET, CLASSIC_RESET_OUTPUT, V_PULSE_SHORT, !CLASSIC_RESET_ACTIVE_VALUE);
// assign the CLRSCR output to the virtual CLRSCR output, configure to produce a long pulse when activated
asdf_virtual_assign(CLASSIC_VIRTUAL_CLR_SCR, CLASSIC_CLR_SCR_OUT, V_PULSE_LONG, !CLASSIC_CLR_SCR_ACTIVE_VALUE);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,69 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_classic.h
//
// Ascii keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// To use this ascii for a new keymap, edit the keymaps definitions as
// desired. The keymaps are organized from row 0, counting upward, and each row
// includes the columns from 0-NUM_COLS.
//
#if !defined(ASDF_KEYMAP_DEFS_CLASSIC_H)
#define ASDF_KEYMAP_DEFS_CLASSIC_H
#include "asdf_hook.h"
// Edit the number of rows and columns used in this map. If the number is less
// than the maxium, the unused elements will be initialized to 0.
#define CLASSIC_NUM_ROWS 9 // DIP switches are row 8 (zero based)
#define CLASSIC_NUM_COLS 8
#define CLASSIC_ACTION_BREAK ACTION_NOTHING
#define CLASSIC_VIRTUAL_RESET VOUT1
#define CLASSIC_ACTION_RESET ACTION_VOUT1
#define CLASSIC_RESET_OUTPUT PHYSICAL_OUT3_OPEN_HI
#define CLASSIC_RESET_ACTIVE_VALUE 0
#define CLASSIC_VIRTUAL_CLR_SCR VOUT2
#define CLASSIC_ACTION_CLEAR ACTION_VOUT2
#define CLASSIC_CLR_SCR_OUT PHYSICAL_OUT1_OPEN_LO
#define CLASSIC_CLR_SCR_ACTIVE_VALUE 1
#define CLASSIC_VIRTUAL_POWER_LED VLED1
#define CLASSIC_POWER_LED PHYSICAL_LED1
#define CLASSIC_POWER_LED_INIT_VALUE 1
#define CLASSIC_CAPS_LED PHYSICAL_LED3
#define CLASSIC_CAPS_LED_INIT_VALUE 0
#define CLASSIC_ID_MESSAGE_HOOK ASDF_HOOK_USER_10
#define APPLESOFT_KEYBOARD_TEST_HOOK ASDF_HOOK_USER_9
#define ASDF_CLASSIC_PRINT_SPEED 40
#endif /* !defined (ASDF_KEYMAP_DEFS_ASCII_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,156 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_classic.c
//
// defines the keymap matrices used by the "classic" ADM 3A style keymap variants
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf_arch.h"
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_keymaps.h"
#include "asdf_keymap_classic.h"
#include "asdf_keymap_classic_add_map.h"
#include "asdf_keymap_defs_dipswitch.h"
// Key Matrix for combination of ASCII controller and Classic ASCII matrix
//
// Col-> 0 1 2 3 4 5 6 7
// Row 0 POWER R-Shift L-Shift (no key) ESC TAB CTRL \(backslash)
// Row 1 Rubout P ; / SPACEBAR Z A Q
// Row 2 Break ,(comma) M N B V C X
// Row 3 Spare K J H G F D A
// Row 4 Rt arrow I U Y T R E W
// Row 5 LT arrow Repeat CapsLock Return LineFeed O(alpha) L .(period)
// Row 6 ~(tilde) ] [ -(dash) :(colon) 0(numeral) 9 8
// Row 7 @(at) 7 6 5 4 3 2 1
//
// Row 15 DIP switches 0-7
//
// Notes:
//
// 1) The keys above correspond to the silk screen on the PCB. For the OSI and
// Apple layouts, the keys may not all match the silk screen. When creating a
// layout different from the silk screen, look up the row and column for the
// silk screen label at the desired position, and then place the desired
// function in the keymap definition at the desired row and column. For
// example, the Apple 2 keymap places the "RESET" key at the "[" silk-screen
// position, Row 6, Col 2. The keymap places ACTION_RESET at Row 6, Col 2 in
// the "ASDF_APPLE2_CTRL_MAP" to map the RESET function to the CTRL-RESET key
// combination.
//
// 2) To ensure consistent DIP switch operation within the keymap, a
// ASDF_ASCII_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3
// definitions in positions 0-3 ensures consistent map selection among all
// keymaps.
#define ASDF_CLASSIC_DIP_SWITCHES ASDF_KEYMAP_DIP_SWITCHES
typedef asdf_keycode_t classic_keycode_matrix_t[CLASSIC_NUM_ROWS][CLASSIC_NUM_COLS];
const FLASH classic_keycode_matrix_t classic_plain_matrix = {
[0] = { ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ASCII_ESC, ASCII_TAB,
ACTION_CTRL, ASCII_BACKSLASH },
[1] = { ASCII_DEL, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' },
[2] = { CLASSIC_ACTION_BREAK, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' },
[3] = { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' },
[4] = { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' },
[5] = { ACTION_NOTHING, ACTION_REPEAT, ACTION_CAPS, ASCII_CR, ASCII_LF, 'o', 'l', ASCII_PERIOD },
[6] = { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', ASCII_ZERO, '9',
'8' },
[7] = { ASCII_AT, '7', '6', '5', '4', '3', '2', '1' },
ASDF_CLASSIC_DIP_SWITCHES
};
const FLASH classic_keycode_matrix_t classic_shift_matrix = {
[0] = { ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ASCII_ESC, ASCII_TAB,
ACTION_CTRL, ASCII_VERT_BAR },
[1] = { ASCII_DEL, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' },
[2] = { CLASSIC_ACTION_CLEAR, '<', 'M', 'N', 'B', 'V', 'C', 'X' },
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' },
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' },
[5] = { ACTION_NOTHING, ACTION_REPEAT, ACTION_CAPS, ASCII_CR, ASCII_LF, 'O', 'L', '>' },
[6] = { ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', ASCII_ZERO,
ASCII_RT_PAREN, ASCII_LT_PAREN },
[7] = { ASCII_GRAVE_ACCENT, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' },
ASDF_CLASSIC_DIP_SWITCHES
};
const FLASH classic_keycode_matrix_t classic_caps_matrix = {
[0] = { ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ASCII_ESC, ASCII_TAB,
ACTION_CTRL, ASCII_BACKSLASH },
[1] = { ASCII_DEL, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' },
[2] = { CLASSIC_ACTION_BREAK, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' },
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' },
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' },
[5] = { ACTION_NOTHING, ACTION_REPEAT, ACTION_CAPS, ASCII_CR, ASCII_LF, 'O', 'L', ASCII_PERIOD },
[6] = { ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', ASCII_ZERO, '9',
'8' },
[7] = { ASCII_AT, '7', '6', '5', '4', '3', '2', '1' },
ASDF_CLASSIC_DIP_SWITCHES
};
const FLASH classic_keycode_matrix_t classic_ctrl_matrix = {
[0] = { ACTION_NOTHING, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, ASCII_ESC, ASCII_TAB,
ACTION_CTRL, 0x1c },
[1] = { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, ASCII_SPACE, ASCII_CTRL_Z,
ASCII_CTRL_A, ASCII_CTRL_Q },
[2] = { CLASSIC_ACTION_RESET, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, ASCII_CTRL_B, ASCII_CTRL_V,
ASCII_CTRL_C, ASCII_CTRL_X },
[3] = { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, ASCII_CTRL_G, ASCII_CTRL_F,
ASCII_CTRL_D, ASCII_CTRL_S },
[4] = { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, ASCII_CTRL_T, ASCII_CTRL_R,
ASCII_CTRL_E, ASCII_CTRL_W },
[5] = { ACTION_NOTHING, ACTION_REPEAT, ACTION_CAPS, ASCII_CR, ASCII_LF, ASCII_CTRL_O,
ASCII_CTRL_L, ACTION_NOTHING },
[6] = { ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, ACTION_NOTHING, ACTION_FN_10,
ACTION_FN_9, ACTION_FN_8 },
[7] = { ASCII_NULL, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, ACTION_FN_4, ACTION_FN_3, ACTION_FN_2,
ACTION_FN_1 },
ASDF_CLASSIC_DIP_SWITCHES
};
static const classic_keycode_matrix_t *classic_maps[] = {
[CLASSIC_CAPS_MAP] = &classic_caps_matrix,
[CLASSIC_PLAIN_MAP] = &classic_plain_matrix,
[CLASSIC_SHIFT_MAP] = &classic_shift_matrix,
[CLASSIC_CTRL_MAP] = &classic_ctrl_matrix,
};
void classic_add_map(const classic_map_index_t map_index,
modifier_index_t modifier_index)
{
asdf_keycode_t (*matrix)[CLASSIC_NUM_COLS] =
(asdf_keycode_t (*)[CLASSIC_NUM_COLS]) classic_maps[map_index];
asdf_keymaps_add_map(&matrix[0][0], modifier_index, (uint8_t) CLASSIC_NUM_ROWS,
(uint8_t) CLASSIC_NUM_COLS);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,50 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_classic_add_map.h
//
// defines keymap matrices and add_map() function for classic layouts
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// To use this ascii for a new keymap, edit the keymaps definitions as
// desired. The keymaps are organized from row 0, counting upward, and each row
// includes the columns from 0-NUM_COLS.
//
#if !defined(ASDF_KEYMAP_CLASSIC_ADD_MAP_H)
#define ASDF_KEYMAP_CLASSIC_ADD_MAP_H
#include "asdf_modifiers.h"
typedef enum {
CLASSIC_PLAIN_MAP,
CLASSIC_CAPS_MAP,
CLASSIC_SHIFT_MAP,
CLASSIC_CTRL_MAP,
} classic_map_index_t;
// function prototypes
void classic_add_map(const classic_map_index_t map_index, modifier_index_t modifier_index);
#endif /* !defined (ASDF_KEYMAP_CLASSIC_ADD_MAP_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,87 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_classic.c
//
// Implements the "classic" ADM 3A style keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf.h"
#include "asdf_keymaps.h"
#include "asdf_print.h"
#include "asdf_virtual.h"
#include "asdf_modifiers.h"
#include "asdf_keymap_classic.h"
#include "asdf_keymap_classic_add_map.h"
#include "asdf_keymap_apple2_add_map.h"
void classic_caps_id_message(void) {
asdf_print("[Keymap: classic]\n");
}
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
void setup_classic_caps_keymap(void)
{
asdf_set_print_delay(ASDF_CLASSIC_PRINT_SPEED);
// for the ALL CAPS keymap, the "plain" mode is the same as "all caps" mode:
classic_add_map(CLASSIC_CAPS_MAP, MOD_PLAIN_MAP);
classic_add_map(CLASSIC_CAPS_MAP, MOD_CAPS_MAP);
classic_add_map(CLASSIC_SHIFT_MAP, MOD_SHIFT_MAP);
classic_add_map(CLASSIC_CTRL_MAP, MOD_CTRL_MAP);
asdf_hook_assign(CLASSIC_ID_MESSAGE_HOOK, classic_caps_id_message);
asdf_hook_assign(APPLESOFT_KEYBOARD_TEST_HOOK, applesoft_keyboard_test);
// Assign power LED to virtual power LED, and initialize to ON
asdf_virtual_assign(CLASSIC_VIRTUAL_POWER_LED, CLASSIC_POWER_LED, V_NOFUNC, CLASSIC_POWER_LED_INIT_VALUE);
// Because the virtual power LED never changes, also assign the CAPSLOCK
// physical LED to the virtual Power LED, and intialize to OFF (or can change
// to ON depending on preference)
asdf_virtual_assign(CLASSIC_VIRTUAL_POWER_LED, CLASSIC_CAPS_LED, V_NOFUNC, CLASSIC_CAPS_LED_INIT_VALUE);
// assign RESET output to the virtual RESET output, configure to produce a short pulse when activated
asdf_virtual_assign(CLASSIC_VIRTUAL_RESET, CLASSIC_RESET_OUTPUT, V_PULSE_SHORT, !CLASSIC_RESET_ACTIVE_VALUE);
// assign the CLRSCR output to the virtual CLRSCR output, configure to produce a long pulse when activated
asdf_virtual_assign(CLASSIC_VIRTUAL_CLR_SCR, CLASSIC_CLR_SCR_OUT, V_PULSE_LONG, !CLASSIC_CLR_SCR_ACTIVE_VALUE);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,304 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps_apple2.h
//
// Apple 2 keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// This file supplies the Apple 2 ASCII keyboard keymap. Two variants are provided:
//
// 1) An Upper/Lowercase variant. This variant moves the @ and ^ symbols from
// the P and N keys to the REPEAT key, since the P and N keys need to reserve
// the shifted value for the uppercase characters. Also, the "Power" key
// doubles as a caps-lock key.
//
// 2) A CAPS only keyboard, following the standard Apple II conventions and
// layout, with ^ above the N key and @ above the P key, and a functioning
// REPEAT key.
//
// For both variants, CTRL+RESET is required for a system reset.
#if !defined(ASDF_KEYMAP_DEFS_APPLE2_H)
#define ASDF_KEYMAP_DEFS_APPLE2_H
// include DIP switch definitions
#include "asdf_keymap_defs_dipswitch.h"
// Edit the number of rows and columns used in this map. If the number is less
// than the maxium, the unused elements will be initialized to 0.
#define ASDF_APPLE2_NUM_ROWS 9 // DIP switches are row 8 (zero-based)
#define ASDF_APPLE2_NUM_COLS 8
#define APPLE_ACTION_RESET ACTION_VOUT1
#define APPLE_VIRTUAL_RESET VOUT1
#define APPLE_RESET_OUTPUT PHYSICAL_OUT3_OPEN_HI
#define APPLE_RESET_ACTIVE_VALUE 0
#define APPLE_ACTION_CLEAR ACTION_VOUT2
#define APPLE_VIRTUAL_CLR_SCR VOUT2
#define APPLE_CLR_SCR_OUTPUT PHYSICAL_OUT1_OPEN_LO
#define APPLE_CLR_SCR_ACTIVE_VALUE 1
#define APPLE_VIRTUAL_POWER_LED VLED1
#define APPLE_POWER_LED PHYSICAL_LED1
#define APPLE_POWER_LED_INIT_VALUE 1
#define APPLE_VIRTUAL_DISABLED_LED VLED2
#define APPLE_DISABLED_LED PHYSICAL_LED3
#define APPLE_DISABLED_INIT_VALUE 0
#define ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH 4
// The PLAIN map uses the "power" button as a caps-lock, so map the CAPS LED to
// the power button LED.
#define ASDF_APPLE2_PLAIN_KEYMAP_INITIALIZER \
{ \
{ .virtual_device = VCAPS_LED, .physical_device = APPLE_POWER_LED, .initial_value = 0 }, \
{ .virtual_device = APPLE_VIRTUAL_DISABLED_LED, \
.physical_device = APPLE_DISABLED_LED, \
.initial_value = 0 }, \
{ .virtual_device = APPLE_VIRTUAL_RESET, \
.physical_device = APPLE_RESET_OUTPUT, \
.function = V_PULSE_SHORT, \
.initial_value = !APPLE_RESET_ACTIVE_VALUE }, \
{ \
.virtual_device = APPLE_VIRTUAL_CLR_SCR, .physical_device = APPLE_CLR_SCR_OUTPUT, \
.function = V_PULSE_LONG, .initial_value = !APPLE_CLR_SCR_ACTIVE_VALUE \
} \
}
// The ALL CAPS map is the classic Apple II/II+ map. There is no CAPS LED, since
// CAPS doesn't matter in the ALL CAPS keymap.
#define ASDF_APPLE2_CAPS_KEYMAP_INITIALIZER \
{ \
{ .virtual_device = APPLE_VIRTUAL_POWER_LED, \
.physical_device = APPLE_POWER_LED, \
.initial_value = APPLE_POWER_LED_INIT_VALUE }, \
{ .virtual_device = APPLE_VIRTUAL_DISABLED_LED, \
.physical_device = APPLE_DISABLED_LED, \
.initial_value = 0 }, \
{ .virtual_device = APPLE_VIRTUAL_RESET, \
.physical_device = APPLE_RESET_OUTPUT, \
.function = V_PULSE_SHORT, \
.initial_value = !APPLE_RESET_ACTIVE_VALUE }, \
{ \
.virtual_device = APPLE_VIRTUAL_CLR_SCR, .physical_device = APPLE_CLR_SCR_OUTPUT, \
.function = V_PULSE_LONG, .initial_value = !APPLE_CLR_SCR_ACTIVE_VALUE \
} \
}
#define ASDF_APPLE2_KEYMAP_INITIALIZER \
ASDF_APPLE2_PLAIN_KEYMAP_INITIALIZER, ASDF_APPLE2_CAPS_KEYMAP_INITIALIZER
// Structure to initialize hooks. No hook functions are needed for APPLE2 keyboard.
#define ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER_LENGTH 0
#define ASDF_APPLE2_PLAIN_KEYMAP_HOOK_INITIALIZER \
{ \
}
#define ASDF_APPLE2_CAPS_KEYMAP_HOOK_INITIALIZER \
{ \
}
#define ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER \
ASDF_APPLE2_PLAIN_KEYMAP_HOOK_INITIALIZER, ASDF_APPLE2_CAPS_KEYMAP_HOOK_INITIALIZER
// Key Matrix for combination of ASCII controller and Classic ASCII matrix
//
// Col-> 0 1 2 3 4 5 6 7
// Row 0 POWER R-Shift L-Shift (no key) ESC TAB CTRL \(backslash)
// Row 1 Rubout P ; / SPACEBAR Z A Q
// Row 2 Break ,(comma) M N B V C X
// Row 3 Spare K J H G F D A
// Row 4 Rt arrow I U Y T R E W
// Row 5 LT arrow Repeat CapsLock Return LineFeed O(alpha) L .(period)
// Row 6 ~(tilde) ] [ -(dash) :(colon) 0(numeral) 9 8
// Row 7 @(at) 7 6 5 4 3 2 1
//
// Row 9 DIP switches 0-7
//
// Notes:
//
// 1) The keys above correspond to the silk screen on the PCB. For the OSI and
// Apple layouts, the keys may not all match the silk screen. When creating a
// layout different from the silk screen, look up the row and column for the
// silk screen label at the desired position, and then place the desired
// function in the keymap definition at the desired row and column. For
// example, the Apple 2 keymap places the "RESET" key at the "[" silk-screen
// position, Row 6, Col 2. The keymap places ACTION_RESET at Row 6, Col 2 in
// the "ASDF_APPLE2_CTRL_MAP" to map the RESET function to the CTRL-RESET key
// combination.
//
// 2) To ensure consistent DIP switch operation within the keymap, a
// ASDF_ASCII_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3
// definitions in positions 0-3 ensures consistent map selection among all
// keymaps.
#define ASDF_APPLE2_DIP_SWITCHES ASDF_KEYMAP_DIP_SWITCHES
#define APPLE_LEFT_ARROW ASCII_CTRL_H
#define APPLE_RIGHT_ARROW ASCII_CTRL_U
// clang-format off
#define ASDF_APPLE2_PLAIN_MAP \
{ \
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW }, \
[1] = { ASCII_DEL, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \
[2] = { ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \
[3] = { ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \
[4] = { ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, '^', 'o', 'l', ASCII_PERIOD }, \
[6] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, '-', ':', ASCII_ZERO, '9', '8' }, \
[7] = { APPLE_LEFT_ARROW, '7', '6', '5', '4', '3', '2', '1' }, \
ASDF_APPLE2_DIP_SWITCHES \
}
#define ASDF_APPLE2_SHIFT_MAP \
{ \
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW }, \
[1] = { ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \
[2] = { ACTION_NOTHING, '<', 'M', 'N', 'B', 'V', 'C', 'X' }, \
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, ASCII_AT, 'O', 'L', '>' }, \
[6] = { ACTION_NOTHING, ACTION_NOTHING, APPLE_ACTION_CLEAR, '=', \
'*', ASCII_ZERO, ASCII_RT_PAREN, ASCII_LT_PAREN }, \
[7] = { APPLE_LEFT_ARROW, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \
ASDF_APPLE2_DIP_SWITCHES \
}
#define ASDF_APPLE2_CAPS_MAP \
{ \
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW }, \
[1] = { ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \
[2] = { ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, ACTION_REPEAT, 'O', 'L', ASCII_PERIOD }, \
[6] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, '-', ':', ASCII_ZERO, '9', '8' }, \
[7] = { APPLE_LEFT_ARROW, '7', '6', '5', '4', '3', '2', '1' }, \
ASDF_APPLE2_DIP_SWITCHES \
}
#define ASDF_APPLE2_SHIFT_CAPS_MAP \
{ \
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW }, \
[1] = { ACTION_NOTHING, ASCII_AT, '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \
[2] = { ACTION_NOTHING, '<', 'M', '^', 'B', 'V', 'C', 'X' }, \
[3] = { ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
[4] = { ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, ACTION_REPEAT, 'O', 'L', '>' }, \
[6] = { ACTION_NOTHING, ACTION_NOTHING, APPLE_ACTION_CLEAR, '=', \
'*', ASCII_ZERO, ASCII_RT_PAREN, ASCII_LT_PAREN }, \
[7] = { APPLE_LEFT_ARROW, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \
ASDF_APPLE2_DIP_SWITCHES \
}
#define ASDF_APPLE2_CTRL_MAP \
{ \
[0] = { ACTION_CAPS, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, APPLE_RIGHT_ARROW }, \
[1] = { ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \
ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \
[2] = { ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \
ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \
[3] = { ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \
ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \
[4] = { ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \
ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \
[5] = { ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ASCII_CR, \
ACTION_REPEAT, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \
[6] = { ACTION_NOTHING, ACTION_NOTHING, APPLE_ACTION_RESET, ACTION_NOTHING, \
ACTION_NOTHING, ACTION_FN_10, ACTION_FN_9, ACTION_FN_8 }, \
[7] = { APPLE_LEFT_ARROW, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \
ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_1 }, \
ASDF_APPLE2_DIP_SWITCHES \
}
// clang-format on
#define ASDF_APPLE2_MAP_DECLARATIONS \
static const FLASH keycode_matrix_t apple2_plain_matrix = ASDF_APPLE2_PLAIN_MAP; \
static const FLASH keycode_matrix_t apple2_shift_matrix = ASDF_APPLE2_SHIFT_MAP; \
static const FLASH keycode_matrix_t apple2_caps_matrix = ASDF_APPLE2_CAPS_MAP; \
static const FLASH keycode_matrix_t apple2_caps_shift_matrix = ASDF_APPLE2_SHIFT_CAPS_MAP; \
static const FLASH keycode_matrix_t apple2_ctrl_matrix = ASDF_APPLE2_CTRL_MAP;
// Here, you can specify which maps are associated with which modifier keys.
// There can be multiple definitions. For example, as shown here, an ALL CAPS
// keymap can be made by assigning the caps map to the "no modifier" position.
// Or, more additional keymaps can be defined above, and keymap sets can be
// defined below that pick and choose between them. The modifiers are assigned as follows:
//
// [0]: plain (no modifiers)
// [1]: shift (shift key or shift lock active)
// [2]: caps (caps lock active)
// [3]: ctrl: (control key active)
#define ASDF_APPLE2_PLAIN_MAP_DEFS \
{ \
[MOD_PLAIN_MAP] = &apple2_plain_matrix, [MOD_SHIFT_MAP] = &apple2_shift_matrix, \
[MOD_CAPS_MAP] = &apple2_caps_matrix, [MOD_CTRL_MAP] = &apple2_ctrl_matrix \
}
#define ASDF_APPLE2_CAPS_MAP_DEFS \
{ \
[MOD_PLAIN_MAP] = &apple2_caps_matrix, [MOD_SHIFT_MAP] = &apple2_caps_shift_matrix, \
[MOD_CAPS_MAP] = &apple2_caps_matrix, [MOD_CTRL_MAP] = &apple2_ctrl_matrix \
}
#define ASDF_APPLE2_ALL_MAPS ASDF_APPLE2_PLAIN_MAP_DEFS, ASDF_APPLE2_CAPS_MAP_DEFS
#define ASDF_APPLE2_ALL_MAPS_COUNT 2
#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_APPLE2_NUM_ROWS)
#undef ASDF_NUM_ROWS
#define ASDF_NUM_ROWS ASDF_APPLE2_NUM_ROWS
#endif
#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_APPLE2_NUM_COLS)
#undef ASDF_NUM_COLS
#define ASDF_NUM_COLS ASDF_APPLE2_NUM_COLS
#endif
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_APPLE2_KEYMAP_INITIALIZER_LENGTH
#endif
#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH
#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_APPLE2_KEYMAP_HOOK_INITIALIZER_LENGTH
#endif
#endif /* !defined (ASDF_KEYMAP_DEFS_APPLE2_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,46 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_defs_dipswitch.h
//
// Contains defitions for DIP switch settings shared by all keymaps.
//
// Copyright 2019 David Fenyes
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#if !defined (DEPS_DIPSWITCH_H)
#define DEPS_DIPSWITCH_H
#define ASDF_KEYMAP_DIP_SWITCHES \
[ASDF_ARCH_DIPSWITCH_ROW] = { \
[0] = ACTION_MAPSEL_0, \
[1] = ACTION_MAPSEL_1, \
[2] = ACTION_MAPSEL_2, \
[3] = ACTION_MAPSEL_3, \
[6] = ACTION_STROBE_POLARITY_SELECT, \
[7] = ACTION_AUTOREPEAT_SELECT, \
}
//
// Device and peripheral definitions, comments should include use of devices.
// Please
//
#endif /* !defined (DEPS_DIPSWITCH_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,311 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps_sol.h
//
// Ascii keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// To use this ascii for a new keymap, edit the keymaps definitions as
// desired. The keymaps are organized from row 0, counting upward, and each row
// includes the columns from 0-NUM_COLS.
//
#if !defined(ASDF_KEYMAP_DEFS_SOL20_H)
#define ASDF_KEYMAP_DEFS_SOL20_H
// include DIP switch definitions
#include "asdf_keymap_defs_dipswitch.h"
// Edit the number of rows and columns used in this map. If the number is less
// than the maxium, the unused elements will be initialized to 0.
#define ASDF_SOL_NUM_ROWS 13 // DIP switches are row 9
#define ASDF_SOL_NUM_COLS 8
// Key Matrix for combination of ASCII controller (ATMega328P version) and Classic ASCII matrix
//
// Col-> 0 1 2 3 4 5 6 7
// Row 0 Lt Ctrl ShiftLock A S D F G(alpha) H
// Row 1 J K L ;(semi) :(colon) DEL Repeat Rt Ctrl
// Row 2 UpperCase Lt Shift Z X C V B(alpha) N
// Row 3 M ,(comma) .(period) /(slash) Rt Shift ModeSelect
// Row 4 ESC 1 2 3 4 5 6(six) 7
// Row 5 8(eight) 9 0(zero) -(Dash) ^(Caret) [ \ ]
// Row 6 BREAK TAB Q W E R T Y
// Row 7 U I O(alpha) P @(at) Return LineFeed Load
// Row 9 LOCAL UpArrow LtArrow Spacebar RtArrow DnArrow Home Clear
// Row 10 NP-Minus NP-7 NP-Times NP-8 NP-Divide NP-9 (none) (none)
// Row 11 NP-4 NP-1 NP-5 NP-2 NP-6 NP-3 (none) (none)
// Row 12 NP-0 NP-period NP-Plus
//
// Row 8 DIP switches 0-7
//
// Physical Resource mapping:
// LED1: UPPER CASE
// LED2: LOCAL
// LED3: SHIFT LOCK
// OUT1: RESET
// OUT2: BREAK
// OUT3: LOCAL
// Notes:
//
// 1) To ensure consistent DIP switch operation within the keymap, a
// ASDF_SOL_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3
// definitions in positions 0-3 ensures consistent map selection among all
// keymaps.
#define SOL_KBD_VRESET VOUT1
#define SOL_KBD_VBREAK VOUT2
#define SOL_KBD_VLOCAL VOUT3
#define SOL_KBD_LED_ON 1
#define SOL_KBD_LED_OFF 0
// The SOL manual (sec. 7.7.8) indicates shiftlock locks SHIFT on, and SHIFT
// returns to unshifted. For Toggle behavior, change to ACTION_SHIFTLOCK_TOGGLE.
#define SOL_KBD_SHIFTLOCK_ACTION ACTION_SHIFTLOCK_ON
// The weird C preprocessor expansion behavior requires one dereference for each
// expansion.
#define SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE) ACTION_ ## SOL_VDEVICE
#define SOL_KBD_VIRTUAL_SUB(SOL_VDEVICE) SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE)
#define SOL_KBD_LOCAL_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VLOCAL)
#define SOL_KBD_RESET_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VRESET)
#define SOL_KBD_BREAK_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VBREAK)
#define SOL_ASCII_LOAD 0x8C
#define SOL_ASCII_MODE_SELECT 0x80
#define SOL_ASCII_UP_ARROW 0x97
#define SOL_ASCII_LT_ARROW 0x81
#define SOL_ASCII_RT_ARROW 0x93
#define SOL_ASCII_DN_ARROW 0x9a
#define SOL_ASCII_HOME 0x8e
#define SOL_ASCII_CLEAR 0x8b
#define SOL_KBD_TTL_HIGH 1
#define SOL_KBD_TTL_LOW 0
#define SOL_KBD_LED_UPPERCASE PHYSICAL_LED1
#define SOL_KBD_LED_LOCAL PHYSICAL_LED2
#define SOL_KBD_LED_SHIFTLOCK PHYSICAL_LED3
#define SOL_KBD_TTLOUT_RESET PHYSICAL_OUT3_OPEN_HI // Emulate open collector output.
#define SOL_KBD_TTLOUT_BREAK PHYSICAL_OUT2
#define SOL_KBD_TTLOUT_LOCAL PHYSICAL_OUT1
#define ASDF_SOL_KEYMAP_INITIALIZER_LENGTH 6
// Notice that TTLOUT_LOCAL (OUT3) and LED_LOCAL (PHYSICAL_LED2) are both bound
// to the VLOCAL_OUT virtual device.
#define ASDF_SOL_KEYMAP_INITIALIZER \
{ \
{ .virtual_device = VCAPS_LED, \
.physical_device = SOL_KBD_LED_UPPERCASE, \
.initial_value = SOL_KBD_LED_OFF }, \
{ .virtual_device = VSHIFT_LED, \
.physical_device = SOL_KBD_LED_SHIFTLOCK, \
.initial_value = SOL_KBD_LED_OFF }, \
{ .virtual_device = SOL_KBD_VLOCAL, \
.physical_device = SOL_KBD_TTLOUT_LOCAL, \
.function = V_TOGGLE, \
.initial_value = SOL_KBD_TTL_HIGH }, \
{ .virtual_device = SOL_KBD_VLOCAL, \
.physical_device = SOL_KBD_LED_LOCAL, \
.function = V_TOGGLE, \
.initial_value = SOL_KBD_LED_OFF }, \
{ .virtual_device = SOL_KBD_VRESET, \
.physical_device = SOL_KBD_TTLOUT_RESET, \
.function = V_PULSE_SHORT, \
.initial_value = SOL_KBD_TTL_HIGH }, \
{ .virtual_device = SOL_KBD_VBREAK, \
.physical_device = SOL_KBD_TTLOUT_BREAK, \
.function = V_PULSE_LONG, \
.initial_value = SOL_KBD_TTL_HIGH }, \
}
// function hooks for the SOL keyboard:
// - At Setup, activate CAPSLOCK to emulate original keyboard.
// - At Setup, configure negative strobe
#define ASDF_SOL_KEYMAP_HOOK_INITIALIZER_LENGTH 2
#define ASDF_SOL_KEYMAP_HOOK_INITIALIZER \
{ \
{ .hook_id = ASDF_HOOK_KEYMAP_SETUP, \
.hook_func = asdf_modifier_capslock_activate, \
}, \
{ .hook_id = ASDF_HOOK_KEYMAP_SETUP, \
.hook_func = asdf_arch_set_neg_strobe, \
}, \
}
#define ASDF_SOL_DIP_SWITCHES ASDF_KEYMAP_DIP_SWITCHES
// clang-format off
#define ASDF_SOL_PLAIN_MAP \
{ \
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, 'a', 's', 'd', 'f', 'g', 'h' }, \
[1] = { 'j', 'k', 'l', ';', ':', ASCII_DEL, ACTION_REPEAT, ACTION_CTRL }, \
[2] = { ACTION_CAPS, ACTION_SHIFT, 'z', 'x', 'c', 'v', 'b', 'n' }, \
[3] = { 'm', ASCII_COMMA, ASCII_PERIOD, '/', \
ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING, ACTION_NOTHING }, \
[4] = { ASCII_ESC, '1', '2', '3', '4', '5', '6', '7' }, /**/ \
[5] = { '8', '9', ASCII_ZERO, '-', '^', \
ASCII_LT_SQUARE_BRACE, ASCII_BACKSLASH, ASCII_RT_SQUARE_BRACE }, \
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, 'q', 'w', 'e', 'r', 't', 'y' }, /**/ \
[7] = { 'u', 'i', 'o', 'p', ASCII_AT, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD }, \
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, \
ASCII_SPACE, SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, \
SOL_ASCII_HOME, SOL_ASCII_CLEAR }, \
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING }, \
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING }, \
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, \
ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING }, \
ASDF_SOL_DIP_SWITCHES, \
}
#define ASDF_SOL_CAPS_MAP \
{ \
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, 'A', 'S', 'D', 'F', 'G', 'H' }, \
[1] = { 'J', 'K', 'L', ';', ':', ASCII_DEL, ACTION_REPEAT, ACTION_CTRL }, \
[2] = { ACTION_CAPS, ACTION_SHIFT, 'Z', 'X', 'C', 'V', 'B', 'N' }, \
[3] = { 'M', ASCII_COMMA, ASCII_PERIOD, '/', \
ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING, ACTION_NOTHING }, \
[4] = { ASCII_ESC, '1', '2', '3', '4', '5', '6', '7' }, /**/ \
[5] = { '8', '9', ASCII_ZERO, '-', '^', \
ASCII_LT_SQUARE_BRACE, ASCII_BACKSLASH, ASCII_RT_SQUARE_BRACE }, \
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y' }, /**/ \
[7] = { 'U', 'I', 'O', 'P', ASCII_AT, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD }, \
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, \
ASCII_SPACE, SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, \
SOL_ASCII_HOME, SOL_ASCII_CLEAR }, \
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING }, \
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING }, \
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, \
ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING }, \
ASDF_SOL_DIP_SWITCHES, \
}
#define ASDF_SOL_SHIFT_MAP \
{ \
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, 'A', 'S', 'D', 'F', 'G', 'H' }, \
[1] = { 'J', 'K', 'L', ';', ':', ASCII_UNDERSCORE, ACTION_REPEAT, ACTION_CTRL }, \
[2] = { ACTION_CAPS, ACTION_SHIFT, 'Z', 'X', 'C', 'V', 'B', 'N' }, \
[3] = { 'M', '<', '>', '?', \
ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING, ACTION_NOTHING }, \
[4] = { ASCII_ESC, '!', ASCII_DOUBLE_QUOTE, '#', '$', '%', '&', ASCII_SINGLE_QUOTE }, \
[5] = { ASCII_LT_PAREN, ASCII_RT_PAREN, ASCII_SPACE, '=', ASCII_TILDE, \
ASCII_LT_SQUARE_BRACE, ASCII_BACKSLASH, ASCII_RT_SQUARE_BRACE }, \
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y' }, \
[7] = { 'U', 'I', 'O', 'P', ASCII_GRAVE_ACCENT, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD }, \
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, \
ASCII_SPACE, SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, \
SOL_ASCII_HOME, SOL_ASCII_CLEAR }, \
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING }, \
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING }, \
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, \
ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING }, \
ASDF_SOL_DIP_SWITCHES, \
}
#define ASDF_SOL_CTRL_MAP \
{ \
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, ASCII_CTRL_A, ASCII_CTRL_S, \
ASCII_CTRL_D, ASCII_CTRL_F, ASCII_CTRL_G, ASCII_CTRL_H }, \
[1] = { ASCII_CTRL_J, ASCII_CTRL_K, ASCII_CTRL_L, ASCII_VT, \
ASCII_LF, ASCII_DEL, SOL_KBD_RESET_ACTION, ACTION_CTRL }, \
[2] = { ACTION_CAPS, ACTION_SHIFT, ASCII_CTRL_Z, ASCII_CTRL_X, \
ASCII_CTRL_C, ASCII_CTRL_V, ASCII_CTRL_B, ASCII_CTRL_N }, \
[3] = { ASCII_CTRL_M, ASCII_FF, ASCII_SO, ASCII_SI, \
ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING, ACTION_NOTHING }, \
[4] = { ASCII_ESC, ASCII_SOH, ASCII_STX, ASCII_ETX, \
ASCII_EOT, ASCII_ENQ, ASCII_ACK, ASCII_BEL }, \
[5] = { ASCII_BS, ASCII_TAB, ASCII_NULL, ASCII_CR, ASCII_RS, \
ASCII_ESC, ASCII_FS, ASCII_GS }, \
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, ASCII_CTRL_Q, ASCII_CTRL_W, \
ASCII_CTRL_E, ASCII_CTRL_R, ASCII_CTRL_T, ASCII_CTRL_Y }, \
[7] = { ASCII_CTRL_U, ASCII_CTRL_I, ASCII_CTRL_O, ASCII_CTRL_P, \
ASCII_NULL, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD }, \
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, \
ASCII_SPACE, SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, \
SOL_ASCII_HOME, SOL_ASCII_CLEAR }, \
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING }, \
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING }, \
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, \
ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING }, \
ASDF_SOL_DIP_SWITCHES, \
}
// clang-format on
#define ASDF_SOL_MAP_DECLARATIONS \
static const FLASH keycode_matrix_t asdf_sol_plain_matrix = ASDF_SOL_PLAIN_MAP; \
static const FLASH keycode_matrix_t asdf_sol_shift_matrix = ASDF_SOL_SHIFT_MAP; \
static const FLASH keycode_matrix_t asdf_sol_caps_matrix = ASDF_SOL_CAPS_MAP; \
static const FLASH keycode_matrix_t asdf_sol_ctrl_matrix = ASDF_SOL_CTRL_MAP;
// Here, you can specify which maps are associated with which modifier keys.
// There can be multiple definitions. For example, as shown here, an ALL CAPS
// keymap can be made by assigning the caps map to the "no modifier" position.
// Or, more additional keymaps can be defined above, and keymap sets can be
// defined below that pick and choose between them. The modifiers are assigned as follows:
//
// [0]: plain (no modifiers)
// [1]: shift (shift key or shift lock active)
// [2]: caps (caps lock active)
// [3]: ctrl: (control key active)
#define ASDF_SOL_MAP_DEFS \
{ \
[MOD_PLAIN_MAP] = &asdf_sol_plain_matrix, [MOD_SHIFT_MAP] = &asdf_sol_shift_matrix, \
[MOD_CAPS_MAP] = &asdf_sol_caps_matrix, [MOD_CTRL_MAP] = &asdf_sol_ctrl_matrix \
}
#define ASDF_SOL_ALL_MAPS ASDF_SOL_MAP_DEFS
#define ASDF_SOL_ALL_MAPS_COUNT 1
#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_SOL_NUM_ROWS)
#undef ASDF_NUM_ROWS
#define ASDF_NUM_ROWS ASDF_SOL_NUM_ROWS
#endif
#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_SOL_NUM_COLS)
#undef ASDF_NUM_COLS
#define ASDF_NUM_COLS ASDF_SOL_NUM_COLS
#endif
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_SOL_KEYMAP_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_SOL_KEYMAP_INITIALIZER_LENGTH
#endif
#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_SOL_KEYMAP_HOOK_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH
#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_SOL_KEYMAP_HOOK_INITIALIZER_LENGTH
#endif
#endif /* !defined (ASDF_KEYMAP_DEFS_SOL20_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,275 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps.h
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// While there is nothing preventing a standard keyboard from having both a
// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For
// testing, both must be present to test their functionality.
#if !defined(ASDF_KEYMAP_DEFS_TEST_H)
#define ASDF_KEYMAP_DEFS_TEST_H
#define ASDF_TEST_NUM_ROWS 9
#define ASDF_TEST_NUM_COLS 8
// The first value in each row serves two purposes:
//
// 1) Indicate a valid row of codes if the value is nonzero.
// 2) Indicate the physical row number corresponding to the keymap row.
//
// Multiple keymaps may be combined, some of which use more rows than other
// keymaps. The keymap with the most rows determines how many rows are allocated
// for each keymap. Since each keymap only initializes the rows it uses, then
// the shorter keymaps may have multiple uninitialized rows that should not be
// scanned. The C99 standard guarantees that all elements no explicitly
// initialized shall be initialized to 0 (C99 Standard 6.7.8.21). Therefore,
// keymap rows starting with a 0 are not valid and are not scanned.
//
// Some hardware may contain blank physical rows To avoid having unused empty
// rows, the first column of each row indicates the physical row. For example, 8
// rows of switches (0-7), and a bank of DIP switches on row 15. In this case,
// only 9 rows need be allocated.
#define PLAIN_MATRIX_1 RESERVED_1
#define CAPS_MATRIX_1 RESERVED_2
#define SHIFT_MATRIX_1 RESERVED_3
#define CTRL_MATRIX_1 RESERVED_4
#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1)
#define ASDF_TEST_MAP_DIP_SWITCHES \
[ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 }
#define ASDF_TEST_PLAIN_MAP \
{ \
{ PLAIN_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \
{ ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \
{ ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \
{ ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \
/**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', \
'l', ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST_CAPS_MAP \
{ \
{ CAPS_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
/**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', \
'L', ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST_SHIFT_MAP \
{ \
\
{ SHIFT_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \
{ ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \
{ ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \
'0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \
{ ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \
ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST_CTRL_MAP \
{ \
{ CTRL_MATRIX_1, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \
{ ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \
ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \
{ ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \
ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \
{ ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \
ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \
{ ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \
ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, \
ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \
{ ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \
ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \
{ ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \
ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_2 }, \
ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST_DECLARATIONS \
static const FLASH keycode_matrix_t test_PLAIN_matrix = ASDF_TEST_PLAIN_MAP; \
static const FLASH keycode_matrix_t test_SHIFT_matrix = ASDF_TEST_SHIFT_MAP; \
static const FLASH keycode_matrix_t test_CAPS_matrix = ASDF_TEST_CAPS_MAP; \
static const FLASH keycode_matrix_t test_CTRL_matrix = ASDF_TEST_CTRL_MAP;
#define ASDF_TEST_MAP_DEFS \
{ \
&test_PLAIN_matrix, &test_SHIFT_matrix, &test_CAPS_matrix, &test_CTRL_matrix \
}
#define ASDF_TEST_CAPS_MAP_DEFS \
{ \
&test_CAPS_matrix, &test_SHIFT_matrix, &test_CAPS_matrix, &test_CTRL_matrix \
}
#define ASDF_TEST_KEYMAPS ASDF_TEST_MAP_DEFS, ASDF_TEST_CAPS_MAP_DEFS
#define ASDF_TEST_KEYMAPS_COUNT 2
#define ASDF_TEST_PLAIN_MAP_INDEX ASDF_TEST_BASE + 0
#define ASDF_TEST_CAPS_MAP_INDEX ASDF_TEST_BASE + 1
#define SINGLE_TESTS_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX
#define DOUBLE_ASSIGN_TEST_KEYMAP ASDF_TEST_PLAIN_MAP_INDEX
#define TRIPLE_TESTS_KEYMAP ASDF_TEST_CAPS_MAP_INDEX
#define ASDF_TEST_KEYMAP_INITIALIZER_LENGTH 5
#define ASDF_TEST_KEYMAP_INITIALIZER_1 \
{ \
{ \
/* Single assignment */ \
.virtual_device = VOUT1, \
.physical_device = PHYSICAL_OUT1, \
.function = V_NOFUNC, \
.initial_value = 0, \
}, \
{ \
/* single toggle */ \
.virtual_device = VOUT2, \
.physical_device = PHYSICAL_OUT2, \
.function = V_TOGGLE, \
.initial_value = 0, \
}, \
{ \
/* single pulse */ \
.virtual_device = VOUT3, \
.physical_device = PHYSICAL_OUT3, \
.function = V_PULSE_SHORT, \
.initial_value = 0, \
}, \
{ /* first of double assignment attempt */ \
.virtual_device = VOUT4, \
.physical_device = PHYSICAL_LED1, \
.initial_value = 0 \
}, \
{ /* second of double assignment attempt */ \
.virtual_device = VOUT5, .physical_device = PHYSICAL_LED1, .initial_value = 1 \
} \
}
#define ASDF_TEST_KEYMAP_INITIALIZER_2 \
{ \
{ \
/* Triple assignment */ \
.virtual_device = VOUT1, \
.physical_device = PHYSICAL_OUT1, \
.function = V_TOGGLE, \
.initial_value = 0, \
}, \
{ \
.virtual_device = VOUT1, \
.physical_device = PHYSICAL_OUT2, \
.function = V_TOGGLE, \
.initial_value = 1, \
}, \
{ \
.virtual_device = VOUT1, .physical_device = PHYSICAL_OUT3, .function = V_TOGGLE, \
.initial_value = 0, \
} \
}
#define ASDF_TEST_KEYMAP_INITIALIZER ASDF_TEST_KEYMAP_INITIALIZER_1, ASDF_TEST_KEYMAP_INITIALIZER_2
#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH 2
#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_1 \
{ \
{ \
.hook_id = ASDF_HOOK_KEYMAP_SETUP, \
.hook_func = &test_hook_1, \
}, \
{ \
.hook_id = ASDF_HOOK_KEYMAP_SETUP, \
.hook_func = &test_hook_2, \
}, \
}
#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER_2 \
{ \
{ \
.hook_id = ASDF_HOOK_KEYMAP_SETUP, \
.hook_func = &test_hook_3, \
}, \
{ \
.hook_id = ASDF_HOOK_KEYMAP_SETUP, \
.hook_func = &test_hook_4, \
}, \
}
#define ASDF_TEST_KEYMAP_HOOK_INITIALIZER \
ASDF_TEST_KEYMAP_HOOK_INITIALIZER_1, ASDF_TEST_KEYMAP_HOOK_INITIALIZER_2
// The following preprocessor "code" permits various keymaps to be created and
// included without generating a lot of complicating code dependencies. The use
// of macros in this way is a bit ugly, I realize, and stretches the intention
// of the C preprocessor. The C preprocessor is used to store a bit of state to
// keep track of the number and ordering of the keymaps as they are added, and
// to keep track of the array sizes to be allocated at compile time.
#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_TEST_NUM_ROWS)
#undef ASDF_NUM_ROWS
#define ASDF_NUM_ROWS ASDF_TEST_NUM_ROWS
#endif
#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_TEST_NUM_COLS)
#undef ASDF_NUM_COLS
#define ASDF_NUM_COLS ASDF_TEST_NUM_COLS
#endif
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST_KEYMAP_INITIALIZER_LENGTH
#endif
#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH
#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH
#endif
#endif /* !defined (ASDF_KEYMAP_DEFS_TEST_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,239 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps.h
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// While there is nothing preventing a standard keyboard from having both a
// "Shift Lock" key and a "Caps Lock" key, usually only one will be present. For
// testing, both must be present to test their functionality.
#if !defined(ASDF_KEYMAP_DEFS_TEST2_H)
#define ASDF_KEYMAP_DEFS_TEST2_H
#define ASDF_TEST2_NUM_ROWS 16
#define ASDF_TEST2_NUM_COLS 8
// The first value in each row serves two purposes:
//
// 1) Indicate a valid row of codes if the value is nonzero.
// 2) Indicate the physical row number corresponding to the keymap row.
//
// Multiple keymaps may be combined, some of which use more rows than other
// keymaps. The keymap with the most rows determines how many rows are allocated
// for each keymap. Since each keymap only initializes the rows it uses, then
// the shorter keymaps may have multiple uninitialized rows that should not be
// scanned. The C99 standard guarantees that all elements no explicitly
// initialized shall be initialized to 0 (C99 Standard 6.7.8.21). Therefore,
// keymap rows starting with a 0 are not valid and are not scanned.
//
// Some hardware may contain blank physical rows To avoid having unused empty
// rows, the first column of each row indicates the physical row. For example, 8
// rows of switches (0-7), and a bank of DIP switches on row 15. In this case,
// only 9 rows need be allocated.
#define PLAIN_MATRIX_2 RESERVED_5
#define CAPS_MATRIX_2 RESERVED_6
#define SHIFT_MATRIX_2 RESERVED_7
#define CTRL_MATRIX_2 RESERVED_8
#define ASDF_LAST_ROW (ASDF_NUM_ROWS - 1)
#define ASDF_TEST_MAP_DIP_SWITCHES \
[ASDF_LAST_ROW] = { ACTION_MAPSEL_0, ACTION_MAPSEL_1, ACTION_MAPSEL_2, ACTION_MAPSEL_3 }
#define ASDF_TEST2_PLAIN_MAP \
{ \
{ PLAIN_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_CAPS, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ACTION_NOTHING, 'p', ';', '/', ASCII_SPACE, 'z', 'a', 'q' }, \
{ ACTION_NOTHING, ASCII_COMMA, 'm', 'n', 'b', 'v', 'c', 'x' }, \
{ ACTION_NOTHING, 'k', 'j', 'h', 'g', 'f', 'd', 's' }, \
{ ACTION_NOTHING, 'i', 'u', 'y', 't', 'r', 'e', 'w' }, \
/**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'o', \
'l', ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST2_CAPS_MAP \
{ \
{ CAPS_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_BACKSLASH }, \
{ ACTION_NOTHING, 'P', ';', '/', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_NOTHING, ASCII_COMMA, 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
/**/ { ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', \
'L', ASCII_PERIOD }, \
{ ASCII_TILDE, ASCII_RT_SQUARE_BRACE, ASCII_LT_SQUARE_BRACE, '-', ':', '0', '9', '8' }, \
{ ACTION_NOTHING, '7', '6', '5', '4', '3', '2', '1' }, ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST2_SHIFT_MAP \
{ \
\
{ SHIFT_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, ASCII_VERT_BAR }, \
{ ACTION_NOTHING, 'P', '+', '?', ASCII_SPACE, 'Z', 'A', 'Q' }, \
{ ACTION_NOTHING, '>', 'M', 'N', 'B', 'V', 'C', 'X' }, \
{ ACTION_NOTHING, 'K', 'J', 'H', 'G', 'F', 'D', 'S' }, \
{ ACTION_NOTHING, 'I', 'U', 'Y', 'T', 'R', 'E', 'W' }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, ASCII_LF, 'O', 'L', '<' }, \
{ ASCII_TILDE, ASCII_RT_CURLY_BRACE, ASCII_LT_CURLY_BRACE, '=', '*', \
'0', ASCII_RT_PAREN, ASCII_LT_PAREN }, \
{ ACTION_NOTHING, ASCII_SINGLE_QUOTE, '&', '%', '$', '#', ASCII_DOUBLE_QUOTE, '!' }, \
ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST2_CTRL_MAP \
{ \
{ CTRL_MATRIX_2, ACTION_SHIFT, ACTION_SHIFT, ACTION_NOTHING, \
ACTION_NOTHING, ASCII_ESC, ACTION_CTRL, 0x1c }, \
{ ACTION_NOTHING, ASCII_CTRL_P, ACTION_NOTHING, ACTION_NOTHING, \
ASCII_SPACE, ASCII_CTRL_Z, ASCII_CTRL_A, ASCII_CTRL_Q }, \
{ ACTION_NOTHING, ASCII_COMMA, ASCII_CTRL_M, ASCII_CTRL_N, \
ASCII_CTRL_B, ASCII_CTRL_V, ASCII_CTRL_C, ASCII_CTRL_X }, \
{ ACTION_NOTHING, ASCII_CTRL_K, ASCII_CTRL_J, ASCII_CTRL_H, \
ASCII_CTRL_G, ASCII_CTRL_F, ASCII_CTRL_D, ASCII_CTRL_S }, \
{ ACTION_NOTHING, ASCII_CTRL_I, ASCII_CTRL_U, ASCII_CTRL_Y, \
ASCII_CTRL_T, ASCII_CTRL_R, ASCII_CTRL_E, ASCII_CTRL_W }, \
{ ACTION_REPEAT, ACTION_HERE_IS, ACTION_SHIFTLOCK_ON, ASCII_CR, \
ASCII_LF, ASCII_CTRL_O, ASCII_CTRL_L, ACTION_NOTHING }, \
{ ACTION_NOTHING, 0x1d, ASCII_ESC, ACTION_NOTHING, \
ACTION_NOTHING, ACTION_FN_1, ACTION_FN_9, ACTION_FN_8 }, \
{ ACTION_NOTHING, ACTION_FN_7, ACTION_FN_6, ACTION_FN_5, \
ACTION_FN_4, ACTION_FN_3, ACTION_FN_2, ACTION_FN_2 }, \
ASDF_TEST_MAP_DIP_SWITCHES \
}
#define ASDF_TEST2_DECLARATIONS \
static const FLASH keycode_matrix_t test2_PLAIN_matrix = ASDF_TEST2_PLAIN_MAP; \
static const FLASH keycode_matrix_t test2_SHIFT_matrix = ASDF_TEST2_SHIFT_MAP; \
static const FLASH keycode_matrix_t test2_CAPS_matrix = ASDF_TEST2_CAPS_MAP; \
static const FLASH keycode_matrix_t test2_CTRL_matrix = ASDF_TEST2_CTRL_MAP;
#define ASDF_TEST2_MAP_DEFS \
{ \
&test2_PLAIN_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
}
#define ASDF_TEST2_CAPS_MAP_DEFS \
{ \
&test2_CAPS_matrix, &test2_SHIFT_matrix, &test2_CAPS_matrix, &test2_CTRL_matrix \
}
#define ASDF_TEST2_KEYMAPS ASDF_TEST2_MAP_DEFS, ASDF_TEST2_CAPS_MAP_DEFS
#define ASDF_TEST2_KEYMAPS_COUNT 2
#define ASDF_TEST2_PLAIN_MAP_INDEX (ASDF_TEST2_BASE + 0)
#define ASDF_TEST2_CAPS_MAP_INDEX (ASDF_TEST2_BASE + 1)
#define VCAPS_TEST_KEYMAP ASDF_TEST2_PLAIN_MAP_INDEX
#define VSHIFT_TEST_KEYMAP ASDF_TEST2_PLAIN_MAP_INDEX
#define ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH 4
#define ASDF_TEST2_KEYMAP_INITIALIZER_1 \
{ \
{ .virtual_device = VCAPS_LED, .physical_device = PHYSICAL_LED1, .initial_value = 0 }, \
{ .virtual_device = VSHIFT_LED, .physical_device = PHYSICAL_LED2, .initial_value = 0 }, \
{ .virtual_device = VOUT2, .physical_device = PHYSICAL_OUT3, .initial_value = 0 }, \
{ \
.virtual_device = VOUT2, .physical_device = ASDF_PHYSICAL_NUM_RESOURCES, .initial_value = 0 \
} \
}
#define ASDF_TEST2_KEYMAP_INITIALIZER_2 \
{ \
{ .virtual_device = VCAPS_LED, .physical_device = PHYSICAL_LED1, .initial_value = 0 }, \
{ .virtual_device = VSHIFT_LED, .physical_device = PHYSICAL_LED2, .initial_value = 0 }, \
{ .virtual_device = VOUT2, .physical_device = PHYSICAL_OUT3, .initial_value = 0 }, \
{ \
.virtual_device = VOUT2, .physical_device = ASDF_PHYSICAL_NUM_RESOURCES, .initial_value = 0 \
} \
}
#define ASDF_TEST2_KEYMAP_INITIALIZER \
ASDF_TEST2_KEYMAP_INITIALIZER_1, ASDF_TEST2_KEYMAP_INITIALIZER_2
#define ASDF_TEST_ALTERNATE_SCANNER_MAP (ASDF_TEST2_BASE + 0)
#define ASDF_TEST_ALTERNATE_OUTPUT_MAP (ASDF_TEST2_BASE + 0)
#define ASDF_TEST_EACH_SCAN_MAP (ASDF_TEST2_BASE + 1)
#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_LENGTH 2
#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_1 \
{ \
{ \
.hook_id = ASDF_HOOK_SCANNER, \
.hook_func = (asdf_hook_function_t) test_hook_read_row, \
}, \
{ \
.hook_id = ASDF_HOOK_OUTPUT, \
.hook_func = (asdf_hook_function_t) test_hook_output, \
}, \
}
#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_2 \
{ \
{ \
.hook_id = ASDF_HOOK_EACH_SCAN, \
.hook_func = (asdf_hook_function_t) test_hook_each_scan, \
}, \
}
#define ASDF_TEST2_KEYMAP_HOOK_INITIALIZER \
ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_1, ASDF_TEST2_KEYMAP_HOOK_INITIALIZER_2
// The following preprocessor "code" permits various keymaps to be created and
// included without generating a lot of complicating code dependencies. The use
// of macros in this way is a bit ugly, I realize, and stretches the intention
// of the C preprocessor. The C preprocessor is used to store a bit of state to
// keep track of the number and ordering of the keymaps as they are added, and
// to keep track of the array sizes to be allocated at compile time.
#if !defined(ASDF_NUM_ROWS) || (ASDF_NUM_ROWS < ASDF_TEST2_NUM_ROWS)
#undef ASDF_NUM_ROWS
#define ASDF_NUM_ROWS ASDF_TEST2_NUM_ROWS
#endif
#if !defined(ASDF_NUM_COLS) || (ASDF_NUM_COLS < ASDF_TEST2_NUM_COLS)
#undef ASDF_NUM_COLS
#define ASDF_NUM_COLS ASDF_TEST2_NUM_COLS
#endif
#if !defined(ASDF_KEYMAP_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_INITIALIZER_LENGTH < ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_INITIALIZER_LENGTH
#define ASDF_KEYMAP_INITIALIZER_LENGTH ASDF_TEST2_KEYMAP_INITIALIZER_LENGTH
#endif
#if !defined(ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH) \
|| (ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH < ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH)
#undef ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH
#define ASDF_KEYMAP_HOOK_INITIALIZER_LENGTH ASDF_TEST_KEYMAP_HOOK_INITIALIZER_LENGTH
#endif
#endif /* !defined (ASDF_KEYMAP_DEFS_TEST2_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,187 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymap_sol.c
//
// Implements the keymap definition and setup routines for the sol-20 keymap
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#include "asdf_arch.h"
#include "asdf_keymap_sol.h"
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_modifiers.h"
#include "asdf_keymaps.h"
#include "asdf_print.h"
#define SOL_PRINT_DELAY 40 // msec
#define SOL_ID_MESSAGE_HOOK ASDF_HOOK_USER_10
static const FLASH asdf_keycode_t sol_plain_map[ASDF_SOL_NUM_ROWS][ASDF_SOL_NUM_COLS] = {
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, 'a', 's', 'd', 'f', 'g', 'h' },
[1] = { 'j', 'k', 'l', ';', ':', ASCII_DEL, ACTION_REPEAT, ACTION_CTRL },
[2] = { ACTION_CAPS, ACTION_SHIFT, 'z', 'x', 'c', 'v', 'b', 'n' },
[3] = { 'm', ASCII_COMMA, ASCII_PERIOD, '/', ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING,
ACTION_NOTHING },
[4] = { ASCII_ESC, '1', '2', '3', '4', '5', '6', '7' },
[5] = { '8', '9', ASCII_ZERO, '-', '^', ASCII_LT_SQUARE_BRACE, ASCII_BACKSLASH,
ASCII_RT_SQUARE_BRACE },
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, 'q', 'w', 'e', 'r', 't', 'y' },
[7] = { 'u', 'i', 'o', 'p', ASCII_AT, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD },
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, ASCII_SPACE,
SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, SOL_ASCII_HOME, SOL_ASCII_CLEAR },
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING },
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING },
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING,
ACTION_NOTHING },
ASDF_SOL_DIP_SWITCHES,
};
static const FLASH asdf_keycode_t sol_caps_map[ASDF_SOL_NUM_ROWS][ASDF_SOL_NUM_COLS] = {
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, 'A', 'S', 'D', 'F', 'G', 'H' },
[1] = { 'J', 'K', 'L', ';', ':', ASCII_DEL, ACTION_REPEAT, ACTION_CTRL },
[2] = { ACTION_CAPS, ACTION_SHIFT, 'Z', 'X', 'C', 'V', 'B', 'N' },
[3] = { 'M', ASCII_COMMA, ASCII_PERIOD, '/', ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING,
ACTION_NOTHING },
[4] = { ASCII_ESC, '1', '2', '3', '4', '5', '6', '7' }, /**/
[5] = { '8', '9', ASCII_ZERO, '-', '^', ASCII_LT_SQUARE_BRACE, ASCII_BACKSLASH,
ASCII_RT_SQUARE_BRACE },
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y' },
[7] = { 'U', 'I', 'O', 'P', ASCII_AT, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD },
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, ASCII_SPACE,
SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, SOL_ASCII_HOME, SOL_ASCII_CLEAR },
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING },
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING },
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING,
ACTION_NOTHING },
ASDF_SOL_DIP_SWITCHES,
};
static const FLASH asdf_keycode_t sol_shift_map[ASDF_SOL_NUM_ROWS][ASDF_SOL_NUM_COLS] = {
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, 'A', 'S', 'D', 'F', 'G', 'H' },
[1] = { 'J', 'K', 'L', ';', ':', ASCII_UNDERSCORE, ACTION_REPEAT, ACTION_CTRL },
[2] = { ACTION_CAPS, ACTION_SHIFT, 'Z', 'X', 'C', 'V', 'B', 'N' },
[3] = { 'M', '<', '>', '?', ACTION_SHIFT, SOL_ASCII_MODE_SELECT, ACTION_NOTHING, ACTION_NOTHING },
[4] = { ASCII_ESC, '!', ASCII_DOUBLE_QUOTE, '#', '$', '%', '&', ASCII_SINGLE_QUOTE },
[5] = { ASCII_LT_PAREN, ASCII_RT_PAREN, ASCII_SPACE, '=', ASCII_TILDE, ASCII_LT_SQUARE_BRACE,
ASCII_BACKSLASH, ASCII_RT_SQUARE_BRACE },
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y' },
[7] = { 'U', 'I', 'O', 'P', ASCII_GRAVE_ACCENT, ASCII_CR, ASCII_LF, SOL_ASCII_LOAD },
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, ASCII_SPACE,
SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, SOL_ASCII_HOME, SOL_ASCII_CLEAR },
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING },
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING },
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING,
ACTION_NOTHING },
ASDF_SOL_DIP_SWITCHES,
};
static const FLASH asdf_keycode_t sol_ctrl_map[ASDF_SOL_NUM_ROWS][ASDF_SOL_NUM_COLS] = {
[0] = { ACTION_CTRL, SOL_KBD_SHIFTLOCK_ACTION, ASCII_CTRL_A, ASCII_CTRL_S, ASCII_CTRL_D,
ASCII_CTRL_F, ASCII_CTRL_G, ASCII_CTRL_H },
[1] = { ASCII_CTRL_J, ASCII_CTRL_K, ASCII_CTRL_L, ASCII_VT, ASCII_LF, ASCII_DEL,
SOL_KBD_RESET_ACTION, ACTION_CTRL },
[2] = { ACTION_CAPS, ACTION_SHIFT, ASCII_CTRL_Z, ASCII_CTRL_X, ASCII_CTRL_C, ASCII_CTRL_V,
ASCII_CTRL_B, ASCII_CTRL_N },
[3] = { ASCII_CTRL_M, ASCII_FF, ASCII_SO, ASCII_SI, ACTION_SHIFT, SOL_ASCII_MODE_SELECT,
ACTION_NOTHING, ACTION_NOTHING },
[4] = { ASCII_ESC, ASCII_SOH, ASCII_STX, ASCII_ETX, ASCII_EOT, ASCII_ENQ, ASCII_ACK, ASCII_BEL },
[5] = { ASCII_BS, ASCII_TAB, ASCII_NULL, ASCII_CR, ASCII_RS, ASCII_ESC, ASCII_FS, ASCII_GS },
[6] = { SOL_KBD_BREAK_ACTION, ASCII_TAB, ASCII_CTRL_Q, ASCII_CTRL_W, ASCII_CTRL_E, ASCII_CTRL_R,
ASCII_CTRL_T, ASCII_CTRL_Y },
[7] = { ASCII_CTRL_U, ASCII_CTRL_I, ASCII_CTRL_O, ASCII_CTRL_P, ASCII_NULL, ASCII_CR, ASCII_LF,
SOL_ASCII_LOAD },
[9] = { SOL_KBD_LOCAL_ACTION, SOL_ASCII_UP_ARROW, SOL_ASCII_LT_ARROW, ASCII_SPACE,
SOL_ASCII_RT_ARROW, SOL_ASCII_DN_ARROW, SOL_ASCII_HOME, SOL_ASCII_CLEAR },
[10] = { '-', '7', '*', '8', '/', '9', ACTION_NOTHING, ACTION_NOTHING },
[11] = { '4', '1', '5', '2', '6', '3', ACTION_NOTHING, ACTION_NOTHING },
[12] = { '0', ASCII_PERIOD, '+', ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING, ACTION_NOTHING,
ACTION_NOTHING },
ASDF_SOL_DIP_SWITCHES,
};
// PROCEDURE: sol_add_map
// INPUTS: asdf_keycode_t (*matrix) - a SOL_NUM_ROWS x SOL_NUM_COLS matrix of keycodes for each physical row/column pair
// modifier_index_t modifier index - the modifier state corresponding to the keycode matrix
// OUTPUTS: none
// DESCRIPTION: Passes the keycode matrix and modifier state through to
// asdf_keymaps_add_map(), along with the row/column dimensions.
//
// SIDE EFFECTS: the matrix is added to the keymap
//
// SCOPE: private
//
// COMPLEXITY: 1
//
static void sol_add_map(const asdf_keycode_t (*matrix)[ASDF_SOL_NUM_COLS],
modifier_index_t modifier_index)
{
asdf_keymaps_add_map(&matrix[0][0], modifier_index, (uint8_t) ASDF_SOL_NUM_ROWS,
(uint8_t) ASDF_SOL_NUM_COLS);
}
static void sol_id_message(void)
{
asdf_print("[Keybd: Sol-20]");
}
void setup_sol_keymap(void)
{
sol_add_map(sol_plain_map, MOD_PLAIN_MAP);
sol_add_map(sol_caps_map, MOD_CAPS_MAP);
sol_add_map(sol_shift_map, MOD_SHIFT_MAP);
sol_add_map(sol_ctrl_map, MOD_CTRL_MAP);
asdf_set_print_delay(SOL_PRINT_DELAY);
// Set up the ALL CAPS LED, default = off
asdf_virtual_assign(VCAPS_LED, SOL_KBD_LED_UPPERCASE, V_NOFUNC, SOL_KBD_LED_OFF);
// Set up the SHIFT LED, default = off
asdf_virtual_assign(VSHIFT_LED, SOL_KBD_LED_SHIFTLOCK, V_NOFUNC, SOL_KBD_LED_OFF);
// Set up the LOCAL LED and output, default LED=OFF, TTL output HIGH. Both LED
// and TTL out are bound to the save virtual device.
asdf_virtual_assign(SOL_KBD_VLOCAL, SOL_KBD_TTLOUT_LOCAL, V_TOGGLE, SOL_KBD_TTL_HIGH);
asdf_virtual_assign(SOL_KBD_VLOCAL, SOL_KBD_LED_LOCAL, V_TOGGLE, SOL_KBD_LED_OFF);
// Set up the RESET output, produce a short pulse when activated. Default output HIGH
asdf_virtual_assign(SOL_KBD_VRESET, SOL_KBD_TTLOUT_RESET, V_PULSE_SHORT, SOL_KBD_TTL_HIGH);
// Set up the BREAK output, produce a long pulse when activated, default output high
asdf_virtual_assign(SOL_KBD_VBREAK, SOL_KBD_TTLOUT_BREAK, V_PULSE_LONG, SOL_KBD_TTL_HIGH);
// Activate the ALL CAPS mode to emulate the original keyboard:
asdf_modifier_capslock_activate();
// Configure negative strobe
asdf_arch_set_neg_strobe();
asdf_hook_assign(SOL_ID_MESSAGE_HOOK, sol_id_message);
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,127 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// asdf_keymaps_sol.h
//
// Ascii keymaps
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
// To use this ascii for a new keymap, edit the keymaps definitions as
// desired. The keymaps are organized from row 0, counting upward, and each row
// includes the columns from 0-NUM_COLS.
//
#if !defined(ASDF_KEYMAP_SOL_H)
#define ASDF_KEYMAP_SOL_H
#include "asdf.h"
#include "asdf_keymap_defs_dipswitch.h"
// Edit the number of rows and columns used in this map. If the number is less
// than the maxium, the unused elements will be initialized to 0.
#define ASDF_SOL_NUM_ROWS 13 // DIP switches are row 9
#define ASDF_SOL_NUM_COLS 8
// Key Matrix for combination of ASCII controller (ATMega328P version) and Classic ASCII matrix
//
// Col-> 0 1 2 3 4 5 6 7
// Row 0 Lt Ctrl ShiftLock A S D F G(alpha) H
// Row 1 J K L ;(semi) :(colon) DEL Repeat Rt Ctrl
// Row 2 UpperCase Lt Shift Z X C V B(alpha) N
// Row 3 M ,(comma) .(period) /(slash) Rt Shift ModeSelect
// Row 4 ESC 1 2 3 4 5 6(six) 7
// Row 5 8(eight) 9 0(zero) -(Dash) ^(Caret) [ \ ]
// Row 6 BREAK TAB Q W E R T Y
// Row 7 U I O(alpha) P @(at) Return LineFeed Load
// Row 9 LOCAL UpArrow LtArrow Spacebar RtArrow DnArrow Home Clear
// Row 10 NP-Minus NP-7 NP-Times NP-8 NP-Divide NP-9 (none) (none)
// Row 11 NP-4 NP-1 NP-5 NP-2 NP-6 NP-3 (none) (none)
// Row 12 NP-0 NP-period NP-Plus
//
// Row 8 DIP switches 0-7
//
// Physical Resource mapping:
// LED1: UPPER CASE
// LED2: LOCAL
// LED3: SHIFT LOCK
// OUT1: RESET
// OUT2: BREAK
// OUT3: LOCAL
// Notes:
//
// 1) To ensure consistent DIP switch operation within the keymap, a
// ASDF_SOL_DIP_SWITCHES macro is defined. Keeping the ACTION_MAPSEL0-3
// definitions in positions 0-3 ensures consistent map selection among all
// keymaps.
#define SOL_PRINT_DELAY 40 // msec
#define SOL_ID_MESSAGE_HOOK ASDF_HOOK_USER_10
#define SOL_NUM_ROWS 13
#define SOL_NUM_COLS 8
#define SOL_KBD_VRESET VOUT1
#define SOL_KBD_VBREAK VOUT2
#define SOL_KBD_VLOCAL VOUT3
#define SOL_KBD_LED_ON 1
#define SOL_KBD_LED_OFF 0
// The SOL manual (sec. 7.7.8) indicates shiftlock locks SHIFT on, and SHIFT
// returns to unshifted. For Toggle behavior, change to ACTION_SHIFTLOCK_TOGGLE.
#define SOL_KBD_SHIFTLOCK_ACTION ACTION_SHIFTLOCK_ON
// The weird C preprocessor expansion behavior requires one dereference for each
// expansion.
#define SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE) ACTION_ ## SOL_VDEVICE
#define SOL_KBD_VIRTUAL_SUB(SOL_VDEVICE) SOL_KBD_VIRTUAL_SUB1(SOL_VDEVICE)
#define SOL_KBD_LOCAL_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VLOCAL)
#define SOL_KBD_RESET_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VRESET)
#define SOL_KBD_BREAK_ACTION SOL_KBD_VIRTUAL_SUB(SOL_KBD_VBREAK)
#define SOL_ASCII_LOAD 0x8C
#define SOL_ASCII_MODE_SELECT 0x80
#define SOL_ASCII_UP_ARROW 0x97
#define SOL_ASCII_LT_ARROW 0x81
#define SOL_ASCII_RT_ARROW 0x93
#define SOL_ASCII_DN_ARROW 0x9a
#define SOL_ASCII_HOME 0x8e
#define SOL_ASCII_CLEAR 0x8b
#define SOL_KBD_TTL_HIGH 1
#define SOL_KBD_TTL_LOW 0
#define SOL_KBD_LED_UPPERCASE PHYSICAL_LED1
#define SOL_KBD_LED_LOCAL PHYSICAL_LED2
#define SOL_KBD_LED_SHIFTLOCK PHYSICAL_LED3
#define SOL_KBD_TTLOUT_RESET PHYSICAL_OUT3_OPEN_HI // Emulate open collector output.
#define SOL_KBD_TTLOUT_BREAK PHYSICAL_OUT2
#define SOL_KBD_TTLOUT_LOCAL PHYSICAL_OUT1
#define ASDF_SOL_DIP_SWITCHES ASDF_KEYMAP_DIP_SWITCHES
#endif /* !defined (ASDF_KEYMAP_SOL_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,14 +0,0 @@
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//

View File

@ -1,125 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// <FIXME-filename>.c
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
// Wiring Information:
// Chip: {Microcontroller type and version}
//
// Example:
// PIN NAME FUNCTION
// 3 AN1 ADC INPUT: Line sense analog input
//
// 6 A4 INPUT: (T0CK) COUNT DOWN from quadrature decoder.
// configured to count on rising edge, synced with xtal
//
//
// Headers
//
#include <version.h>
//
// Global Variable declarations: Use very sparingly. Used for communication
// with ISR's. Exceptions should be documented.
//
// Examples:
// run_clock_thread (global uns 8) when this is set to TRUE (by the
// clock_tick() ISR every 20 ms), the main loop performs certain
// actions, and resets the value to FALSE (see main loop comments)
//
uint8 send_count = FALSE;
//
// ISR routines
//
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// COMPLEXITY:
//
//
// Regular functions
//
// PROCEDURE:
// INPUTS:
// OUTPUTS:
//
// DESCRIPTION:
//
// SIDE EFFECTS:
//
// NOTES:
//
// SCOPE:
//
// COMPLEXITY:
//
// PROCEDURE: main()
//
// Main program loop; invoked at processor startup.
//
main()
{
// INITIALIZATION SECTION
cold_start:
// re-initialize variables and re-enter control loop, when the "R" command
// is received
warm_start:
// END OF INITIALIZATION SECTION
// Main Section:
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,41 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unfified Keyboard Project
// ASDF keyboard firmware
//
// <FIXME-filename>.h
//
// Copyright 2019 David Fenyes
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#if !defined (FILENAME_H)
#define FILENAME_H
//
// Headers
//
//
// Device and peripheral definitions, comments should include use of devices.
// Please
//
#endif /* !defined (FILENAME_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,46 +0,0 @@
---
BasedOnStyle: Mozilla
AlignAfterOpenBracket: Align
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'true'
BinPackArguments: 'true'
BinPackParameters: 'true'
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Stroustrup
ColumnLimit: '100'
ConstructorInitializerIndentWidth: '2'
ContinuationIndentWidth: '2'
DerivePointerAlignment: 'false'
DisableFormat: 'false'
IncludeBlocks: Preserve
IndentCaseLabels: 'true'
IndentPPDirectives: None
IndentWidth: '2'
IndentWrappedFunctionNames: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'true'
Language: Cpp
MaxEmptyLinesToKeep: '2'
PointerAlignment: Right
ReflowComments: 'true'
SortIncludes: 'false'
SpaceAfterCStyleCast: 'true'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '1'
SpacesInCStyleCastParentheses: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
TabWidth: '8'
UseTab: Never
...

View File

@ -1,667 +0,0 @@
// File recommented by recomment.cpp
// on Dec 9 2019 at 10:14:05.
//
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF firmware - small, fast, and simple keyboard encoder.
//
// asdf.c
//
// This file contains code for:
// - the main scan code and key handler routines
// - key matrix declarations and keyboard state variables not delegated
// elsewhere.
// - Key debouncing logic and data stuctures
// - dispatch of special functions bound to keys.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdint.h>
#include "asdf.h"
#include "asdf_ascii.h"
#include "asdf_physical.h"
#include "asdf_virtual.h"
#include "asdf_keymaps.h"
#include "asdf_repeat.h"
#include "asdf_modifiers.h"
#include "asdf_buffer.h"
#include "asdf_arch.h"
#include "asdf_hook.h"
// The key scanner keeps track of the last stable (debounced) state of each key
// in the matrix, one bit per key, 8 bits per row.
static asdf_cols_t last_stable_key_state[ASDF_MAX_ROWS];
// Each key is debounced separately, supporting true N-key rollover, allowing a
// new key to be pressed when the previously pressed key is still debouncing.
// This requires a debounce counter for each key. This is is a large RAM
// footprint, 64 bytes for an 8 x 8 key matrix. It would be possible to only
// debounce the most recently pressed key and reduce the RAM usage to a single
// debounce counuter. However, this would probably require different handling of
// key presses and releases, and special handling for modifier keys, perhaps
// including separate debounce logic in the handlers for toggle keys such as
// CAPS_LOCK.
static uint8_t debounce_counters[ASDF_MAX_ROWS][ASDF_MAX_COLS];
// Stores the last key pressed
static asdf_keycode_t last_key;
// This is the handle for the char output buffer
static asdf_buffer_handle_t asdf_keycode_buffer;
// This is the handle for the message output buffer
static asdf_buffer_handle_t asdf_message_buffer;
// The delay time for strings sent via parallel port. This is needed because
// most keyboards have no handshaking, and we need to allow time for various
// environments to process the characters. Some, such as basic interpreters, are
// rather slow. So we we allow keyboard modules to modifiy this delay.
static uint16_t asdf_print_delay_ms;
// PROCEDURE: asdf_put_code
// INPUTS: (asdf_keycode_t) code: code to be buffered for output
// OUTPUTS: none
//
// DESCRIPTION: Takes a keycode argument and buffers for output.
//
// SIDE EFFECTS: modifies buffer state.
//
// NOTES: If buffer is full, silently drop the code.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_put_code(asdf_keycode_t code)
{
asdf_buffer_put(asdf_keycode_buffer, code);
}
// PROCEDURE: asdf_putc
// INPUTS: (char) c: character to be buffered for output
// (FILE *) stream - only used to match prototype.
// OUTPUTS: none
//
// DESCRIPTION: Takes a character generated by the system and buffers for
// output.
//
// SIDE EFFECTS: modifies buffer state.
//
// NOTES: If buffer is full, silently drop the code.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
int asdf_putc(char c, FILE *stream)
{
// for messages, add CR to LF:
if ('\n' == c) {
asdf_putc('\r', stream);
}
asdf_buffer_put(asdf_message_buffer, (asdf_keycode_t) c);
return (int) c;
}
// PROCEDURE: asdf_next_code
// INPUTS: none
//
// OUTPUTS: (asdf_keycode_t) returns next value in buffer. If both buffers are
// empty, the code ASDF_INVALID_CODE is returned.
//
// DESCRIPTION: Checks the message buffer, and returns a character
// if present. Otherwise, return the next code in the keycode
// buffer.
//
// SIDE EFFECTS: modifies buffer state.
//
// NOTES: A delay is enforced for system messages, to reduce the risk of dropped
// characters with unbuffered polling hosts. No delay is needed for typed
// keycodes, as these are generated at human speeds.
//
// SCOPE: public
//
// COMPLEXITY: 2
//
asdf_keycode_t asdf_next_code(void)
{
asdf_keycode_t code = asdf_buffer_get(asdf_message_buffer);
if (ASDF_INVALID_CODE == code) {
code = asdf_buffer_get(asdf_keycode_buffer);
} else {
// for system message
asdf_arch_delay_ms(asdf_print_delay_ms);
}
return code;
}
// PROCEDURE: asdf_set_print_delay
// INPUTS: (uint8_t) delay_ms
//
// OUTPUTS: none
//
// DESCRIPTION: sets the delay to be used by the system print buffer
//
// SIDE EFFECTS: modifies character delay variable.
//
// NOTES: A delay is enforced for system messages, to reduce the risk of dropped
// characters with unbuffered polling hosts. No delay is needed for typed
// keycodes, as these are generated at human speeds.
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_set_print_delay(uint8_t delay_ms)
{
asdf_print_delay_ms = delay_ms;
}
// PROCEDURE: asdf_lookup_keycode
// INPUTS: row, col: specify a row and column in the keyboard matrix
// OUTPUTS: returns a keycode
//
// DESCRIPTION: Given a row and column in the keyboard matrix, returns the
// corresponding keycode, depending on the state of the modifier keys.
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 1
//
asdf_keycode_t asdf_lookup_keycode(uint8_t row, uint8_t col)
{
return asdf_keymaps_get_code(row, col, asdf_modifier_index());
}
// PROCEDURE: asdf_activate_action
// INPUTS: keycode: an action key code
// OUTPUTS: none
//
// DESCRIPTION: This routine is called when a key bound to an action code is
// pressed, and maps the action code to a function call, or other action
// appropriate for activation of the function.
//
// SIDE EFFECTS: All the actions may have side effects, depending on the function called.
//
// SCOPE: private
//
// NOTES: The switch() could be implemented as an array of function pointers,
// essentially a jump table. However, the switch statement will also be
// implemented as a jump table, and may be more efficiently implemented as a
// code jump table than an array of pointers stored in flash that would require
// an additional flash-read operation. Also, the switch jumptable will make more
// efficient use of space than a sparse array of function pointers. The
// reduction in cyclometric complexity by using an array is a technicality,
// since the elements must still be entered as lines of code in some part of the
// program. Here, they are arranged in the place they are used.
//
// COMPLEXITY: 1 (+18 for the switch)
//
static void asdf_activate_action(action_t keycode)
{
switch (keycode) {
case ACTION_SHIFT: {
asdf_modifier_shift_activate();
break;
}
case ACTION_SHIFTLOCK_ON: {
asdf_modifier_shiftlock_on_activate();
break;
}
case ACTION_SHIFTLOCK_TOGGLE: {
asdf_modifier_shiftlock_toggle_activate();
break;
}
case ACTION_CAPS: {
asdf_modifier_capslock_activate();
break;
}
case ACTION_CTRL: {
asdf_modifier_ctrl_activate();
break;
}
case ACTION_REPEAT: {
asdf_repeat_activate();
break;
}
case ACTION_MAPSEL_0: {
asdf_keymaps_map_select_0_set();
break;
}
case ACTION_MAPSEL_1: {
asdf_keymaps_map_select_1_set();
break;
}
case ACTION_MAPSEL_2: {
asdf_keymaps_map_select_2_set();
break;
}
case ACTION_MAPSEL_3: {
asdf_keymaps_map_select_3_set();
break;
}
case ACTION_STROBE_POLARITY_SELECT: {
asdf_arch_set_pos_strobe();
break;
}
case ACTION_AUTOREPEAT_SELECT: {
asdf_repeat_auto_on();
break;
}
case ACTION_VLED1: {
asdf_virtual_activate(VLED1);
break;
}
case ACTION_VLED2: {
asdf_virtual_activate(VLED2);
break;
}
case ACTION_VLED3: {
asdf_virtual_activate(VLED3);
break;
}
case ACTION_VOUT1: {
asdf_virtual_activate(VOUT1);
break;
}
case ACTION_VOUT2: {
asdf_virtual_activate(VOUT2);
break;
}
case ACTION_VOUT3: {
asdf_virtual_activate(VOUT3);
break;
}
case ACTION_VOUT4: {
asdf_virtual_activate(VOUT4);
break;
}
case ACTION_VOUT5: {
asdf_virtual_activate(VOUT5);
break;
}
case ACTION_VOUT6: {
asdf_virtual_activate(VOUT6);
break;
}
case ACTION_NOTHING:
case ACTION_HERE_IS:
case ACTION_FN_1:
asdf_hook_execute(ASDF_HOOK_USER_1);
break;
case ACTION_FN_2:
asdf_hook_execute(ASDF_HOOK_USER_2);
break;
case ACTION_FN_3:
asdf_hook_execute(ASDF_HOOK_USER_3);
break;
case ACTION_FN_4:
asdf_hook_execute(ASDF_HOOK_USER_4);
break;
case ACTION_FN_5:
asdf_hook_execute(ASDF_HOOK_USER_5);
break;
case ACTION_FN_6:
asdf_hook_execute(ASDF_HOOK_USER_6);
break;
case ACTION_FN_7:
asdf_hook_execute(ASDF_HOOK_USER_7);
break;
case ACTION_FN_8:
asdf_hook_execute(ASDF_HOOK_USER_8);
break;
case ACTION_FN_9:
asdf_hook_execute(ASDF_HOOK_USER_9);
break;
case ACTION_FN_10:
asdf_hook_execute(ASDF_HOOK_USER_10);
break;
default: break;
}
}
// PROCEDURE: asdf_deactivate_action
// INPUTS: keycode: an action key code
// OUTPUTS: none
//
// DESCRIPTION: This routine is called when a key bound to an action code is
// released, and maps the action code to a function call, or other action
// appropriate for deactivation of the function.
//
// SIDE EFFECTS: All the actions may have side effects, depending on the function called.
//
// SCOPE: private
//
// NOTES: See NOTE for asdf_activate_action(). The Virtual Outputs have
// activate() functions, but no deactivate() functions, and are handled by the
// default case.
//
// COMPLEXITY: 1 (+9 for the switch, see note)
//
static void asdf_deactivate_action(action_t keycode)
{
switch (keycode) {
case ACTION_SHIFT: {
asdf_modifier_shift_deactivate();
break;
}
case ACTION_CTRL: {
asdf_modifier_ctrl_deactivate();
break;
}
case ACTION_REPEAT: {
asdf_repeat_deactivate();
break;
}
case ACTION_MAPSEL_0: {
asdf_keymaps_map_select_0_clear();
break;
}
case ACTION_MAPSEL_1: {
asdf_keymaps_map_select_1_clear();
break;
}
case ACTION_MAPSEL_2: {
asdf_keymaps_map_select_2_clear();
break;
}
case ACTION_MAPSEL_3: {
asdf_keymaps_map_select_3_clear();
break;
}
case ACTION_STROBE_POLARITY_SELECT: {
asdf_arch_set_neg_strobe();
break;
}
case ACTION_AUTOREPEAT_SELECT: {
asdf_repeat_auto_off();
break;
}
case ACTION_NOTHING:
default: break;
}
}
// PROCEDURE: asdf_activate_key
// INPUTS: keycode - the code for a key that has been pressed.
// OUTPUTS: none
//
// DESCRIPTION: Called when a key has been pressed. If the key is bound to a
// value, output the value. If the key is bound to an action, call the activate action
// handler with the keycode.
//
// SIDE EFFECTS: If the code is a value, the last key is updated to the current
// value, and repeat timer is reset. If the code is an action code, the activate
// action dispatcher produces side effects. See asdf_activate_action()
//
// SCOPE: private
//
// COMPLEXITY: 3
//
static void asdf_activate_key(asdf_keycode_t keycode)
{
if (keycode > ASDF_ACTION) { // ASDF_ACTION = ASDF_NOTHING = no action.
asdf_activate_action((action_t) keycode);
}
else {
// activate a new codable keypress
asdf_put_code(keycode);
if (last_key != keycode) {
last_key = keycode;
asdf_repeat_reset_count();
}
}
}
// PROCEDURE: asdf_deactivate_key
// INPUTS: keycode - the code for a key that has been released
// OUTPUTS: none
//
// DESCRIPTION: Called when a key has been released. If the key is bound to a
// value, output the value. If the key is bound to an action, call the deactivate
// action handler with the keycode.
//
// SIDE EFFECTS: If the code is a value, the last key is set to ACTION_NOTHING,
// which is effectively a NOP. If the code is an action code, the deactivate action
// dispatcher produces side effects. See asdf_deactivate_action()
//
// SCOPE: private
//
// COMPLEXITY: 3
//
static void asdf_deactivate_key(asdf_keycode_t keycode)
{
if (keycode > ASDF_ACTION) {
asdf_deactivate_action((action_t) keycode);
}
else {
// deactivate a released keypress
if (last_key == keycode) {
last_key = ACTION_NOTHING;
}
}
}
// PROCEDURE: asdf_handle_key_press_or_release
// INPUTS: row, col: the row and column number of the key that has changed.
// OUTPUTS: none
//
// DESCRIPTION: Given a row and column of a key that has changed:
//
// 1) Debounce the key by decrementing a debounce timer. If not yet debounced,
// return.
// 2) When the key is debounced, if the key is pressed, then call the activation
// function associated with the key. Otherwise, if the key is released, call
// the deactivation function for the key.
//
// SIDE EFFECTS: - Modifies debounce counter for the row and column
// - After key debounces, modifies the table of stable key states
// - Activate/deactivate functions have side effects
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 3
//
static void asdf_handle_key_press_or_release(uint8_t row, uint8_t col, uint8_t key_was_pressed)
{
uint8_t *debounce_count = &debounce_counters[row][col];
if (!(--(*debounce_count))) {
// debounce timed out. Set new stable state and activate or
// deactivate key.
*debounce_count = ASDF_DEBOUNCE_TIME_MS;
if (key_was_pressed) {
last_stable_key_state[row] |= 1 << col;
asdf_activate_key(asdf_lookup_keycode(row, col));
}
else {
// key was released
last_stable_key_state[row] &= ~(1 << col);
asdf_deactivate_key(asdf_lookup_keycode(row, col));
}
}
}
// PROCEDURE: asdf_handle_key_held_pressed
// INPUTS: row, col: The row and column of a key that is being held down
// OUTPUTS: none
//
// DESCRIPTION: Given a row and column of a key that has been debounced and
// continues to be pressed:
// 1) Determine if this is the last key pressed.
// 2) If it's the most recent key, then check to see if it's time to repeat the key code.
// 3) If it's time to repeat, then do the repeat and reset the repeat timer.
//
// SIDE EFFECTS:
// - Causes repeat timer to tick, and may reset the repeat timer.
// - activate_key() will send a key code.
//
// NOTES: last_key is always a key code, never an action function, so only valid
// key codes will be repeated.
//
// SCOPE: private
//
// COMPLEXITY: 3
//
static void asdf_handle_key_held_pressed(uint8_t row, uint8_t col)
{
if (asdf_lookup_keycode(row, col) == last_key) {
// if last debounced code-producing key is still pressed, handle repeat
if (asdf_repeat()) {
asdf_activate_key(last_key);
}
}
}
// PROCEDURE: asdf_keyscan
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Scans the key matrix. For each row, read the columns and compare
// with last stable state. For each changed key, call a key-change handler
// function. For each stable pressed key, call a "continued press" handler
// function.
//
// SIDE EFFECTS:
//
// NOTES: 1) The keyboard state is stored as an array of words, with one word
// per row, and each bit in a word representing one key in the row.
//
// 2) While it is tempting to use bit hacks to reduce the number of
// cycles through the inner loop, I have opted to just loop over all
// the bits (as long as there are some changed or pressed keys). For
// an 8-bit word, bit tricks don't deliver much performance boost,
// but do decrease code clarity.
//
// COMPLEXITY: 5
//
void asdf_keyscan(void)
{
asdf_cols_t (*row_reader)(uint8_t) = (asdf_cols_t(*)(uint8_t)) asdf_hook_get(ASDF_HOOK_SCANNER);
asdf_hook_execute(ASDF_HOOK_EACH_SCAN);
for (uint8_t row = 0; row < asdf_keymaps_num_rows(); row++) {
asdf_cols_t row_key_state = (*row_reader)(row);
asdf_cols_t changed = row_key_state ^ last_stable_key_state[row];
// loop over the bits until all changed or pressed keys in the row are handled.
for (uint8_t col = 0; /*(changed || row_key_state) && */col < asdf_keymaps_num_cols(); col++) {
if (changed & 1) {
// key state is different from last stable state
asdf_handle_key_press_or_release(row, col, row_key_state & 1);
}
else if (row_key_state & 1) {
asdf_handle_key_held_pressed(row, col);
}
changed >>= 1;
row_key_state >>= 1;
}
}
}
// PROCEDURE: asdf_apply_all_actions
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Scans the key matrix. For each row, read the columns, and for
// each bit, if an action is specified, then call the activate or deactivate
// function for that action, based on the key state. This is necessary to ensure
// that configuration settings, such as DIP switches and jumper settings, are
// properly handled when a keymap is changed.
// SIDE EFFECTS: See DESCRIPTION
//
// COMPLEXITY: 5
//
// SCOPE: private
//
void asdf_apply_all_actions(void)
{
asdf_cols_t (*row_reader)(uint8_t) = (asdf_cols_t(*)(uint8_t)) asdf_hook_get(ASDF_HOOK_SCANNER);
for (uint8_t row = 0; row < asdf_keymaps_num_rows(); row++) {
asdf_cols_t row_key_state = (*row_reader)(row);
// To avoid double actions, assign last stable key state to current state.
last_stable_key_state[row] = row_key_state;
// loop over the bits until all changed or pressed keys in the row are handled.
for (uint8_t col = 0; col < asdf_keymaps_num_cols(); col++) {
asdf_keycode_t code = asdf_lookup_keycode(row, col);
if (row_key_state & 1) {
asdf_activate_action(code);
} else {
asdf_deactivate_action(code);
}
row_key_state >>= 1;
}
}
}
// PROCEDURE: asdf_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Reserve an output buffer to hold keycodes to be sent, and
// initialize the keyboard state and debounce counters
//
// SIDE EFFECTS: see DESCRIPTION
//
// SCOPE: public
//
// COMPLEXITY: 3
//
void asdf_init(void)
{
last_key = ACTION_NOTHING;
asdf_buffer_init(); // initialize the buffers
asdf_repeat_init(); // initialize the repeat counters
asdf_keymaps_init(); // initialize keymaps. This also initializes the modifier
// key states.
// reserve a buffer for the ASCII output:
asdf_keycode_buffer = asdf_buffer_new(ASDF_KEYCODE_BUFFER_SIZE);
asdf_message_buffer = asdf_buffer_new(ASDF_MESSAGE_BUFFER_SIZE);
// Initialize all the keys to the unpressed state, and initialze the debounce
// counters.
for (uint8_t row = 0; row < ASDF_MAX_ROWS; row++) {
last_stable_key_state[row] = 0;
for (uint8_t col = 0; col < ASDF_MAX_COLS; col++) {
debounce_counters[row][col] = ASDF_DEBOUNCE_TIME_MS;
}
}
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,163 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf.h
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#if !defined(ASDF_H)
#define ASDF_H
#include <stdio.h>
#include <stdint.h>
// Define the code at which keyboard actions begin. Codes below this value are
// values to be transmitted to the host machine. Codes above this value are
// actions to be performed.
#define ASDF_ACTION 0xA0 // SOL-20 uses codes 0x80-0x9A
// an action code is not a valid keycode.
#define ASDF_INVALID_CODE ASDF_ACTION
// define ASDF_MAX_COLS to fit in asdf_cols_t
#define ASDF_MAX_COLS 8
#define ASDF_MAX_ROWS 16
// for efficiency on 8-bit machines, use 8 columns per row. For 16 columns per
// row, change cols_t to uint16_t and increase ASDF_NUM_COLS to 16.
typedef uint8_t asdf_cols_t;
// ASCII keycodes are 7 bits. An 8-bit datatype encodes ASCII, plus a flag for a
// key function. For longer codes, such as extended ASCII or unicode, change
// keycode_t appropriately, and also change ASDF_ACTION so that the action key
// codes (enumerated in action_t) do not conflict with the encoding scheme.
typedef uint8_t asdf_keycode_t;
// This typedef enumerates the valid ACTIONS than can be specified in a keymap.
typedef enum {
ACTION_NOTHING = ASDF_ACTION,
ACTION_SHIFT,
ACTION_SHIFTLOCK_ON,
ACTION_SHIFTLOCK_TOGGLE,
ACTION_CAPS,
ACTION_CTRL,
ACTION_REPEAT,
ACTION_HERE_IS,
ACTION_MAPSEL_0,
ACTION_MAPSEL_1,
ACTION_MAPSEL_2,
ACTION_MAPSEL_3,
ACTION_AUTOREPEAT_SELECT,
ACTION_STROBE_POLARITY_SELECT,
ACTION_VLED1,
ACTION_VLED2,
ACTION_VLED3,
ACTION_VOUT1,
ACTION_VOUT2,
ACTION_VOUT3,
ACTION_VOUT4,
ACTION_VOUT5,
ACTION_VOUT6,
ACTION_FN_1,
ACTION_FN_2,
ACTION_FN_3,
ACTION_FN_4,
ACTION_FN_5,
ACTION_FN_6,
ACTION_FN_7,
ACTION_FN_8,
ACTION_FN_9,
ACTION_FN_10,
RESERVED_1,
RESERVED_2,
RESERVED_3,
RESERVED_4,
RESERVED_5,
RESERVED_6,
RESERVED_7,
RESERVED_8,
RESERVED_9,
RESERVED_10,
RESERVED_11,
RESERVED_12,
RESERVED_13,
RESERVED_14,
RESERVED_15,
RESERVED_16,
} action_t;
// PROCEDURE: asdf_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: initialize the keyboard state and debounce counters
void asdf_init(void);
// PROCEDURE: asdf_keyscan
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Scans the key matrix. For each row, read the columns and compare
// with last stable state. For each changed key, call a key-change handler
// function. For each stable pressed key, call a "continued press" handler
// function.
void asdf_keyscan(void);
// PROCEDURE: asdf_put_code
// INPUTS: (asdf_keycode_t) code: code to be buffered for output
// OUTPUTS: none
// DESCRIPTION: Takes a keycode argument and buffers for output.
// NOTES: If buffer is full, silently drop the code.
void asdf_put_code(asdf_keycode_t code);
// PROCEDURE: asdf_putc
// INPUTS: (char) c: character to be buffered for output
// (FILE*) stream: only for prototype matching
// OUTPUTS: none
// DESCRIPTION: Takes a character generated by the system and buffers for
// output.
// NOTES: If buffer is full, silently drop the code.
int asdf_putc(char c, FILE *stream);
// PROCEDURE: asdf_next_code
// INPUTS: none
// OUTPUTS: (asdf_keycode_t) returns next value in buffer. If both buffers are
// empty, the code ASDF_INVALID_CODE is returned.
// DESCRIPTION: Checks the message buffer, and returns a character
// if present. Otherwise, return the next code in the keycode
// buffer.
// NOTES: A delay is enforced for system messages, to reduce the risk of dropped
// characters with unbuffered polling hosts. No delay is needed for typed
// keycodes, as these are generated at human speeds.
asdf_keycode_t asdf_next_code(void);
// PROCEDURE: asdf_set_print_delay
// INPUTS: (uint8_t) delay_ms
// OUTPUTS: none
// DESCRIPTION: sets the delay to be used by the system print buffer
// NOTES: A delay is enforced for system messages, to reduce the risk of dropped
// characters with unbuffered polling hosts. No delay is needed for typed
// keycodes, as these are generated at human speeds.
void asdf_set_print_delay(uint8_t delay_ms);
#endif // !defined (ASDF_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,121 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_ascii.h
//
// This file contains definitions of ASCII control codes and certain symbols for
// keymap definitions. The purpose is to improve readability and consistency of
// the keymap matrices, and avoid escaping special characters in the keymap
// definitions.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#if !defined(ASDF_ASCII_H)
#define ASDF_ASCII_H
// List of all ASCII control codes
typedef enum {
ASCII_NULL = 0x00,
ASCII_CTRL_A = 0x01,
ASCII_CTRL_B = 0x02,
ASCII_CTRL_C = 0x03,
ASCII_CTRL_D = 0x04,
ASCII_CTRL_E = 0x05,
ASCII_CTRL_F = 0x06,
ASCII_CTRL_G = 0x07,
ASCII_CTRL_H = 0x08,
ASCII_CTRL_I = 0x09,
ASCII_CTRL_J = 0x0a,
ASCII_CTRL_K = 0x0b,
ASCII_CTRL_L = 0x0c,
ASCII_CTRL_M = 0x0d,
ASCII_CTRL_N = 0x0e,
ASCII_CTRL_O = 0x0f,
ASCII_CTRL_P = 0x10,
ASCII_CTRL_Q = 0x11,
ASCII_CTRL_R = 0x12,
ASCII_CTRL_S = 0x13,
ASCII_CTRL_T = 0x14,
ASCII_CTRL_U = 0x15,
ASCII_CTRL_V = 0x16,
ASCII_CTRL_W = 0x17,
ASCII_CTRL_X = 0x18,
ASCII_CTRL_Y = 0x19,
ASCII_CTRL_Z = 0x1a,
ASCII_ESC = 0x1b,
ASCII_FS = 0x1c, // File Separator
ASCII_GS = 0x1d, // Group Separator
ASCII_RS = 0x1e, // Record Separator
ASCII_US = 0x1f, // Unit Separator
ASCII_SPACE = 0x20,
ASCII_DOUBLE_QUOTE = 0x22,
ASCII_SINGLE_QUOTE = 0x27,
ASCII_LT_PAREN = 0x28,
ASCII_RT_PAREN = 0x29,
ASCII_COMMA = 0x2C,
ASCII_PERIOD = 0x2e,
ASCII_ZERO = 0x30,
ASCII_AT = 0x40,
ASCII_LT_SQUARE_BRACE = 0x5b,
ASCII_RT_SQUARE_BRACE = 0x5d,
ASCII_UNDERSCORE = 0x5f,
ASCII_BACKSLASH = 0x5c,
ASCII_GRAVE_ACCENT = 0x60,
ASCII_LT_CURLY_BRACE = 0x7b,
ASCII_RT_CURLY_BRACE = 0x7d,
ASCII_TILDE = 0x7e,
ASCII_VERT_BAR = 0x7c,
ASCII_DEL = 0x7f
} ascii_defs_t;
#define ASCII_NULL 0
#define ASCII_SOH ASCII_CTRL_A // Start of Heading
#define ASCII_STX ASCII_CTRL_B // Start of Text
#define ASCII_ETX ASCII_CTRL_C // End of Text
#define ASCII_EOT ASCII_CTRL_D // End of Transmission
#define ASCII_ENQ ASCII_CTRL_E // Enquiry
#define ASCII_ACK ASCII_CTRL_F // Acknlowledge
#define ASCII_BEL ASCII_CTRL_G // Bell
#define ASCII_BS ASCII_CTRL_H // Backspace
#define ASCII_TAB ASCII_CTRL_I // Horizontal Tab
#define ASCII_LF ASCII_CTRL_J // Line Feed
#define ASCII_VT ASCII_CTRL_K // Vertical Tab
#define ASCII_FF ASCII_CTRL_L // Form Feed
#define ASCII_CR ASCII_CTRL_M // Carriage Return
#define ASCII_SO ASCII_CTRL_N // Shift Out
#define ASCII_SI ASCII_CTRL_O // Shift In
#define ASCII_DLE ASCII_CTRL_P // Data Link Escape
#define ASCII_DC1 ASCII_CTRL_Q // Device Control 1
#define ASCII_DC2 ASCII_CTRL_R // Device Control 2
#define ASCII_DC3 ASCII_CTRL_S // Device Control 3
#define ASCII_DC4 ASCII_CTRL_T // Device Control 4
#define ASCII_NAK ASCII_CTRL_U // Negative Acknlowledge
#define ASCII_SYN ASCII_CTRL_V // Synchronous Idle
#define ASCII_ETB ASCII_CTRL_W // End of Transmission Block
#define ASCII_CAN ASCII_CTRL_X // Cancel
#define ASCII_EM ASCII_CTRL_Y // End of Medium
#define ASCII_SUB ASCII_CTRL_Z // Substitute
#define ASCII_ESC 0x1b
#define ASCII_
#endif // !defined (ASDF_ASCII_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,205 +0,0 @@
// -*- mode: C; tab-width: 2 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_buffer.c
//
// This is a circular buffer module that can be used by any part of the code
// that requires buffering. Buffering provides an interface between the
// generation of keycodes and the hardware-level keycode transmission, which may
// occur at different rates.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdint.h>
#include "asdf.h"
#include "asdf_buffer.h"
// Implementation Notes:
//
// 1) Note that this implementation does not support dynamic allocation and
// freeing of buffers. Each buffer is allocated at startup and is stable forever
// afterwards.
//
// 2) Buffer handles are indices into an array of buffer-tracking structures.
// Using indices rather than pointers incurs a small performance penalty for the
// extra level of indirection, but affords the advantage of testing the buffer
// handle for validity.
// Define the low-level details for each buffer.
typedef struct {
asdf_keycode_t *buf;
int16_t size;
uint8_t head;
uint8_t tail;
uint8_t count;
} asdf_buffer_t;
// This is the pool of codes available for buffering. This pool is divided among
// the allocated buffers.
static asdf_keycode_t buffer_pool[ASDF_BUFFER_POOL_SIZE];
// This array stores the buffering details for each allocated buffer. The number
// of available buffers is defined in the header file.
static asdf_buffer_t buffers[ASDF_BUFFER_NUM_HANDLES];
// Index of the beginning of unallocated part of the buffer pool.
static int16_t buffer_pool_next_available;
// Index of the next available buffer handle
static asdf_buffer_handle_t next_handle;
// PROCEDURE: asdf_buffer_init
// INPUTS: none
// OUTPUTS: none
//
// DESCRIPTION: Initialize the buffer pool and handles
//
// SIDE EFFECTS: See description
//
// NOTES:
//
// SCOPE: public
//
// COMPLEXITY: 1
//
void asdf_buffer_init(void)
{
buffer_pool_next_available = 0;
next_handle = 0;
}
// PROCEDURE: buffer_handle_valid
// INPUTS: (uint8_t) handle - handle to be checked
// OUTPUTS: returns TRUE if the handle is a valid allocated handle.
//
// DESCRIPTION: Returns TRUE if the handle is one that has been allocated.
//
// SIDE EFFECTS: none
//
// NOTES:
//
// SCOPE: private
//
// COMPLEXITY: 1
//
uint8_t buffer_handle_valid(asdf_buffer_handle_t handle)
{
return ((handle >= 0) && (handle < next_handle));
}
// PROCEDURE: asdf_buffer_new
// INPUTS: (uint16_t) size: size of the buffer to allocate.
//
// OUTPUTS: returns a uint8_t handle to identify the buffer allocated from the
// pool.
//
// DESCRIPTION: Receives a request to allocate a fixed-size buffer from the
// pool. If there is enough room in the buffer pool, and if a buffer handle is
// available, then allocate space from the pool, initialize the next available
// buffer struct, and return the handle.
//
// SIDE EFFECTS: see above
//
// SCOPE: public
//
// COMPLEXITY: 3
//
asdf_buffer_handle_t asdf_buffer_new(int16_t size)
{
asdf_buffer_handle_t handle = ASDF_BUFFER_INVALID;
if (next_handle < ASDF_BUFFER_NUM_HANDLES) {
if (size <= (ASDF_BUFFER_POOL_SIZE - buffer_pool_next_available)) {
handle = next_handle++;
buffers[handle].size = size;
buffers[handle].buf = &buffer_pool[buffer_pool_next_available];
buffers[handle].head = 0;
buffers[handle].tail = 0;
buffers[handle].count = 0;
buffer_pool_next_available += size;
}
}
return handle;
}
// PROCEDURE: asdf_buffer_put
//
// INPUTS:(asdf_buffer_t) buffer_handle: pointer to the buffer struct.
// (asdf_keycode_t) code: code to be added to the queue.
//
// OUTPUTS: None
//
// DESCRIPTION: Add the keycode to the head of the output buffer. If the buffer
// is full, quietly drop the keycode.
//
// SIDE EFFECTS: See DESCRIPTION
//
// NOTES:
//
// COMPLEXITY: 3
//
// SCOPE: public
//
void asdf_buffer_put(asdf_buffer_handle_t handle, asdf_keycode_t code)
{
if (buffer_handle_valid(handle)) {
if (buffers[handle].count < buffers[handle].size) {
buffers[handle].buf[buffers[handle].head] = code;
buffers[handle].head = (buffers[handle].head + 1) % buffers[handle].size;
buffers[handle].count++;
}
}
}
// PROCEDURE: asdf_buffer_get
//
// INPUTS: None
//
// OUTPUTS: returns next code in the buffer.
//
// DESCRIPTION: Gets the next queued code in the output buffer and return the
// value.
//
// SIDE EFFECTS: Removes a code from the queue.
//
// NOTES: If the buffer is empty, the code ASDF_INVALID_CODE is returned.
//
// COMPLEXITY: 2
//
// SCOPE: Public
//
asdf_keycode_t asdf_buffer_get(asdf_buffer_handle_t handle)
{
asdf_keycode_t code = ASDF_INVALID_CODE;
if (buffer_handle_valid(handle) && buffers[handle].count) {
code = buffers[handle].buf[buffers[handle].tail];
buffers[handle].tail = (buffers[handle].tail + 1) % buffers[handle].size;
buffers[handle].count--;
}
return code;
}
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,78 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Unified Keyboard Project
// ASDF keyboard firmware
//
// asdf_buffer.h
//
// Contains definitions and prototypes for the asdf keycode output buffer.
//
// Copyright 2019 David Fenyes
//
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#if !defined(ASDF_BUFFER_H)
#define ASDF_BUFFER_H
// ASDF_BUFFER_POOL_SIZE is defined in asdf_config.h
#include "asdf_config.h"
// Used to designate an invalid buffer.
#define ASDF_BUFFER_INVALID -1
// Setting the number of handles to 1 will work if only one buffer is requrired,
// and will save a few bytes of RAM. But the test code needs at least 2 buffer
// handles to test the module, so we leave it at 2.
#define ASDF_BUFFER_NUM_HANDLES 4
// The buffer handle type should be able to handle the expected number of buffers.
typedef int8_t asdf_buffer_handle_t;
// PROCEDURE: asdf_buffer_init
// INPUTS: none
// OUTPUTS: none
// DESCRIPTION: Initialize the buffer pool and handles
void asdf_buffer_init(void);
// PROCEDURE: asdf_buffer_new
// INPUTS: (uint16_t) size: size of the buffer to allocate.
// OUTPUTS: returns (asdf_buffer_handle_t) handle to identify the buffer allocated from the
// pool.
// DESCRIPTION: Receives a request to allocate a fixed-size buffer from the
// pool. If there is enough room in the buffer pool, and if a buffer handle is
// available, then allocate space from the pool, initialize the next available
// buffer struct, and return the handle.
asdf_buffer_handle_t asdf_buffer_new(int16_t size);
// PROCEDURE: asdf_buffer_put
// INPUTS:(asdf_buffer_t) buffer_handle: pointer to the buffer struct.
// (asdf_keycode_t) code: code to be added to the queue.
// OUTPUTS: None
// DESCRIPTION: Add the keycode to the head of the output buffer. If the buffer
// is full, quietly drop the keycode.
void asdf_buffer_put(asdf_buffer_handle_t handle, asdf_keycode_t code);
// PROCEDURE: asdf_buffer_get
// INPUTS: None
// OUTPUTS: returns next code in the buffer.
// DESCRIPTION: Gets the next queued code in the output buffer and return the
// value.
asdf_keycode_t asdf_buffer_get(asdf_buffer_handle_t handle);
#endif // !defined (ASDF_BUFFER_H)
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

View File

@ -1,89 +0,0 @@
// -*- mode: C; tab-width: 4 ; indent-tabs-mode: nil -*-
//
// Universal Keyboard Project
// ASDF keyboard firmware
//
// asdf_config.h
//
// This file gathers configuration parameters related to the user-detectable
// keyboard experience. For example, put key debounce times, repeat rates,
// buffer sized, baud rates, etc. here. Details such as processor clock speed,
// etc. should go in the architecture-dependent files. System details such as
// number of buffer handles, etc. should go with the appropriate module, but
// certain buffer sized may go here if they can affect the user experience (such
// as how long a macro can be).
//
// Copyright 2019 David Fenyes
// 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 3 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, see <https://www.gnu.org/licenses/>.
//
#if !defined(CONFIG_H)
#define CONFIG_H
#define ASDF_POSITIVE_POLARITY 0
#define ASDF_NEGATIVE_POLARITY (~ASDF_POSITIVE_POLARITY)
// data polarity is positive (inactive is low, active is high)
#define ASDF_DEFAULT_DATA_POLARITY ASDF_POSITIVE_POLARITY
// Strobe polarity is positive (inactive is low, active is high)
#define ASDF_DEFAULT_STROBE_POLARITY ASDF_POSITIVE_POLARITY
// RESET output polarity is negative (inactive is high, active is low)
#define ASDF_DEFAULT_RESET_POLARITY ASDF_NEGATIVE_POLARITY
// SCREEN_CLEAR output polarity is positive (inactive is low, active is high)
#define ASDF_DEFAULT_SCREEN_CLEAR_POLARITY ASDF_POSITIVE_POLARITY
// Data structure sizes:
// size of the keycode output buffer.
#define ASDF_KEYCODE_BUFFER_SIZE 16
#define ASDF_MESSAGE_BUFFER_SIZE 128
#define ASDF_BUFFER_POOL_SIZE (ASDF_MESSAGE_BUFFER_SIZE + ASDF_KEYCODE_BUFFER_SIZE)
// key debounce period (in msec)
#define ASDF_DEBOUNCE_TIME_MS 10
// Autorepeat default behavior. Set to REPEAT_AUTO for default autorepeat.
// Set to REPEAT_OFF for default no autorepeat by default.
#define ASDF_DEFAULT_REPEAT_STATE REPEAT_AUTO
// time to wait before sending consecutive message characters to the host, to
// ensure that messages are intact on hosts that poll the port without
// buffering. (in msec)
#define ASDF_MESSAGE_CHARACTER_DELAY 16 //msec
// time to hold down a key in milliseconds before autorepeat starts
#define ASDF_AUTOREPEAT_TIME_MS 525 // 525 msec.
// time between repeats of a character with repeat key held, or in autorepeat (milliseconds)
#define ASDF_REPEAT_TIME_MS (1000 / 15) // l5 characters per sec.
// duration of keyboard output pulses (RESET, SCREEN CLEAR, BREAK, etc.)
#define ASDF_PULSE_DELAY_SHORT_US 10
// duration of keyboard output pulses (RESET, SCREEN CLEAR, BREAK, etc.)
#define ASDF_PULSE_DELAY_LONG_MS 50
// DEFAULT value of keyboard outputs
#define ASDF_VIRTUAL_OUT_DEFAULT_VALUE 1 // High if not used.
#endif /* !defined (CONFIG_H) */
//-------|---------|---------+---------+---------+---------+---------+---------+
// Above line is 80 columns, and should display completely in the editor.

Some files were not shown because too many files have changed in this diff Show More