Compare commits
2 Commits
8b2e7c2752
...
7fce58e481
Author | SHA1 | Date | |
---|---|---|---|
7fce58e481 | |||
d86ac8d52d |
@ -289,11 +289,12 @@ TAB_SIZE = 4
|
|||||||
# with the commands \{ and \} for these it is advised to use the version @{ and
|
# with the commands \{ and \} for these it is advised to use the version @{ and
|
||||||
# @} or use a double escape (\\{ and \\})
|
# @} or use a double escape (\\{ and \\})
|
||||||
|
|
||||||
ALIASES = "modifies=\xrefitem modifies \"Modifies Registers\" \"Modified Registers\"" \
|
ALIASES = "modifies=\par Modifies Registers^^" \
|
||||||
"type=\xrefitem type \"Code Type\" \"Code Type\"" \
|
"type=\xrefitem type \"Code Type\" \"Code Type\"" \
|
||||||
"macro=\qualifier macro \brief" \
|
"macro=\qualifier macro \brief" \
|
||||||
"function=\qualifier subroutine \brief" \
|
"function=\qualifier subroutine \brief" \
|
||||||
"module=\file ^^ \brief"
|
"module=\file ^^ \brief" \
|
||||||
|
"clock_dependant=\xrefitem clock_dependant \"Clock Speed Dependance\" \"Clock frequency dependant code\""
|
||||||
|
|
||||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||||
# only. Doxygen will then generate output that is more tailored for C. For
|
# only. Doxygen will then generate output that is more tailored for C. For
|
||||||
@ -529,7 +530,8 @@ TIMESTAMP = NO
|
|||||||
# normally produced when WARNINGS is set to YES.
|
# normally produced when WARNINGS is set to YES.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_ALL = NO
|
# TODO Document everyhing
|
||||||
|
EXTRACT_ALL = YES
|
||||||
|
|
||||||
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
|
||||||
# be included in the documentation.
|
# be included in the documentation.
|
||||||
@ -954,7 +956,7 @@ WARN_LOGFILE =
|
|||||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = . build programs system util
|
INPUT = . build programs system util .extra_docs.s65 doxy-asm65.py
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@ -994,10 +996,8 @@ INPUT_FILE_ENCODING =
|
|||||||
# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||||
# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||||
|
|
||||||
FILE_PATTERNS = *.cpp \
|
FILE_PATTERNS = *.s65 \
|
||||||
*.s65 \
|
*.h65
|
||||||
*.h65 \
|
|
||||||
*.md
|
|
||||||
|
|
||||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||||
# be searched for input files as well.
|
# be searched for input files as well.
|
||||||
@ -1124,7 +1124,7 @@ FILTER_SOURCE_PATTERNS =
|
|||||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||||
# and want to reuse the introduction page also for the doxygen output.
|
# and want to reuse the introduction page also for the doxygen output.
|
||||||
|
|
||||||
USE_MDFILE_AS_MAINPAGE = #../README.md
|
USE_MDFILE_AS_MAINPAGE =
|
||||||
|
|
||||||
# The Fortran standard specifies that for fixed formatted Fortran code all
|
# The Fortran standard specifies that for fixed formatted Fortran code all
|
||||||
# characters from position 72 are to be considered as comment. A common
|
# characters from position 72 are to be considered as comment. A common
|
||||||
@ -1364,7 +1364,7 @@ HTML_STYLESHEET =
|
|||||||
# documentation.
|
# documentation.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_EXTRA_STYLESHEET = #../docs/doxygen-awesome-css/doxygen-awesome.css
|
HTML_EXTRA_STYLESHEET = ../docs/custom/doxygen-awesome.css
|
||||||
|
|
||||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||||
# other source files which should be copied to the HTML output directory. Note
|
# other source files which should be copied to the HTML output directory. Note
|
||||||
|
67
.extra_docs.s65
Normal file
67
.extra_docs.s65
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
;;********************************************************************************
|
||||||
|
;; @mainpage 8-bit Breadboard Computer with W65C02S Processor
|
||||||
|
;; This repo contains the assembly code for my [6502-project](https://quintern.xyz/de/posts/2021_6502).
|
||||||
|
;;
|
||||||
|
;; The assembler used for this project is the excellent [ca65](https://github.com/cc65/cc65).
|
||||||
|
;; After assembling it, the binary is loaded onto the EEPROM using [my *eeprom.py* script](https://git.quintern.xyz/MatthiasQuintern/AT28C256-rpi-util) on a Raspberry Pi 4B.
|
||||||
|
;;
|
||||||
|
;; @section main_os Operating System
|
||||||
|
;; ... is probably a far stretch, since it is just the programs I wrote pieced together. My "OS" consists of these functionalities:
|
||||||
|
;; - Supported Hardware:
|
||||||
|
;; - 4x4 Matrix Keypad
|
||||||
|
;; - 4x16 Characters LCD Display
|
||||||
|
;; - PS/2 Keyboard
|
||||||
|
;; - SPI Connection to an Arduino
|
||||||
|
;; - Software
|
||||||
|
;; - @ref ps2_keyboard_printer "Keyboard" and @ref keypad_printer "keypad printer": Prints the characters you press on to the lcd
|
||||||
|
;; <!-- - Temperature: Shows the temperature using a dht sensor. *Work in progress, this does not work yet* -->
|
||||||
|
;; - @ref print_slow "(Stylishly)" print @ref "str::strf" "formated strings" to the LCD
|
||||||
|
;; - @ref sleep "Sleep"
|
||||||
|
;; - Send @ref ps2_keyboard_util "various commands" to the keyboard
|
||||||
|
;; - @ref ringbuffer "Ringbuffer"
|
||||||
|
;;
|
||||||
|
;; > It's not much, but it's honest work.
|
||||||
|
;;
|
||||||
|
;; @section main_hardware Hardware details
|
||||||
|
;; @subsection main_hw_addr Address Space
|
||||||
|
;; |Name|From|To|r/w|
|
||||||
|
;; |---|---:|---:|:---:|
|
||||||
|
;; |ZEROPAGE |$00 |$ff |`rw`|
|
||||||
|
;; |STACK |$100 |$1ff |`rw`|
|
||||||
|
;; |RAM |$200 |$4fff |`rw`|
|
||||||
|
;; |SPI |$5000 |$5fff |`rw`|
|
||||||
|
;; |VIA1 |$6000 |$600f |`rw`|
|
||||||
|
;; |VIA2 |$7000 |$700f |`rw`|
|
||||||
|
;; |ROM |$8000 |$ffff |`r `|
|
||||||
|
;;
|
||||||
|
;;
|
||||||
|
;; @section main_software Software details
|
||||||
|
;; @subsection main_sw_naming Naming conventions
|
||||||
|
;; leading underscors `_` indicate a "private" label/variable, that is meant for internal use within the module only.
|
||||||
|
;;
|
||||||
|
;; **Labels**:
|
||||||
|
;; - **scopes**: snake case
|
||||||
|
;; - **subroutines** and **variables**: snake case (`scope::(_)fname_snake_case` or `scope::(_)varname_2`)
|
||||||
|
;; - **macros**: camel case (`(_)GoodMacroname` or `scope_GoodMacroname`)
|
||||||
|
;; - **constants** (eg. in ROM): upper case (`scope::(_)NICE_SYMBOLNAME`)
|
||||||
|
;; - **enums**: upper case (`scope::(_)ENUM_NAME::ENUM_MEMBER`)
|
||||||
|
;;********************************************************************************
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @defgroup applications
|
||||||
|
;; @brief Applications that do ... *something*
|
||||||
|
;;
|
||||||
|
;;********************************************************************************
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @defgroup drivers
|
||||||
|
;; @brief Code that handles a physical device
|
||||||
|
;;
|
||||||
|
;;********************************************************************************
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @defgroup utility
|
||||||
|
;; @brief Code that does something useful and is intended to be used in other code
|
||||||
|
;;
|
||||||
|
;;********************************************************************************
|
||||||
|
|
19
details.md
19
details.md
@ -1,19 +0,0 @@
|
|||||||
# Project details
|
|
||||||
## Address Space
|
|
||||||
|Name|From|To|r/w|
|
|
||||||
|---|---:|---:|:---:|
|
|
||||||
|ZEROPAGE |$00 |$ff |`rw`|
|
|
||||||
|STACK |$100 |$1ff |`rw`|
|
|
||||||
|RAM |$200 |$4fff |`rw`|
|
|
||||||
|SPI |$5000 |$5fff |`rw`|
|
|
||||||
|VIA1 |$6000 |$600f |`rw`|
|
|
||||||
|VIA2 |$7000 |$700f |`rw`|
|
|
||||||
|ROM |$8000 |$ffff |`r `|
|
|
||||||
|
|
||||||
## Naming conventions
|
|
||||||
leading underscors `_` indicate a "private" label/variable, that is meant for internal use within the module only.
|
|
||||||
### Labels
|
|
||||||
- **scopes**: snake case
|
|
||||||
- **subroutines** and **variables**: snake case (`scope::(_)fname_snake_case` or `scope::(_)varname_2`)
|
|
||||||
- **macros**: camel case (`(_)GoodMacroname` or `scope_GoodMacroname`)
|
|
||||||
- **constants** (eg. in ROM): upper case (`scope::(_)NICE_SYMBOLNAME`)
|
|
@ -2,6 +2,37 @@ import sys
|
|||||||
import re
|
import re
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
|
##
|
||||||
|
# @defgroup documentation Documentation
|
||||||
|
# @brief
|
||||||
|
#
|
||||||
|
|
||||||
|
##
|
||||||
|
# @file
|
||||||
|
# @brief Doxygen filter for ca65 assembler files
|
||||||
|
# @details
|
||||||
|
# This filter converts ca65 to C++ statements that doxygen can parse.
|
||||||
|
#
|
||||||
|
# Doxygen comments are double semicolons `;;`
|
||||||
|
# - turns procedures `.proc` into function statements with `proc` as return type
|
||||||
|
# Parameters documented with the @param command are put into the paranthesis (function arguments) with `Param` as type (@ref handle_procedure)
|
||||||
|
# - turns macros `.macro` into function statements with `macro` as return type with the parameter macros
|
||||||
|
# as function arguments with `Param` type (@ref handle_procedure)
|
||||||
|
# - enums become ... enums, documentation of enum members after their name is also handled (@ref handle_procedure)
|
||||||
|
# - labeled storage allocations with `.byte`, `.res`, `.ascii` etc. are turned into variable declarations with the label as variable name (@ref handle_procedure)
|
||||||
|
# - if allocations are strings, they are concatenated together to `char * LABEL_NAME = "<string(s)>";`
|
||||||
|
# - if there are multiple non-string allocations: `bytes LABEL_NAME[] = {alloc1, alloc2, ...};`
|
||||||
|
# - if there is one non-string allocation: `alloc_type * LABEL_NAME = alloc;`
|
||||||
|
# - if the allocation is not initilized: `alloc_type * LABEL_NAME;`
|
||||||
|
# - if the allocation type is `res SIZE`: `bytes LABEL_NAME[SIZE];`
|
||||||
|
# - the sizes of the arrays may be wrong!
|
||||||
|
# - include statements are kept
|
||||||
|
# - all other preprocessor macros are removed
|
||||||
|
#
|
||||||
|
# @todo Handle structs
|
||||||
|
# @todo for storage allocators, check in which segment they are in and apply `const` where necessary
|
||||||
|
# @ingroup documentation
|
||||||
|
|
||||||
filename = "unknown"
|
filename = "unknown"
|
||||||
|
|
||||||
def pdebug(*args, **k):
|
def pdebug(*args, **k):
|
||||||
@ -16,7 +47,7 @@ def parse_custom_language(file_content: str):
|
|||||||
scope = m.groups()[1]
|
scope = m.groups()[1]
|
||||||
functions = m.groups()[2].replace(" ", "").strip(",")
|
functions = m.groups()[2].replace(" ", "").strip(",")
|
||||||
for f in functions.split(","):
|
for f in functions.split(","):
|
||||||
pdebug(f"Add Exported function: '{f}' in '{scope}'")
|
# pdebug(f"Add Exported function: '{f}' in '{scope}'")
|
||||||
exported_names[f] = scope
|
exported_names[f] = scope
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@ -50,12 +81,11 @@ def parse_custom_language(file_content: str):
|
|||||||
if s[-1] == ",": s = s[:-1]
|
if s[-1] == ",": s = s[:-1]
|
||||||
s += ");\n"
|
s += ");\n"
|
||||||
elif p_type == "macro":
|
elif p_type == "macro":
|
||||||
pdebug(f"Processing macro '{p_name}' with args '{'TXT'.join(p_args.replace(' ', '').split(','))}'")
|
# pdebug(f"Processing macro '{p_name}' with args '{'TXT'.join(p_args.replace(' ', '').split(','))}'")
|
||||||
s += f"macro {p_name}("
|
s += f"macro {p_name}("
|
||||||
p_args = "".join("Param " + param + "," for param in p_args.replace(" ", "").split(',')).strip(",")
|
p_args = "".join("Param " + param + "," for param in p_args.replace(" ", "").split(',')).strip(",")
|
||||||
s += p_args
|
s += p_args
|
||||||
s += ");\n"
|
s += ");\n"
|
||||||
pdebug("Found macro", p_name, s)
|
|
||||||
elif p_type == "enum":
|
elif p_type == "enum":
|
||||||
p_code = re.sub(r"( *(?:;;.*)?\n)", r",\1", p_code)
|
p_code = re.sub(r"( *(?:;;.*)?\n)", r",\1", p_code)
|
||||||
s += f"enum {p_name}" + "{\n" + p_code + "};"
|
s += f"enum {p_name}" + "{\n" + p_code + "};"
|
||||||
@ -69,10 +99,12 @@ def parse_custom_language(file_content: str):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
def handle_storage_label(m):
|
def handle_storage_label(m):
|
||||||
l_docs = m.groups()[0].strip('\n')
|
l_docs = m.groups()[0]
|
||||||
l_name = m.groups()[1]
|
l_name = m.groups()[1]
|
||||||
l_allocs = m.groups()[2]
|
l_allocs = m.groups()[2]
|
||||||
storage_alloc = r"(?:\.(byte|res|dbyte|word|addr|faraddr|dword|ascii|asciiz)([, ]+(?:0x[a-fA-F0-9]+|0b[01]+|\d+|\w+|\"[^\n]*?[^\\\n]\")[ \n]*)*)"
|
l_docs2 = m.groups()[3] # if doc was in the same line as the label
|
||||||
|
|
||||||
|
storage_alloc = r"\.(byte|res|dbyte|word|addr|faraddr|dword|asciiz?)(([, ]+(?:0x[a-fA-F0-9]+|0b[01]+|\d+|\w+|\"[^\n]*?[^\\\n]\")[ \n]*)*)"
|
||||||
storage_alloc_arg = r"(0x[a-fA-F0-9]+|0b[01]+|\d+|\w+|\"[^\n]*[^\\\n]\")"
|
storage_alloc_arg = r"(0x[a-fA-F0-9]+|0b[01]+|\d+|\w+|\"[^\n]*[^\\\n]\")"
|
||||||
|
|
||||||
args = []
|
args = []
|
||||||
@ -83,36 +115,42 @@ def parse_custom_language(file_content: str):
|
|||||||
if alloc_args:
|
if alloc_args:
|
||||||
args += re.findall(storage_alloc_arg, alloc_args)
|
args += re.findall(storage_alloc_arg, alloc_args)
|
||||||
|
|
||||||
|
# pdebug(f"Storage label {l_name} with allocs '{[ma.group() for ma in allocs]}' and args '{args}'\n\t{m.groups()}")
|
||||||
s = ""
|
s = ""
|
||||||
in_namespace = False
|
in_namespace = False
|
||||||
# pdebug("ldocs for", l_name, l_docs)
|
# if the label is exported, put it in a namespace
|
||||||
# pdebug(m.groups())
|
|
||||||
if l_name in exported_names:
|
if l_name in exported_names:
|
||||||
in_namespace = True
|
in_namespace = True
|
||||||
namespace = exported_names[l_name]
|
namespace = exported_names[l_name]
|
||||||
s += f"namespace {namespace}" + " {" + l_docs
|
s += f"namespace {namespace}" + " {"
|
||||||
s += "\n"
|
# docs after the namespace, otherwise they document the namespace
|
||||||
else:
|
if l_docs:
|
||||||
s += l_docs + "\n"
|
s += l_docs
|
||||||
|
# put the single line comment into a /** */ comment in front of the declaration
|
||||||
|
if l_docs2:
|
||||||
|
s += "/** "
|
||||||
|
if not "brief" in l_docs2: s += "@brief "
|
||||||
|
s += f"{l_docs2.strip(';')} */ "
|
||||||
|
# completely ignoring the type of the storage allocation here
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
if all(arg.startswith("\"") for arg in args):
|
if all(arg.startswith("\"") for arg in args):
|
||||||
s += f'char* {l_name} = "' + "".join(map(lambda x: x.strip('"'), args)) + '"'
|
s += f'char* {l_name} = "' + "".join(map(lambda x: x.strip('"'), args)) + '"'
|
||||||
else:
|
else:
|
||||||
s += "bytes[] = {"
|
s += f"bytes {l_name}[{len(args)}] = " + "{"
|
||||||
for arg in args:
|
for arg in args:
|
||||||
s += arg + ","
|
s += arg + ","
|
||||||
s += "}"
|
s = s.strip(",") + "}"
|
||||||
s += s.strip(",") + "}"
|
|
||||||
else:
|
else:
|
||||||
# alloc_type label =
|
|
||||||
l_type = allocs[0].groups()[0]
|
l_type = allocs[0].groups()[0]
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
l_arg = None
|
l_arg = None
|
||||||
else:
|
else:
|
||||||
l_arg = args[0]
|
l_arg = args[0]
|
||||||
|
# if res: use bytes[length] as type
|
||||||
if l_type == "res":
|
if l_type == "res":
|
||||||
l_type = f"bytes[{l_arg}]"
|
l_type = f"bytes[{l_arg}]"
|
||||||
l_arg = None
|
l_arg = None
|
||||||
|
# else use type* as type
|
||||||
else: l_type += "*"
|
else: l_type += "*"
|
||||||
s += f"{l_type} {l_name}"
|
s += f"{l_type} {l_name}"
|
||||||
if l_arg:
|
if l_arg:
|
||||||
@ -134,8 +172,9 @@ def parse_custom_language(file_content: str):
|
|||||||
r"^(Import(?:Zp)?) (\w+)((?: *, *\w+)+)": "",
|
r"^(Import(?:Zp)?) (\w+)((?: *, *\w+)+)": "",
|
||||||
r"(?<!^;)\$([A-Fa-f0-9_]+)": r"0x\1", # $HEX -> 0xHEX except in comments
|
r"(?<!^;)\$([A-Fa-f0-9_]+)": r"0x\1", # $HEX -> 0xHEX except in comments
|
||||||
r"(?<!^;)%([01_]+)": r"0b\1", # %BIN -> 0bBIN except in comments
|
r"(?<!^;)%([01_]+)": r"0b\1", # %BIN -> 0bBIN except in comments
|
||||||
r"^((?:;;.*\n)*)^\.(proc|enum|macro) (\w+)(.*?)\n((?:.|\n)*?)\.end(proc|enum|macro).*": handle_procedure,
|
r"^((?:;;.*\n)*) *\.(proc|enum|macro) (\w+)(.*?)\n((?:.|\n)*?)\.end(proc|enum|macro).*": handle_procedure,
|
||||||
r"^((?:;;.*\n)*) *(\w+):((?:\s*\.(?:byte|res|dbyte|word|addr|faraddr|dword|ascii|asciiz)(?:[, ]+(?:0x[a-fA-F0-9]+|0b[01]+|\d+|\w+|\"[^\n]*[^\\\n]\")[ \n]*)*)+)": handle_storage_label,
|
r"^((?:;;.*\n)*) *(\w+):((?:\s*\.(?:byte|res|dbyte|word|addr|faraddr|dword|asciiz?)(?:[, ]+(?:0x[a-fA-F0-9]+|0b[01]+|\d+|\w+|\"[^\n]*[^\\\n]\")[ \n]*)*)+)(;;.*)?": handle_storage_label,
|
||||||
|
r"^INCLUDE_[A-Z0-9_]+ *= *1$": r"", # Include guard variables
|
||||||
r";;": "//!", # C++ comments
|
r";;": "//!", # C++ comments
|
||||||
# TODO this is currently case sensitive
|
# TODO this is currently case sensitive
|
||||||
r"(?<!^;)( *\w+ *= *[^;,\n]+?) *(//.*)?$": r"\1;\2", # semicolons after assignments, except in comments and when they already end with a comma or semicolon. Also preserve comments after the assignment
|
r"(?<!^;)( *\w+ *= *[^;,\n]+?) *(//.*)?$": r"\1;\2", # semicolons after assignments, except in comments and when they already end with a comma or semicolon. Also preserve comments after the assignment
|
||||||
@ -157,7 +196,6 @@ def parse_custom_language(file_content: str):
|
|||||||
for pat, subst in resub_patterns.items():
|
for pat, subst in resub_patterns.items():
|
||||||
file_content = re.sub(pat, subst, file_content, 0, re.MULTILINE)
|
file_content = re.sub(pat, subst, file_content, 0, re.MULTILINE)
|
||||||
for pat,subst in patterns.items():
|
for pat,subst in patterns.items():
|
||||||
pdebug(f"Now doing pattern: {pat}")
|
|
||||||
(file_content, n_subst) = re.subn(pat, subst, file_content, 0, re.MULTILINE)
|
(file_content, n_subst) = re.subn(pat, subst, file_content, 0, re.MULTILINE)
|
||||||
return file_content
|
return file_content
|
||||||
|
|
||||||
|
32
main.s65
32
main.s65
@ -3,6 +3,8 @@
|
|||||||
.export home,homeloop
|
.export home,homeloop
|
||||||
.import keypad_printer:absolute
|
.import keypad_printer:absolute
|
||||||
.import spi_menu:absolute
|
.import spi_menu:absolute
|
||||||
|
.import ps2_keyboard_printer:absolute
|
||||||
|
.import ps2_keyboard_util:absolute
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
@ -143,9 +145,11 @@ reset:
|
|||||||
cmp #'D'
|
cmp #'D'
|
||||||
jeq print_2
|
jeq print_2
|
||||||
cmp #'1'
|
cmp #'1'
|
||||||
beq @debug0_on
|
; beq @debug0_on
|
||||||
|
beq @ps2_util
|
||||||
cmp #'2'
|
cmp #'2'
|
||||||
beq @debug0_off
|
beq @ps2_printer
|
||||||
|
; beq @debug0_off
|
||||||
cmp #'4'
|
cmp #'4'
|
||||||
beq @debug1_on
|
beq @debug1_on
|
||||||
cmp #'5'
|
cmp #'5'
|
||||||
@ -161,6 +165,10 @@ reset:
|
|||||||
wai
|
wai
|
||||||
jmp @loop
|
jmp @loop
|
||||||
|
|
||||||
|
@ps2_util:
|
||||||
|
jmp ps2_keyboard_util
|
||||||
|
@ps2_printer:
|
||||||
|
jmp ps2_keyboard_printer
|
||||||
@debug0_off:
|
@debug0_off:
|
||||||
DEBUG_LED_OFF 0
|
DEBUG_LED_OFF 0
|
||||||
jmp @loop
|
jmp @loop
|
||||||
@ -209,18 +217,18 @@ message_1:
|
|||||||
message_2:
|
message_2:
|
||||||
.byte "0123456789=!?#+*"
|
.byte "0123456789=!?#+*"
|
||||||
.byte "ABCDEFGHIJKLMNOP"
|
.byte "ABCDEFGHIJKLMNOP"
|
||||||
.byte "QRSTUVWXYZÖÄÜß-_"
|
.byte "QRSTUVWXYZöäüß-_"
|
||||||
.asciiz "{[(<>)]}$%&/,;.:"
|
.asciiz "{[(<>)]}$%&/,;.:"
|
||||||
message_menu:
|
message_menu:
|
||||||
.byte "<A> Printer "
|
.byte "A/2: KP/KB Print"
|
||||||
; .byte "<B> Temperatur "
|
; .byte "<B> Temperatur"
|
||||||
.byte "<B> SPI-Menu "
|
.byte "1: KB Util "
|
||||||
.byte "<C> Text 1 "
|
.byte "B: SPI-Menu "
|
||||||
.asciiz "<D> Text 2 "
|
.asciiz "C/D: Text 1/2 "
|
||||||
str_spi_begin:
|
; str_spi_begin:
|
||||||
.asciiz "---BEGIN SPI---"
|
; .asciiz "---BEGIN SPI---"
|
||||||
str_spi_start:
|
; str_spi_start:
|
||||||
.asciiz "---START SPI---"
|
; .asciiz "---START SPI---"
|
||||||
str_io2:
|
str_io2:
|
||||||
.asciiz "IO2::RB='"
|
.asciiz "IO2::RB='"
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
.include "keypad.h65"
|
.include "keypad.h65"
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Print characters to the display when a button was pressed
|
||||||
|
;; @ingroup applications
|
||||||
|
;;********************************************************************************
|
||||||
.proc keypad_printer
|
.proc keypad_printer
|
||||||
jsr lcd::clear
|
jsr lcd::clear
|
||||||
@printer_loop:
|
@printer_loop:
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
.export print_slow
|
.export print_slow
|
||||||
|
|
||||||
.code
|
.code
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @function Print a null-terminated string
|
;; @function Print a null-terminated string with a delay between each character
|
||||||
; @param ARG0-1: Address of the string to print
|
;; @param ARG0-1: Address of the string to print
|
||||||
; @param x: time to sleep in centiseconds
|
;; @param x: time to sleep in centiseconds
|
||||||
;********************************************************************************
|
;; @ingroup applications
|
||||||
|
;; @clock_dependant
|
||||||
|
;;********************************************************************************
|
||||||
.proc print_slow
|
.proc print_slow
|
||||||
ldy #$00
|
ldy #$00
|
||||||
@print_loop:
|
@print_loop:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
.include "lcd.h65"
|
.include "lcd.h65"
|
||||||
|
.include "string.h65"
|
||||||
.include "ps2_keyboard_text_handler.h65"
|
.include "ps2_keyboard_text_handler.h65"
|
||||||
|
|
||||||
.export ps2_keyboard_printer
|
.export ps2_keyboard_printer
|
||||||
@ -6,10 +7,36 @@
|
|||||||
.import home:absolute
|
.import home:absolute
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Print characters to the display when a key was pressed
|
||||||
|
;; @details
|
||||||
|
;; Print the character that corresponds to a key.
|
||||||
|
;; This uses the @ref kb "text keyboard handler" to correctly handle modifier keys
|
||||||
|
;;
|
||||||
|
;; Controls:
|
||||||
|
;; - `ESC`: Jump home
|
||||||
|
;; - `Print`: Clear the display
|
||||||
|
;; - `F12`: Restart the program
|
||||||
|
;; @ingroup applications keyboard
|
||||||
|
;;********************************************************************************
|
||||||
.proc ps2_keyboard_printer
|
.proc ps2_keyboard_printer
|
||||||
jsr lcd::clear
|
jsr lcd::clear
|
||||||
jsr kb::init
|
jsr kb::init
|
||||||
|
jeq loop
|
||||||
|
ps2kb_PrintCmdFailed
|
||||||
|
; jmp homeloop
|
||||||
|
ps2kb_CmdEnable
|
||||||
|
jsr ps2kb::begin_receive
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
|
wai
|
||||||
|
; ; put shift, ralt and lalt in debug leds
|
||||||
|
; lda kb::modifier
|
||||||
|
; Reverse A
|
||||||
|
; and #%00000111
|
||||||
|
; ora IO1 + IO::RANH
|
||||||
|
; sta IO1 + IO::RANH
|
||||||
lda kb::char
|
lda kb::char
|
||||||
beq @no_char
|
beq @no_char
|
||||||
stz kb::char
|
stz kb::char
|
||||||
@ -18,11 +45,13 @@ loop:
|
|||||||
@no_char:
|
@no_char:
|
||||||
lda kb::keycode
|
lda kb::keycode
|
||||||
beq loop
|
beq loop
|
||||||
|
stz kb::keycode
|
||||||
cmp #kb::K::ESCAPE
|
cmp #kb::K::ESCAPE
|
||||||
beq @esacpe
|
beq @esacpe
|
||||||
cmp #kb::K::PRINT
|
cmp #kb::K::PRINT
|
||||||
beq @clear_display
|
beq @clear_display
|
||||||
|
cmp #kb::K::F12
|
||||||
|
jeq ps2_keyboard_printer
|
||||||
bra loop
|
bra loop
|
||||||
@esacpe:
|
@esacpe:
|
||||||
jmp home
|
jmp home
|
||||||
@ -30,4 +59,3 @@ loop:
|
|||||||
jsr lcd::clear
|
jsr lcd::clear
|
||||||
bra loop
|
bra loop
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
@ -5,15 +5,15 @@ ExportZp kb, modifier
|
|||||||
|
|
||||||
.zeropage
|
.zeropage
|
||||||
;; @ref kb::MOD "status of the modifier keys"
|
;; @ref kb::MOD "status of the modifier keys"
|
||||||
modifier: .byte
|
modifier: .res 1
|
||||||
.bss
|
.bss
|
||||||
;; previous scancode is used to determine if a key was released (BREAK sent previously)
|
;; previous scancode is used to determine if a key was released (BREAK sent previously)
|
||||||
;; will be $ff if the previous scancode was K_BREAK
|
;; will be $ff if the previous scancode was K_BREAK
|
||||||
previous_scancode: .byte
|
previous_scancode: .res 1
|
||||||
;; 0 when no key or non-character key was pressed, otherwise character of the key (with modifiers applied)
|
;; 0 when no key or non-character key was pressed, otherwise character of the key (with modifiers applied)
|
||||||
char: .byte
|
char: .res 1
|
||||||
;; @ref kb::K "keycode" of the last key that was pressed or 0 if none was pressed
|
;; @ref kb::K "keycode" of the last key that was pressed or 0 if none was pressed
|
||||||
keycode: .byte
|
keycode: .res 1
|
||||||
|
|
||||||
.code
|
.code
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
|
@ -10,6 +10,29 @@
|
|||||||
.import home:absolute
|
.import home:absolute
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Send various commands to the keyboard and print the response bytes
|
||||||
|
;; @details
|
||||||
|
;; - `0`: `0xf0` query scancode set
|
||||||
|
;; - `1`: `0xee` echo
|
||||||
|
;; - `2`: `0xf2` identify
|
||||||
|
;; - `3`: `0xf3` set typematic min speed and delay (`0b0111111`)
|
||||||
|
;; - `4`: `0xf4` enable
|
||||||
|
;; - `5`: `0xf5` disable
|
||||||
|
;; - `6`: `0xf3` set typematic max speed and min delay (`0b00000000`)
|
||||||
|
;; - `7`: `0xf7` set typematic all
|
||||||
|
;; - `8`: `0xf8` set make/release all
|
||||||
|
;; - `9`: `0xed` set CAPSLOCK led
|
||||||
|
;; - `#`: `0xed` set SCROLLLOCK led
|
||||||
|
;; - `C`: `0xed` set NUMLOCK led
|
||||||
|
;; - `D`: `0xed` turn all leds off
|
||||||
|
;; - `A`: reprint menu
|
||||||
|
;; - `B`: reprint menu
|
||||||
|
;; - `*`: jump home
|
||||||
|
;; For more details, see https://wiki.osdev.org/PS/2_Keyboard
|
||||||
|
;; @ingroup applications keyboard
|
||||||
|
;;********************************************************************************
|
||||||
.proc ps2_keyboard_util
|
.proc ps2_keyboard_util
|
||||||
stz kp::_DEBUG_VAL
|
stz kp::_DEBUG_VAL
|
||||||
jsr skb::init
|
jsr skb::init
|
||||||
@ -67,6 +90,7 @@ loop:
|
|||||||
beq @lD
|
beq @lD
|
||||||
jsr lcd::print_char
|
jsr lcd::print_char
|
||||||
jmp loop
|
jmp loop
|
||||||
|
|
||||||
@l0: ; get scancode set
|
@l0: ; get scancode set
|
||||||
lda #$f0
|
lda #$f0
|
||||||
ldx #0
|
ldx #0
|
||||||
@ -99,7 +123,7 @@ loop:
|
|||||||
@l8: ; set make/release all
|
@l8: ; set make/release all
|
||||||
lda #$f8
|
lda #$f8
|
||||||
bra @send_cmd
|
bra @send_cmd
|
||||||
@l9: ; set CAPSLOCK
|
@l9: ; set CAPSLOCK led
|
||||||
lda #$ed
|
lda #$ed
|
||||||
ldx #kb::MOD::CAPSLOCK
|
ldx #kb::MOD::CAPSLOCK
|
||||||
bra @send_cmd
|
bra @send_cmd
|
||||||
|
@ -3,14 +3,16 @@
|
|||||||
.export sleep
|
.export sleep
|
||||||
|
|
||||||
.code
|
.code
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @function sleep
|
;; @function sleep
|
||||||
; @param x: Time to sleep in centiseconds (10^-2s = 10ms)
|
;; @param x: Time to sleep in centiseconds (10^-2s = 10ms) @ 1MHz
|
||||||
; @details
|
;; @details
|
||||||
; Interrupts might change the actual time to finish
|
;; Interrupts might change the actual time to finish
|
||||||
; To be exact, time_cs is in units of 0.010244s
|
;; To be exact, time_cs is in units of 0.010244s
|
||||||
; @modifies: ARG15
|
;; @modifies: ARG15
|
||||||
;********************************************************************************
|
;; @ingroup applications
|
||||||
|
;; @clock_dependant
|
||||||
|
;;********************************************************************************
|
||||||
.proc sleep
|
.proc sleep
|
||||||
_VAR_1 = ARG15
|
_VAR_1 = ARG15
|
||||||
stz _VAR_1
|
stz _VAR_1
|
||||||
|
@ -9,11 +9,15 @@
|
|||||||
|
|
||||||
.export spi_menu
|
.export spi_menu
|
||||||
.bss
|
.bss
|
||||||
trans_bytes: .res 2 ; used to check if screen needs to be updated
|
trans_bytes: .res 2 ;; used to check if screen needs to be updated
|
||||||
status_char: .res 1
|
status_char: .res 1
|
||||||
status_str: .res 17 ; 16 + null
|
status_str: .res 17 ;; space for 16 + null
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Receive code via SPI and execute it
|
||||||
|
;; @ingroup applications
|
||||||
|
;;********************************************************************************
|
||||||
.proc spi_menu
|
.proc spi_menu
|
||||||
stz trans_bytes
|
stz trans_bytes
|
||||||
stz trans_bytes+1
|
stz trans_bytes+1
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
;;********************************************************************************
|
||||||
|
;; @module VIU - VI Unimproved
|
||||||
|
;;********************************************************************************
|
||||||
.include "lcd.h65"
|
.include "lcd.h65"
|
||||||
.include "ps2_keyboard_text_handler.h65"
|
.include "ps2_keyboard_text_handler.h65"
|
||||||
|
|
||||||
@ -13,7 +16,6 @@ buffer: .res 256
|
|||||||
stz ptr
|
stz ptr
|
||||||
stz ptr+1
|
stz ptr+1
|
||||||
stz buffer
|
stz buffer
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
.proc insert_mode
|
.proc insert_mode
|
||||||
|
20
readme.md
20
readme.md
@ -5,12 +5,18 @@ The assembler used for this project is the excellent [ca65](https://github.com/c
|
|||||||
After assembling it, the binary is loaded onto the EEPROM using [my *eeprom.py* script](https://git.quintern.xyz/MatthiasQuintern/AT28C256-rpi-util) on a Raspberry Pi 4B.
|
After assembling it, the binary is loaded onto the EEPROM using [my *eeprom.py* script](https://git.quintern.xyz/MatthiasQuintern/AT28C256-rpi-util) on a Raspberry Pi 4B.
|
||||||
|
|
||||||
## Operating System
|
## Operating System
|
||||||
... is probably a far stretch, since it is just the programs I wrote pieced together. My "os" consists of these functionalities:
|
... is probably a far stretch, since it is just the programs I wrote pieced together. My "OS" consists of these functionalities:
|
||||||
- Main Menu:
|
- Supported Hardware:
|
||||||
- Printer: Prints the characters you press on the keypad to the lcd.
|
- 4x4 Matrix Keypad
|
||||||
- Temperature: Shows the temperature using a dht sensor. *Work in progress, this does not work yet*
|
- 4x16 Characters LCD Display
|
||||||
- Text 1: Show a 4x16 character text (defined at compile time)
|
- PS/2 Keyboard
|
||||||
- Text 2: Show a 4x16 character text (defined at compile time)
|
- SPI Connection to an Arduino
|
||||||
- Ringbuffer for pressed keys.
|
- Software
|
||||||
|
- Keyboard and keypad printer: Prints the characters you press on to the lcd
|
||||||
|
<!-- - Temperature: Shows the temperature using a dht sensor. *Work in progress, this does not work yet* -->
|
||||||
|
- (Stylishly) print formated strings to the LCD
|
||||||
|
- Sleep
|
||||||
|
- Send various commands to the keyboard
|
||||||
|
- Ringbuffer
|
||||||
|
|
||||||
> It's not much, but it's honest work.
|
> It's not much, but it's honest work.
|
||||||
|
42
spicode.s65
42
spicode.s65
@ -79,7 +79,7 @@ CODE_START:
|
|||||||
@l0:
|
@l0:
|
||||||
jmp ps2_keyboard_util
|
jmp ps2_keyboard_util
|
||||||
@l1:
|
@l1:
|
||||||
jmp _ps2_keyboard_printer
|
jmp ps2_keyboard_printer
|
||||||
@l2:
|
@l2:
|
||||||
lcd_SetCursorPos $26
|
lcd_SetCursorPos $26
|
||||||
lda #'6'
|
lda #'6'
|
||||||
@ -101,46 +101,6 @@ CODE_START:
|
|||||||
@lD:
|
@lD:
|
||||||
jmp @loop
|
jmp @loop
|
||||||
|
|
||||||
.proc _ps2_keyboard_printer
|
|
||||||
jsr lcd::clear
|
|
||||||
jsr kb::init
|
|
||||||
jeq loop
|
|
||||||
ps2kb_PrintCmdFailed
|
|
||||||
; jmp homeloop
|
|
||||||
ps2kb_CmdEnable
|
|
||||||
jsr ps2kb::begin_receive
|
|
||||||
|
|
||||||
|
|
||||||
loop:
|
|
||||||
wai
|
|
||||||
; put shift, ralt and lalt in debug leds
|
|
||||||
lda kb::modifier
|
|
||||||
Reverse A
|
|
||||||
and #%00000111
|
|
||||||
ora IO1 + IO::RANH
|
|
||||||
sta IO1 + IO::RANH
|
|
||||||
lda kb::char
|
|
||||||
beq @no_char
|
|
||||||
stz kb::char
|
|
||||||
jsr lcd::print_char
|
|
||||||
bra loop
|
|
||||||
@no_char:
|
|
||||||
lda kb::keycode
|
|
||||||
beq loop
|
|
||||||
stz kb::keycode
|
|
||||||
cmp #kb::K::ESCAPE
|
|
||||||
beq @esacpe
|
|
||||||
cmp #kb::K::PRINT
|
|
||||||
beq @clear_display
|
|
||||||
cmp #kb::K::F12
|
|
||||||
jeq _ps2_keyboard_printer
|
|
||||||
bra loop
|
|
||||||
@esacpe:
|
|
||||||
jmp home
|
|
||||||
@clear_display:
|
|
||||||
jsr lcd::clear
|
|
||||||
bra loop
|
|
||||||
.endproc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,28 +8,43 @@
|
|||||||
.ifndef INCLUDE_IOW65C22
|
.ifndef INCLUDE_IOW65C22
|
||||||
INCLUDE_IOW65C22 = 1
|
INCLUDE_IOW65C22 = 1
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Versatile Interface Adapter (VIA) W65C22
|
||||||
|
;; @ingroup utility
|
||||||
|
;; @device Western Design - W65C22N Versatile Interface Adapter
|
||||||
|
;; @todo rename to VIA
|
||||||
|
;; @warning @anchor via_hardware_bug
|
||||||
|
;; The 6522 and 65C22 have a hardware bug, where a bit is not read in when the
|
||||||
|
;; external shift register clock transitions close to @f$ \phi_2 @f$.
|
||||||
|
;; To resolve this, you should use a @f$ \phi_2 @f$ controlled flip flop to ensure
|
||||||
|
;; the external clock transitions after the system clock.
|
||||||
|
;;********************************************************************************
|
||||||
.scope IO
|
.scope IO
|
||||||
|
|
||||||
; not using a struct for this since the syntax for access would be the same,
|
; not using a struct for this since the syntax for access would be the same,
|
||||||
; ie label+IO::RA
|
; ie label+IO::RA
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief VIA register offsets from the base address
|
||||||
|
;; @details
|
||||||
|
;; Use like this: `VIA_ADDRESS + IO::RB`
|
||||||
|
;;********************************************************************************
|
||||||
.enum
|
.enum
|
||||||
; IO-CHIPS OFFSETS FOR PINS FROM BASE ADDRESS
|
RB = $0 ;; Register B (ORB/IRB)
|
||||||
RB = $0 ; Register B (ORB/IRB)
|
RA = $1 ;; Register A (ORA/IRA)
|
||||||
RA = $1 ; Register A (ORA/IRA)
|
DDRB = $2 ;; Data Direction Register B
|
||||||
DDRB = $2 ; Data Direction Register B
|
DDRA = $3 ;; Data Direction Register A
|
||||||
DDRA = $3 ; Data Direction Register A
|
T1CL = $4 ;; Timer 1 Counter Low/High
|
||||||
T1CL = $4 ; Timer 1 Counter Low/High
|
|
||||||
T1CH = $5
|
T1CH = $5
|
||||||
T1LL = $6 ; Timer 1 Latch Low/High
|
T1LL = $6 ;; Timer 1 Latch Low/High
|
||||||
T1LH = $7
|
T1LH = $7
|
||||||
T2CL = $8 ; Timer 2 Counter Low/High
|
T2CL = $8 ;; Timer 2 Counter Low/High
|
||||||
T2CH = $9
|
T2CH = $9
|
||||||
SR = $a ; Shift Register
|
SR = $a ;; Shift Register
|
||||||
ACR = $b ; Auxiliary Control Register
|
ACR = $b ;; Auxiliary Control Register
|
||||||
PCR = $c ; Peripheral Control Register
|
PCR = $c ;; Peripheral Control Register
|
||||||
IFR = $d ; Interrupt Flag Register
|
IFR = $d ;; Interrupt Flag Register
|
||||||
IER = $e ; Interrupt Enable Register
|
IER = $e ;; Interrupt Enable Register
|
||||||
RANH = $f ; RA without handshake
|
RANH = $f ;; RA without handshake
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
.enum ACR_MASK ; ACR Masks
|
.enum ACR_MASK ; ACR Masks
|
||||||
@ -40,27 +55,32 @@ INCLUDE_IOW65C22 = 1
|
|||||||
T1 = %11000000
|
T1 = %11000000
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
.enum ACR ; ACR Settings
|
;;********************************************************************************
|
||||||
|
;; @brief Settings for Auxiliary Control Register
|
||||||
|
;; @details
|
||||||
|
;; `OR` the values with the appropriate IO::ACR_MASK to not target only specific settings
|
||||||
|
;;********************************************************************************
|
||||||
|
.enum ACR
|
||||||
; SR Modes
|
; SR Modes
|
||||||
SR_DISABLE = %00000000 ; Disabled
|
SR_DISABLE = %00000000 ;; Disabled
|
||||||
SR_SIN_T2 = %00000100 ; Shift in under control of T2
|
SR_SIN_T2 = %00000100 ;; Shift in under control of T2
|
||||||
SR_SIN_PHI2 = %00001000 ; Shift in under control of PHI2
|
SR_SIN_PHI2 = %00001000 ;; Shift in under control of PHI2
|
||||||
SR_SIN_PHIE = %00001100 ; Shift in under control of external clock
|
SR_SIN_PHIE = %00001100 ;; Shift in under control of external clock
|
||||||
SR_SOUT_FREE_T2 = %00010000 ; Shift out free running at T2 rate
|
SR_SOUT_FREE_T2 = %00010000 ;; Shift out free running at T2 rate
|
||||||
SR_SOUT_T2 = %00010100 ; Shift out under control of T2
|
SR_SOUT_T2 = %00010100 ;; Shift out under control of T2
|
||||||
SR_SOUT_PHI2 = %00011000 ; Shift out under control of PHI2
|
SR_SOUT_PHI2 = %00011000 ;; Shift out under control of PHI2
|
||||||
SR_SOUT_PHIE = %00011100 ; Shift out under control of external clock
|
SR_SOUT_PHIE = %00011100 ;; Shift out under control of external clock
|
||||||
; T1 Modes
|
; T1 Modes
|
||||||
T1_IRQ_LOAD = %00000000 ; Timed interrupt each time T1 is loaded
|
T1_IRQ_LOAD = %00000000 ;; Timed interrupt each time T1 is loaded
|
||||||
T1_IRQ_CONT = %01000000 ; Continuous interrupts
|
T1_IRQ_CONT = %01000000 ;; Continuous interrupts
|
||||||
T1_IRQ_LOAD_PB7 = %10000000 ; Timed interrupt each time T1 is loaded - PB7 One Shot output
|
T1_IRQ_LOAD_PB7 = %10000000 ;; Timed interrupt each time T1 is loaded - PB7 One Shot output
|
||||||
T1_IRQ_CONT_PB7 = %11000000 ; Continuous interrupts - PB7 Square wave output
|
T1_IRQ_CONT_PB7 = %11000000 ;; Continuous interrupts - PB7 Square wave output
|
||||||
; T2 Modes
|
; T2 Modes
|
||||||
T2_IRQ_LOAD = %00000000 ; Timed interrupt each time T2 is loaded
|
T2_IRQ_LOAD = %00000000 ;; Timed interrupt each time T2 is loaded
|
||||||
T2_COUNT_PB6 = %00100000 ; Count down with pulsen on PB6
|
T2_COUNT_PB6 = %00100000 ;; Count down with pulsen on PB6
|
||||||
; Latch
|
; Latch
|
||||||
LATCH_DISABLE = %00000000
|
LATCH_DISABLE = %00000000 ;; `OR` this with IO::ACR_MASK::PA or IO::ACR_MASK::PB
|
||||||
LATCH_ENBLE = %00000000
|
LATCH_ENBLE = %00000011 ;; `OR` this with IO::ACR_MASK::PA or IO::ACR_MASK::PB
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
.enum PCR_MASK ; PCR Masks
|
.enum PCR_MASK ; PCR Masks
|
||||||
@ -70,6 +90,11 @@ INCLUDE_IOW65C22 = 1
|
|||||||
CB2 = %11100000 ;
|
CB2 = %11100000 ;
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Settings for Peripheral Control Register
|
||||||
|
;; @details
|
||||||
|
;; `OR` the values with the appropriate IO::PCR_MASK to not target only specific settings
|
||||||
|
;;********************************************************************************
|
||||||
.enum PCR
|
.enum PCR
|
||||||
; CA1 Modes
|
; CA1 Modes
|
||||||
CA1_IN_AE = %00000000 ; Input-negative active edge
|
CA1_IN_AE = %00000000 ; Input-negative active edge
|
||||||
@ -97,7 +122,10 @@ INCLUDE_IOW65C22 = 1
|
|||||||
CB2_OUT_HIGH = %11100000 ; High output
|
CB2_OUT_HIGH = %11100000 ; High output
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
; IFR/IER bits
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Interrupt Flag/Enable Register bits
|
||||||
|
;;********************************************************************************
|
||||||
.enum IRQ
|
.enum IRQ
|
||||||
CA2 = %00000001
|
CA2 = %00000001
|
||||||
CA1 = %00000010
|
CA1 = %00000010
|
||||||
@ -112,7 +140,7 @@ INCLUDE_IOW65C22 = 1
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @macro Enable an interrupt source
|
;; @macro Enable an interrupt source
|
||||||
;; @modifies: A
|
;; @modifies: A
|
||||||
;; @param flag: A flag of the interrupt flag register (IO:IRQ)
|
;; @param flag: A flag of the interrupt flag register (IO::IRQ)
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.macro IO_EnableIRQ ioaddr, flag
|
.macro IO_EnableIRQ ioaddr, flag
|
||||||
lda #(IO::IRQ::IRQ | flag)
|
lda #(IO::IRQ::IRQ | flag)
|
||||||
@ -121,7 +149,7 @@ INCLUDE_IOW65C22 = 1
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @macro Disable an interrupt source
|
;; @macro Disable an interrupt source
|
||||||
;; @modifies: A
|
;; @modifies: A
|
||||||
;; @param flag: A flag of the interrupt flag register (IO:IRQ)
|
;; @param flag: A flag of the interrupt flag register (IO::IRQ)
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.macro IO_DisableIRQ ioaddr, flag
|
.macro IO_DisableIRQ ioaddr, flag
|
||||||
lda #flag
|
lda #flag
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @module keypad4x4
|
;; @module keypad4x4
|
||||||
; @type driver
|
;; @type driver
|
||||||
; @device 4x4 Matrix Keypad
|
;; @device 4x4 Matrix Keypad
|
||||||
; @details
|
;; @details
|
||||||
; The LCD must be connected to a W65C22N Interface Chip:
|
;; The LCD must be connected to a W65C22N Interface Chip:
|
||||||
; - IO.RA0-7 ->
|
;; - IO.RA0-7 ->
|
||||||
; @requires KP_IO: Base Address of IO Chip
|
;; @requires KP_IO: Base Address of IO Chip
|
||||||
; @depends IO-W65C22N
|
;; @depends IO-W65C22N
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
.ifndef INCLUDE_KEYPAD
|
.ifndef INCLUDE_KEYPAD
|
||||||
INCLUDE_KEYPAD = 1
|
INCLUDE_KEYPAD = 1
|
||||||
.include "system.h65"
|
.include "system.h65"
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief 4x4 Matrix Keypad
|
||||||
|
;;********************************************************************************
|
||||||
.scope kp
|
.scope kp
|
||||||
KP_IO = IO2
|
KP_IO = IO2
|
||||||
; .import KP_IO
|
; .import KP_IO
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @module LCD-W164B
|
;; @module LCD-W164B
|
||||||
;; @type driver
|
;; @ingroup driver
|
||||||
;; @device ELECTRONIC ASSEMBLY - W164B-NLW
|
;; @device ELECTRONIC ASSEMBLY - W164B-NLW
|
||||||
;; @details
|
;; @details
|
||||||
;; The LCD must be connected to a W65C22N Interface Chip:
|
;; The LCD must be connected to a W65C22N Interface Chip:
|
||||||
@ -8,7 +8,6 @@
|
|||||||
;; - IO.RA5 -> LCD.RS register select
|
;; - IO.RA5 -> LCD.RS register select
|
||||||
;; - IO.RA6 -> LCD.R/W read/write
|
;; - IO.RA6 -> LCD.R/W read/write
|
||||||
;; - IO.RA7 -> LCD.E enable
|
;; - IO.RA7 -> LCD.E enable
|
||||||
;;
|
|
||||||
;; @requires IO: Base Address of IO Chip
|
;; @requires IO: Base Address of IO Chip
|
||||||
;; @depends IO-W65C22N
|
;; @depends IO-W65C22N
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
@ -19,6 +18,7 @@ INCLUDE_LCD = 1
|
|||||||
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @brief LCD character display
|
;; @brief LCD character display
|
||||||
|
;; @ingroup driver
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.scope lcd
|
.scope lcd
|
||||||
LCD_IO = IO1
|
LCD_IO = IO1
|
||||||
|
@ -11,7 +11,7 @@ Export lcd,_charcount
|
|||||||
.bss
|
.bss
|
||||||
_charcount: .res 1
|
_charcount: .res 1
|
||||||
|
|
||||||
; TODO when clockspeeds are more than 1MHz, _cmd, _write_ram and _read_ram might need to be adjusted
|
; @TODO when clockspeeds are more than 1MHz, _cmd, _write_ram and _read_ram might need to be adjusted
|
||||||
.code
|
.code
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @function Initialize the lcd module
|
;; @function Initialize the lcd module
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @module ps2_keyboard
|
;; @module ps2_keyboard
|
||||||
;; @type driver
|
;; @ingroup drivers
|
||||||
;; @details:
|
;; @details:
|
||||||
;; Support for a PS2 Keyboard using the shift register of a 6522 VIA
|
;; Support for a PS2 Keyboard using the shift register of a 6522 VIA
|
||||||
;; @section reading Reading a scancode/command answer
|
;; @section reading Reading a scancode/command answer
|
||||||
@ -17,32 +17,52 @@
|
|||||||
;; The scancode may be processed by storing the address of a handler subroutine in
|
;; The scancode may be processed by storing the address of a handler subroutine in
|
||||||
;; `ps2kb::scancode_handler`. This handler can load the scancode byte from `ps2kb::scancode`.
|
;; `ps2kb::scancode_handler`. This handler can load the scancode byte from `ps2kb::scancode`.
|
||||||
;;
|
;;
|
||||||
;;
|
|
||||||
;; To use a different layout, change the enum K and the CHARS_NOMOD and CHARS_MODSHIFT
|
;; To use a different layout, change the enum K and the CHARS_NOMOD and CHARS_MODSHIFT
|
||||||
;; @warning
|
;; @warning
|
||||||
;; The value with which the timer is loaded must depends on the clock frequency
|
;; The value with which the timer is loaded must depends on the clock frequency
|
||||||
;; of the keyboard and the computer
|
;; of the keyboard and the computer
|
||||||
;;
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.ifndef INCLUDE_PS2_KEYBOARD
|
.ifndef INCLUDE_PS2_KEYBOARD
|
||||||
INCLUDE_PS2_KEYBOARD = 1
|
INCLUDE_PS2_KEYBOARD = 1
|
||||||
.include "system.h65"
|
.include "system.h65"
|
||||||
|
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief PS/2 Keyboard
|
||||||
|
;; This requires the data line to be hooked up to `CB2` and the clock to `CB1`.
|
||||||
|
;; The VIA will be set to shift in the data into the shift register under the external clock.
|
||||||
|
;; @see @ref via_hardware_bug "VIA external clock bug"
|
||||||
|
;; @include keyboard
|
||||||
|
;; @ingroup drivers
|
||||||
|
;;********************************************************************************
|
||||||
.scope ps2kb
|
.scope ps2kb
|
||||||
Import ps2kb, init, begin_receive, scancode, status, scancode_handler
|
Import ps2kb, init, begin_receive, scancode, status, scancode_handler
|
||||||
Import ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_byte, _send_irq_shift_reg_handler, _send_irq_timer_handler,
|
Import ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_byte, _send_irq_shift_reg_handler, _send_irq_timer_handler,
|
||||||
Import ps2kb, send_command, send_cmd, send_data, cmd_response, response_length, FMT_CMD_FAIL
|
Import ps2kb, send_command, send_cmd, send_data, cmd_response, response_length, FMT_CMD_FAIL
|
||||||
|
|
||||||
|
;; Base address of the VIA the keyboard is conencted to
|
||||||
VIA = IO1
|
VIA = IO1
|
||||||
; Enough time must pass for 3 bits to be shifted in.
|
|
||||||
; TIMER_RECV = 230 ; 230 ms (@1MHz)
|
;; @brief #clock cycles to to wait for the last 3 bits after the first 8 have been shifted in
|
||||||
TIMER_RECV = 400 ; 230 ms (@1MHz)
|
;; @details
|
||||||
; Enough time must pass for one bit must be shifted out (parity),
|
;; The last 3 bits take about 230 ms.
|
||||||
; but at most two (parity+stop).
|
;; Calculate the appropriate value using: @f$ N_\text{cycles} = 230 \times f_\text{in MHZ} @f$
|
||||||
; After that, the interrupt must have happened because the keyboard will pull data low.
|
;; - 230 \@ 1MHz
|
||||||
; At that point, the SR needs to be set to input again
|
;; - 400 \@ 1.84 MHz
|
||||||
; TIMER_SEND = 230 ; 180 ms (@1MHz)
|
;; @clock_dependant
|
||||||
TIMER_SEND = 400 ; 180 ms (@1MHz)
|
TIMER_RECV = 400
|
||||||
|
;; @brief #clock cycles to wait after loading the SR a second time while sending a command to the keyboard
|
||||||
|
;; @details
|
||||||
|
;; Enough time must pass for one bit must be shifted out (parity),
|
||||||
|
;; but at most two (parity+stop).
|
||||||
|
;; After that, the interrupt must have happened because the keyboard will pull data low.
|
||||||
|
;; At that point, the shift register needs to be set to input again
|
||||||
|
;;
|
||||||
|
;; Values that seem to work:
|
||||||
|
;; - 230 \@ 1MHz
|
||||||
|
;; - 400 \@ 1.84 MHz
|
||||||
|
;; @clock_dependant
|
||||||
|
TIMER_SEND = 400
|
||||||
|
|
||||||
PULL_REG = IO::RANH
|
PULL_REG = IO::RANH
|
||||||
PULL_DDR = IO::DDRA
|
PULL_DDR = IO::DDRA
|
||||||
@ -50,24 +70,24 @@ PULL_DDR = IO::DDRA
|
|||||||
PULL_MASK_CLK = %00010000
|
PULL_MASK_CLK = %00010000
|
||||||
|
|
||||||
; using ff because 0 is a possible data byte (set led)
|
; using ff because 0 is a possible data byte (set led)
|
||||||
NO_DATA = $ff ; indicates that no data byte should be send
|
NO_DATA = $ff ;; indicates that no data byte should be send
|
||||||
NO_RESPONSE = $ff ; indicates a command did not receive a response (yet)
|
NO_RESPONSE = $ff ;; indicates a command did not receive a response (yet)
|
||||||
ACK = $fa ; successful transmission
|
ACK = $fa ;; successful transmission
|
||||||
RESEND = $fe ; unsuccessful transmission
|
RESEND = $fe ;; unsuccessful transmission
|
||||||
|
|
||||||
|
|
||||||
.enum STATUS
|
.enum STATUS
|
||||||
RECEIVE_KEYS = %10000000 ; keyboard sends scancodes
|
RECEIVE_KEYS = %10000000 ;; keyboard sends scancodes
|
||||||
RECEIVE_ANSWER = %01000000 ; keyboard replies to a command
|
RECEIVE_ANSWER = %01000000 ;; keyboard replies to a command
|
||||||
SEND_CMD = %00100000 ; host sends/sent the command byte
|
SEND_CMD = %00100000 ;; host sends/sent the command byte
|
||||||
SEND_DATA = %00010000 ; host sends/sent the data byte
|
SEND_DATA = %00010000 ;; host sends/sent the data byte
|
||||||
SEND_RECV = %00001000 ; keyboard sends additional data byte
|
SEND_RECV = %00001000 ;; keyboard sends additional data byte
|
||||||
SEND = SEND_CMD | SEND_DATA | SEND_RECV ; host is sending something, only used for checking status
|
SEND = SEND_CMD | SEND_DATA | SEND_RECV ;; host is sending something, only used for checking status
|
||||||
NONE = %00000000
|
NONE = %00000000
|
||||||
.endenum
|
.endenum
|
||||||
|
|
||||||
.enum TYPEMATIC
|
.enum TYPEMATIC
|
||||||
REPEAT_MASK = %00011111 ; 00000 = 30Hz, ..., 11111 = 2Hz
|
REPEAT_MASK = %00011111 ;; 00000 = 30Hz, ..., 11111 = 2Hz
|
||||||
DELAY250 = %00000000
|
DELAY250 = %00000000
|
||||||
DELAY500 = %00100000
|
DELAY500 = %00100000
|
||||||
DELAY750 = %01000000
|
DELAY750 = %01000000
|
||||||
@ -186,6 +206,10 @@ RESEND = $fe ; unsuccessful transmission
|
|||||||
bne :-
|
bne :-
|
||||||
.endmacro
|
.endmacro
|
||||||
|
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @note You need to manually include `string.h65` when using this macro!
|
||||||
|
;;********************************************************************************
|
||||||
.macro ps2kb_PrintCmdFailed
|
.macro ps2kb_PrintCmdFailed
|
||||||
Printf ps2kb::FMT_CMD_FAIL,ps2kb::send_cmd,ps2kb::send_data,ps2kb::cmd_response,ps2kb::cmd_response+1,ps2kb::cmd_response+2
|
Printf ps2kb::FMT_CMD_FAIL,ps2kb::send_cmd,ps2kb::send_data,ps2kb::cmd_response,ps2kb::cmd_response+1,ps2kb::cmd_response+2
|
||||||
.endmacro
|
.endmacro
|
||||||
|
@ -7,20 +7,21 @@ Export ps2kb, _receive_irq_shift_reg_handler, _receive_irq_timer_handler, _send_
|
|||||||
Export ps2kb, send_command, send_cmd, send_data, cmd_response, response_length, FMT_CMD_FAIL
|
Export ps2kb, send_command, send_cmd, send_data, cmd_response, response_length, FMT_CMD_FAIL
|
||||||
|
|
||||||
.bss
|
.bss
|
||||||
status: .res 1 ; current status
|
status: .res 1 ;; current status
|
||||||
prev_status: .res 1 ; status before sending command
|
prev_status: .res 1 ;; status before sending command
|
||||||
send_last_bits: .res 1 ; last bits to load after 8 bits were shifted out
|
send_last_bits: .res 1 ;; last bits to load after 8 bits were shifted out
|
||||||
send_cmd: .res 1 ; command to send/last sent
|
send_cmd: .res 1 ;; command to send/last sent
|
||||||
send_data: .res 1 ; data byte to send/last sent or NO_DATA
|
send_data: .res 1 ;; data byte to send/last sent or NO_DATA
|
||||||
expect_data_length: .res 1 ; number of data bytes to expect from keyboard
|
expect_data_length: .res 1 ;; number of data bytes to expect from keyboard
|
||||||
response_length: .res 1 ; number of response bytes from keyboard
|
response_length: .res 1 ;; number of response bytes from keyboard
|
||||||
cmd_response: .res 3 ; responses from keyboard
|
cmd_response: .res 3 ;; responses from keyboard
|
||||||
key_read: .res 2 ; first 8 bits, last 3 bits from scancode
|
key_read: .res 2 ;; first 8 bits, last 3 bits from scancode
|
||||||
scancode: .res 1 ; last received scancode
|
scancode: .res 1 ;; last received scancode
|
||||||
scancode_handler: .res 2 ; pointer to a function that handles new scancodes
|
scancode_handler: .res 2 ;; pointer to a function that handles new scancodes
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
|
; spi-transferred code will be placed here
|
||||||
; these are macros and not subroutines to save time during the interrupt handler (no jsr, rts)
|
; these are macros and not subroutines to save time during the interrupt handler (no jsr, rts)
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @macro Enable the clock signal from the keyboard
|
;; @macro Enable the clock signal from the keyboard
|
||||||
@ -80,6 +81,15 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
.endmacro
|
.endmacro
|
||||||
|
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @function Initialize the keyboard
|
||||||
|
;; @details
|
||||||
|
;; - @ref _DisableClock "Disable the clock"
|
||||||
|
;; - Initialize variables to 0
|
||||||
|
;; - Clear the VIAs shift register and set T2 to oneshote mode
|
||||||
|
;; - Set scancode_handler to immediately return (dont handle scancodes)
|
||||||
|
;; @modifies: A
|
||||||
|
;;********************************************************************************
|
||||||
.proc init
|
.proc init
|
||||||
_DisableClock
|
_DisableClock
|
||||||
stz key_read
|
stz key_read
|
||||||
@ -468,5 +478,5 @@ scancode_handler: .res 2 ; pointer to a function that handles new scancod
|
|||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
.rodata
|
.rodata
|
||||||
;; Can be used by other programs
|
;; Format string that can be used by other programs for keyboard command errors
|
||||||
FMT_CMD_FAIL: .asciiz "PS/2 Cmd fail: %x-%x > %x%x%x "
|
FMT_CMD_FAIL: .asciiz "PS/2 Cmd fail: %x-%x > %x%x%x "
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @module SPI-P
|
;; @module SPI-P
|
||||||
;; @type driver
|
|
||||||
;; @details
|
;; @details
|
||||||
;; Support being a peripheral SPI device.
|
;; Support being a peripheral SPI device.
|
||||||
;; @depends IO-W65C22N
|
;; @depends IO-W65C22N
|
||||||
@ -11,11 +10,16 @@ INCLUDE_SPI = 1
|
|||||||
.include "system/system.h65"
|
.include "system/system.h65"
|
||||||
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @brief SPI-Peripheral
|
;; @brief Support being a peripheral SPI device
|
||||||
|
;; @details
|
||||||
|
;; This requires the data line to be hooked up to `CB2` and the clock to `CB1`.
|
||||||
|
;; The VIA will be set to shift in the data into the shift register under the external clock.
|
||||||
|
;; @ingroup driver
|
||||||
|
;; @see via_hardware_bug "VIA external clock bug"
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.scope spi_p
|
.scope spi_p
|
||||||
|
|
||||||
|
;; Address of the VIA that is used for the spi connection
|
||||||
SPI_IO = IO2
|
SPI_IO = IO2
|
||||||
Import spi_p, init, irq_handler, status, buffer_size, recv_size
|
Import spi_p, init, irq_handler, status, buffer_size, recv_size
|
||||||
ImportZp spi_p, buffer_ptr
|
ImportZp spi_p, buffer_ptr
|
||||||
|
22
test.s65
22
test.s65
@ -1,22 +0,0 @@
|
|||||||
; .include "other/file.h65"
|
|
||||||
|
|
||||||
|
|
||||||
.segment "TEST"
|
|
||||||
; .proc my_subroutine
|
|
||||||
; pha
|
|
||||||
; bbr4 var1,@bit_4_set
|
|
||||||
; bit var1
|
|
||||||
; ; macro packs are supported
|
|
||||||
; jmi other_routine
|
|
||||||
; lda #'a'
|
|
||||||
; sta char
|
|
||||||
; bra @end
|
|
||||||
; @bit_4_set:
|
|
||||||
; ; custom macros can be highlighted
|
|
||||||
; Printf STR_FMT,char,var1
|
|
||||||
; @end:
|
|
||||||
; pla
|
|
||||||
; rts
|
|
||||||
; .endproc
|
|
||||||
|
|
||||||
; STR_FMT: .asciiz "%c: num=%x"
|
|
@ -1,19 +1,22 @@
|
|||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @module math
|
;; @module math
|
||||||
; @type utility
|
;; @details
|
||||||
; @details
|
;; Math library
|
||||||
; Math library
|
;;********************************************************************************
|
||||||
;********************************************************************************
|
|
||||||
.ifndef INCLUDE_MATH
|
.ifndef INCLUDE_MATH
|
||||||
INCLUDE_MATH = 1
|
INCLUDE_MATH = 1
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Math library
|
||||||
|
;; @ingroup utility
|
||||||
|
;;********************************************************************************
|
||||||
.scope math
|
.scope math
|
||||||
|
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
; @macro Divide a num (or A) by a factor
|
;; @macro Divide a num (or A) by a factor
|
||||||
; @param num: Memory or A
|
;; @param num: Memory or A
|
||||||
; @param divider: must be power of 2
|
;; @param divider: must be power of 2
|
||||||
;********************************************************************************
|
;;********************************************************************************
|
||||||
.macro div num,divider
|
.macro div num,divider
|
||||||
.if divider = 2
|
.if divider = 2
|
||||||
lsr num
|
lsr num
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
.rodata
|
.rodata
|
||||||
.align 256
|
.align 256
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief A 256 byte table where the *i*-th byte is the value *i* with bits reversed
|
||||||
|
;; @see Reverse
|
||||||
|
;;********************************************************************************
|
||||||
REVERSE_TABLE:
|
REVERSE_TABLE:
|
||||||
.byte $00, $80, $40, $c0, $20, $a0, $60, $e0
|
.byte $00, $80, $40, $c0, $20, $a0, $60, $e0
|
||||||
.byte $10, $90, $50, $d0, $30, $b0, $70, $f0
|
.byte $10, $90, $50, $d0, $30, $b0, $70, $f0
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @module string
|
;; @module string
|
||||||
;; @type utility
|
|
||||||
;; @details
|
;; @details
|
||||||
;; String utility
|
;; String utility
|
||||||
|
;; @see str
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.ifndef INCLUDE_STRING
|
.ifndef INCLUDE_STRING
|
||||||
INCLUDE_STRING = 1
|
INCLUDE_STRING = 1
|
||||||
@ -12,6 +12,7 @@ INCLUDE_STRING = 1
|
|||||||
|
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @brief String utility
|
;; @brief String utility
|
||||||
|
;; @ingroup utility
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.scope str
|
.scope str
|
||||||
Import str, strf, printf_buffer
|
Import str, strf, printf_buffer
|
||||||
@ -22,7 +23,7 @@ Import str, uint8_to_hex_str, uint_to_hex_str
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @macro Helper for str::Strf macro
|
;; @macro Helper for str::Strf macro
|
||||||
;; @details
|
;; @details
|
||||||
;; Store arg in ARG4-ARG... and increment counter variable @N_ARGS one.
|
;; Store arg in ARG4-ARG... and increment counter variable `\@N_ARGS` by one.
|
||||||
;; Arg can be x, y, immediate or an address
|
;; Arg can be x, y, immediate or an address
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
.macro _StrfStoreArg arg
|
.macro _StrfStoreArg arg
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
Export str, strf, printf_buffer
|
Export str, strf, printf_buffer
|
||||||
|
|
||||||
.bss
|
.bss
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @brief Used to store output string of Printf macro
|
||||||
|
;; @todo Use dynamically allocated buffer when a memory allocator is implemented
|
||||||
|
;;********************************************************************************
|
||||||
printf_buffer: .res $41
|
printf_buffer: .res $41
|
||||||
|
|
||||||
.zeropage
|
.zeropage
|
||||||
@ -14,14 +18,15 @@ digits: .res 1
|
|||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @function Format a string
|
;; @function Format a string
|
||||||
;; @details
|
;; @details
|
||||||
;; If there is no value to be read, the Pz will be set
|
;; If there is no value to be read, the `Pz` will be set
|
||||||
;; Formats:
|
;; Formats:
|
||||||
;; - x: unsigned hex integer (1 byte) -> 2 chars
|
;; - `x`: unsigned hex integer (1 byte) -> 2 chars
|
||||||
;; - X: unsigned hex integer (2 byte) -> 4 chars TODO
|
;; - `X`: unsigned hex integer (2 byte) -> 4 chars TODO
|
||||||
;; - u: unsigned decimal integer (1 byte) TODO
|
;; - `u`: unsigned decimal integer (1 byte) TODO
|
||||||
;; - U: unsigned decimal integer (2 bytes) TODO
|
;; - `U`: unsigned decimal integer (2 bytes) TODO
|
||||||
;; - s: null-terminated string (2 bytes ptr)
|
;; - `s`: null-terminated string (2 bytes ptr)
|
||||||
;; - c: char
|
;; - `c`: char
|
||||||
|
;; @todo Implement decimal, test X
|
||||||
;; @param ARG0-1: Format string address
|
;; @param ARG0-1: Format string address
|
||||||
;; @param ARG2-3: Output string address
|
;; @param ARG2-3: Output string address
|
||||||
;; @param ARG4+: Additional parameters
|
;; @param ARG4+: Additional parameters
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
.ifndef INCLUDE_UTILITY
|
.ifndef INCLUDE_UTILITY
|
||||||
INCLUDE_UTILITY = 1
|
INCLUDE_UTILITY = 1
|
||||||
|
|
||||||
|
|
||||||
|
;;********************************************************************************
|
||||||
|
;; @file
|
||||||
|
;; @brief Various useful macros
|
||||||
|
;; @ingroup utility
|
||||||
|
;;********************************************************************************
|
||||||
|
|
||||||
.macpack longbranch ; jeq, jge...
|
.macpack longbranch ; jeq, jge...
|
||||||
.macpack generic ; bge, add, sub
|
.macpack generic ; bge, add, sub
|
||||||
|
|
||||||
@ -190,7 +197,7 @@ _n_genlabel .set 0
|
|||||||
|
|
||||||
.import REVERSE_TABLE
|
.import REVERSE_TABLE
|
||||||
;;********************************************************************************
|
;;********************************************************************************
|
||||||
;; @macro Reverse a byte
|
;; @macro Reverse a byte using a @ref REVERSE_TABLE "table"
|
||||||
;; @param reg: The byte to reverse. May be in X, Y or A
|
;; @param reg: The byte to reverse. May be in X, Y or A
|
||||||
;; @returns A: The reversed byte
|
;; @returns A: The reversed byte
|
||||||
;; @modifies A, X (only when reg = A)
|
;; @modifies A, X (only when reg = A)
|
||||||
|
Loading…
Reference in New Issue
Block a user