forked from Akcelerometry_drgania_WMT/PI_mikrokontroler
Initial commit: PI_mikrokontroler changes
This commit is contained in:
243
firmware_adxl345_spi/lib/Adafruit BusIO/.clang-format
Normal file
243
firmware_adxl345_spi/lib/Adafruit BusIO/.clang-format
Normal file
@@ -0,0 +1,243 @@
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
46
firmware_adxl345_spi/lib/Adafruit BusIO/.github/ISSUE_TEMPLATE.md
vendored
Normal file
46
firmware_adxl345_spi/lib/Adafruit BusIO/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||
improve the speed of resolution please review the following guidelines and
|
||||
common troubleshooting steps below before creating the issue:
|
||||
|
||||
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||
something isn't working as expected. In many cases the problem is a common issue
|
||||
that you will more quickly receive help from the forum community. GitHub issues
|
||||
are meant for known defects in the code. If you don't know if there is a defect
|
||||
in the code then start with troubleshooting on the forum first.
|
||||
|
||||
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||
check all of the steps and commands to run have been followed. Consult the
|
||||
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||
|
||||
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||
|
||||
- For uploading sketches or communicating with the board make sure you're using
|
||||
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||
very hard to tell the difference between a data and charge cable! Try using the
|
||||
cable with other devices or swapping to another cable to confirm it is not
|
||||
the problem.
|
||||
|
||||
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||
your board and plug in an external power supply. In many cases just
|
||||
plugging a board into your computer is not enough to power it and other
|
||||
peripherals.
|
||||
|
||||
- **Double check all soldering joints and connections.** Flakey connections
|
||||
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||
|
||||
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||
guarantee a clone board will have the same functionality and work as expected
|
||||
with this code and don't support them.
|
||||
|
||||
If you're sure this issue is a defect in the code and checked the steps above
|
||||
please fill in the following fields to provide enough troubleshooting information.
|
||||
You may delete the guideline and text above to just leave the following details:
|
||||
|
||||
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||
|
||||
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||
VERSION HERE**
|
||||
|
||||
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
||||
26
firmware_adxl345_spi/lib/Adafruit BusIO/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
26
firmware_adxl345_spi/lib/Adafruit BusIO/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||
Before you open the request please review the following guidelines and tips to
|
||||
help it be more easily integrated:
|
||||
|
||||
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||
of the code were modified.** This will help us understand any risks of integrating
|
||||
the code.
|
||||
|
||||
- **Describe any known limitations with your change.** For example if the change
|
||||
doesn't apply to a supported platform of the library please mention it.
|
||||
|
||||
- **Please run any tests or examples that can exercise your modified code.** We
|
||||
strive to not break users of the code and running tests/examples helps with this
|
||||
process.
|
||||
|
||||
Thank you again for contributing! We will try to test and integrate the change
|
||||
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||
can't immediately respond to every request. There is no need to bump or check in
|
||||
on a pull request (it will clutter the discussion of the request).
|
||||
|
||||
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||
priorities of the pull request. Don't fret, the open source community thrives on
|
||||
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||
|
||||
After reviewing the guidelines above you can delete this text from the pull request.
|
||||
33
firmware_adxl345_spi/lib/Adafruit BusIO/.github/workflows/githubci.yml
vendored
Normal file
33
firmware_adxl345_spi/lib/Adafruit BusIO/.github/workflows/githubci.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Arduino Library CI
|
||||
|
||||
on: [pull_request, push, repository_dispatch]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: adafruit/ci-arduino
|
||||
path: ci
|
||||
|
||||
- name: Install the prerequisites
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
- name: Check for correct code formatting with clang-format
|
||||
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
|
||||
|
||||
- name: Check for correct documentation with doxygen
|
||||
env:
|
||||
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
|
||||
PRETTYNAME : "Adafruit Bus IO Library"
|
||||
run: bash ci/doxy_gen_and_deploy.sh
|
||||
|
||||
- name: Test the code on supported platforms
|
||||
run: python3 ci/build_platform.py main_platforms zero feather32u4
|
||||
|
||||
1
firmware_adxl345_spi/lib/Adafruit BusIO/.piopm
Normal file
1
firmware_adxl345_spi/lib/Adafruit BusIO/.piopm
Normal file
@@ -0,0 +1 @@
|
||||
{"type": "library", "name": "Adafruit BusIO", "version": "1.17.4", "spec": {"owner": "adafruit", "id": 6214, "name": "Adafruit BusIO", "requirements": null, "uri": null}}
|
||||
@@ -0,0 +1,384 @@
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
|
||||
#if !defined(SPI_INTERFACES_COUNT) || \
|
||||
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
|
||||
|
||||
/*!
|
||||
* @brief Create a register we access over an I2C Device (which defines the
|
||||
* bus and address)
|
||||
* @param i2cdevice The I2CDevice to use for underlying I2C access
|
||||
* @param reg_addr The address pointer value for the I2C/SMBus register, can
|
||||
* be 8 or 16 bits
|
||||
* @param width The width of the register data itself, defaults to 1 byte
|
||||
* @param byteorder The byte order of the register (used when width is > 1),
|
||||
* defaults to LSBFIRST
|
||||
* @param address_width The width of the register address itself, defaults
|
||||
* to 1 byte
|
||||
*/
|
||||
Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
|
||||
uint16_t reg_addr,
|
||||
uint8_t width,
|
||||
uint8_t byteorder,
|
||||
uint8_t address_width) {
|
||||
_i2cdevice = i2cdevice;
|
||||
_spidevice = nullptr;
|
||||
_addrwidth = address_width;
|
||||
_address = reg_addr;
|
||||
_byteorder = byteorder;
|
||||
_width = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create a register we access over an SPI Device (which defines the
|
||||
* bus and CS pin)
|
||||
* @param spidevice The SPIDevice to use for underlying SPI access
|
||||
* @param reg_addr The address pointer value for the SPI register, can
|
||||
* be 8 or 16 bits
|
||||
* @param type The method we use to read/write data to SPI (which is not
|
||||
* as well defined as I2C)
|
||||
* @param width The width of the register data itself, defaults to 1 byte
|
||||
* @param byteorder The byte order of the register (used when width is > 1),
|
||||
* defaults to LSBFIRST
|
||||
* @param address_width The width of the register address itself, defaults
|
||||
* to 1 byte
|
||||
*/
|
||||
Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice,
|
||||
uint16_t reg_addr,
|
||||
Adafruit_BusIO_SPIRegType type,
|
||||
uint8_t width,
|
||||
uint8_t byteorder,
|
||||
uint8_t address_width) {
|
||||
_spidevice = spidevice;
|
||||
_spiregtype = type;
|
||||
_i2cdevice = nullptr;
|
||||
_addrwidth = address_width;
|
||||
_address = reg_addr;
|
||||
_byteorder = byteorder;
|
||||
_width = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create a register we access over an I2C or SPI Device. This is a
|
||||
* handy function because we can pass in nullptr for the unused interface,
|
||||
* allowing libraries to mass-define all the registers
|
||||
* @param i2cdevice The I2CDevice to use for underlying I2C access, if
|
||||
* nullptr we use SPI
|
||||
* @param spidevice The SPIDevice to use for underlying SPI access, if
|
||||
* nullptr we use I2C
|
||||
* @param reg_addr The address pointer value for the I2C/SMBus/SPI register,
|
||||
* can be 8 or 16 bits
|
||||
* @param type The method we use to read/write data to SPI (which is not
|
||||
* as well defined as I2C)
|
||||
* @param width The width of the register data itself, defaults to 1 byte
|
||||
* @param byteorder The byte order of the register (used when width is > 1),
|
||||
* defaults to LSBFIRST
|
||||
* @param address_width The width of the register address itself, defaults
|
||||
* to 1 byte
|
||||
*/
|
||||
Adafruit_BusIO_Register::Adafruit_BusIO_Register(
|
||||
Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice,
|
||||
Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, uint8_t width,
|
||||
uint8_t byteorder, uint8_t address_width) {
|
||||
_spidevice = spidevice;
|
||||
_i2cdevice = i2cdevice;
|
||||
_spiregtype = type;
|
||||
_addrwidth = address_width;
|
||||
_address = reg_addr;
|
||||
_byteorder = byteorder;
|
||||
_width = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create a register we access over a GenericDevice
|
||||
* @param genericdevice Generic device to use
|
||||
* @param reg_addr Register address we will read/write
|
||||
* @param width Width of the register in bytes (1-4)
|
||||
* @param byteorder Byte order of register data (LSBFIRST or MSBFIRST)
|
||||
* @param address_width Width of the register address in bytes (1 or 2)
|
||||
*/
|
||||
Adafruit_BusIO_Register::Adafruit_BusIO_Register(
|
||||
Adafruit_GenericDevice *genericdevice, uint16_t reg_addr, uint8_t width,
|
||||
uint8_t byteorder, uint8_t address_width) {
|
||||
_i2cdevice = nullptr;
|
||||
_spidevice = nullptr;
|
||||
_genericdevice = genericdevice;
|
||||
_addrwidth = address_width;
|
||||
_address = reg_addr;
|
||||
_byteorder = byteorder;
|
||||
_width = width;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write a buffer of data to the register location
|
||||
* @param buffer Pointer to data to write
|
||||
* @param len Number of bytes to write
|
||||
* @return True on successful write (only really useful for I2C as SPI is
|
||||
* uncheckable)
|
||||
*/
|
||||
bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
|
||||
uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
|
||||
(uint8_t)(_address >> 8)};
|
||||
if (_i2cdevice) {
|
||||
return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth);
|
||||
}
|
||||
if (_spidevice) {
|
||||
if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) {
|
||||
// very special case!
|
||||
// pass the special opcode address which we set as the high byte of the
|
||||
// regaddr
|
||||
addrbuffer[0] =
|
||||
(uint8_t)(_address >> 8) & ~0x01; // set bottom bit low to write
|
||||
// the 'actual' reg addr is the second byte then
|
||||
addrbuffer[1] = (uint8_t)(_address & 0xFF);
|
||||
// the address appears to be a byte longer
|
||||
return _spidevice->write(buffer, len, addrbuffer, _addrwidth + 1);
|
||||
}
|
||||
if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
|
||||
addrbuffer[0] &= ~0x80;
|
||||
}
|
||||
if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) {
|
||||
addrbuffer[0] |= 0x80;
|
||||
}
|
||||
if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) {
|
||||
addrbuffer[0] &= ~0x80;
|
||||
addrbuffer[0] |= 0x40;
|
||||
}
|
||||
return _spidevice->write(buffer, len, addrbuffer, _addrwidth);
|
||||
}
|
||||
if (_genericdevice) {
|
||||
return _genericdevice->writeRegister(addrbuffer, _addrwidth, buffer, len);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write up to 4 bytes of data to the register location
|
||||
* @param value Data to write
|
||||
* @param numbytes How many bytes from 'value' to write
|
||||
* @return True on successful write (only really useful for I2C as SPI is
|
||||
* uncheckable)
|
||||
*/
|
||||
bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) {
|
||||
if (numbytes == 0) {
|
||||
numbytes = _width;
|
||||
}
|
||||
if (numbytes > 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// store a copy
|
||||
_cached = value;
|
||||
|
||||
for (int i = 0; i < numbytes; i++) {
|
||||
if (_byteorder == LSBFIRST) {
|
||||
_buffer[i] = value & 0xFF;
|
||||
} else {
|
||||
_buffer[numbytes - i - 1] = value & 0xFF;
|
||||
}
|
||||
value >>= 8;
|
||||
}
|
||||
return write(_buffer, numbytes);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read data from the register location. This does not do any error
|
||||
* checking!
|
||||
* @return Returns 0xFFFFFFFF on failure, value otherwise
|
||||
*/
|
||||
uint32_t Adafruit_BusIO_Register::read(void) {
|
||||
if (!read(_buffer, _width)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t value = 0;
|
||||
|
||||
for (int i = 0; i < _width; i++) {
|
||||
value <<= 8;
|
||||
if (_byteorder == LSBFIRST) {
|
||||
value |= _buffer[_width - i - 1];
|
||||
} else {
|
||||
value |= _buffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read cached data from last time we wrote to this register
|
||||
* @return Returns 0xFFFFFFFF on failure, value otherwise
|
||||
*/
|
||||
uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; }
|
||||
|
||||
/*!
|
||||
@brief Read a number of bytes from a register into a buffer
|
||||
@param buffer Buffer to read data into
|
||||
@param len Number of bytes to read into the buffer
|
||||
@return true on successful read, otherwise false
|
||||
*/
|
||||
bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
|
||||
uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
|
||||
(uint8_t)(_address >> 8)};
|
||||
if (_i2cdevice) {
|
||||
return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
|
||||
}
|
||||
if (_spidevice) {
|
||||
if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) {
|
||||
// very special case!
|
||||
// pass the special opcode address which we set as the high byte of the
|
||||
// regaddr
|
||||
addrbuffer[0] =
|
||||
(uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read
|
||||
// the 'actual' reg addr is the second byte then
|
||||
addrbuffer[1] = (uint8_t)(_address & 0xFF);
|
||||
// the address appears to be a byte longer
|
||||
return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer,
|
||||
len);
|
||||
}
|
||||
if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
|
||||
addrbuffer[0] |= 0x80;
|
||||
}
|
||||
if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) {
|
||||
addrbuffer[0] &= ~0x80;
|
||||
}
|
||||
if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) {
|
||||
addrbuffer[0] |= 0x80 | 0x40;
|
||||
}
|
||||
return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
|
||||
}
|
||||
if (_genericdevice) {
|
||||
return _genericdevice->readRegister(addrbuffer, _addrwidth, buffer, len);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read 2 bytes of data from the register location
|
||||
* @param value Pointer to uint16_t variable to read into
|
||||
* @return True on successful write (only really useful for I2C as SPI is
|
||||
* uncheckable)
|
||||
*/
|
||||
bool Adafruit_BusIO_Register::read(uint16_t *value) {
|
||||
if (!read(_buffer, 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_byteorder == LSBFIRST) {
|
||||
*value = _buffer[1];
|
||||
*value <<= 8;
|
||||
*value |= _buffer[0];
|
||||
} else {
|
||||
*value = _buffer[0];
|
||||
*value <<= 8;
|
||||
*value |= _buffer[1];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read 1 byte of data from the register location
|
||||
* @param value Pointer to uint8_t variable to read into
|
||||
* @return True on successful write (only really useful for I2C as SPI is
|
||||
* uncheckable)
|
||||
*/
|
||||
bool Adafruit_BusIO_Register::read(uint8_t *value) {
|
||||
if (!read(_buffer, 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = _buffer[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Pretty printer for this register
|
||||
* @param s The Stream to print to, defaults to &Serial
|
||||
*/
|
||||
void Adafruit_BusIO_Register::print(Stream *s) {
|
||||
uint32_t val = read();
|
||||
s->print("0x");
|
||||
s->print(val, HEX);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Pretty printer for this register
|
||||
* @param s The Stream to print to, defaults to &Serial
|
||||
*/
|
||||
void Adafruit_BusIO_Register::println(Stream *s) {
|
||||
print(s);
|
||||
s->println();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create a slice of the register that we can address without
|
||||
* touching other bits
|
||||
* @param reg The Adafruit_BusIO_Register which defines the bus/register
|
||||
* @param bits The number of bits wide we are slicing
|
||||
* @param shift The number of bits that our bit-slice is shifted from LSB
|
||||
*/
|
||||
Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits(
|
||||
Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) {
|
||||
_register = reg;
|
||||
_bits = bits;
|
||||
_shift = shift;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read 4 bytes of data from the register
|
||||
* @return data The 4 bytes to read
|
||||
*/
|
||||
uint32_t Adafruit_BusIO_RegisterBits::read(void) {
|
||||
uint32_t val = _register->read();
|
||||
val >>= _shift;
|
||||
return val & ((1 << (_bits)) - 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write 4 bytes of data to the register
|
||||
* @param data The 4 bytes to write
|
||||
* @return True on successful write (only really useful for I2C as SPI is
|
||||
* uncheckable)
|
||||
*/
|
||||
bool Adafruit_BusIO_RegisterBits::write(uint32_t data) {
|
||||
uint32_t val = _register->read();
|
||||
|
||||
// mask off the data before writing
|
||||
uint32_t mask = (1 << (_bits)) - 1;
|
||||
data &= mask;
|
||||
|
||||
mask <<= _shift;
|
||||
val &= ~mask; // remove the current data at that spot
|
||||
val |= data << _shift; // and add in the new data
|
||||
|
||||
return _register->write(val, _register->width());
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief The width of the register data, helpful for doing calculations
|
||||
* @returns The data width used when initializing the register
|
||||
*/
|
||||
uint8_t Adafruit_BusIO_Register::width(void) { return _width; }
|
||||
|
||||
/*!
|
||||
* @brief Set the default width of data
|
||||
* @param width the default width of data read from register
|
||||
*/
|
||||
void Adafruit_BusIO_Register::setWidth(uint8_t width) { _width = width; }
|
||||
|
||||
/*!
|
||||
* @brief Set register address
|
||||
* @param address the address from register
|
||||
*/
|
||||
void Adafruit_BusIO_Register::setAddress(uint16_t address) {
|
||||
_address = address;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the width of register address
|
||||
* @param address_width the width for register address
|
||||
*/
|
||||
void Adafruit_BusIO_Register::setAddressWidth(uint16_t address_width) {
|
||||
_addrwidth = address_width;
|
||||
}
|
||||
|
||||
#endif // SPI exists
|
||||
@@ -0,0 +1,117 @@
|
||||
#ifndef Adafruit_BusIO_Register_h
|
||||
#define Adafruit_BusIO_Register_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if !defined(SPI_INTERFACES_COUNT) || \
|
||||
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
|
||||
|
||||
#include <Adafruit_GenericDevice.h>
|
||||
#include <Adafruit_I2CDevice.h>
|
||||
#include <Adafruit_SPIDevice.h>
|
||||
|
||||
typedef enum _Adafruit_BusIO_SPIRegType {
|
||||
ADDRBIT8_HIGH_TOREAD = 0,
|
||||
/*!<
|
||||
* ADDRBIT8_HIGH_TOREAD
|
||||
* When reading a register you must actually send the value 0x80 + register
|
||||
* address to the device. e.g. To read the register 0x0B the register value
|
||||
* 0x8B is sent and to write 0x0B is sent.
|
||||
*/
|
||||
AD8_HIGH_TOREAD_AD7_HIGH_TOINC = 1,
|
||||
|
||||
/*!<
|
||||
* ADDRBIT8_HIGH_TOWRITE
|
||||
* When writing to a register you must actually send the value 0x80 +
|
||||
* the register address to the device. e.g. To write to the register 0x19 the
|
||||
* register value 0x99 is sent and to read 0x19 is sent.
|
||||
*/
|
||||
ADDRBIT8_HIGH_TOWRITE = 2,
|
||||
|
||||
/*!<
|
||||
* ADDRESSED_OPCODE_LOWBIT_TO_WRITE
|
||||
* Used by the MCP23S series, we send 0x40 |'rd with the opcode
|
||||
* Then set the lowest bit to write
|
||||
*/
|
||||
ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE = 3,
|
||||
|
||||
} Adafruit_BusIO_SPIRegType;
|
||||
|
||||
/*!
|
||||
* @brief The class which defines a device register (a location to read/write
|
||||
* data from)
|
||||
*/
|
||||
class Adafruit_BusIO_Register {
|
||||
public:
|
||||
Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr,
|
||||
uint8_t width = 1, uint8_t byteorder = LSBFIRST,
|
||||
uint8_t address_width = 1);
|
||||
|
||||
Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr,
|
||||
Adafruit_BusIO_SPIRegType type, uint8_t width = 1,
|
||||
uint8_t byteorder = LSBFIRST,
|
||||
uint8_t address_width = 1);
|
||||
|
||||
Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
|
||||
Adafruit_SPIDevice *spidevice,
|
||||
Adafruit_BusIO_SPIRegType type, uint16_t reg_addr,
|
||||
uint8_t width = 1, uint8_t byteorder = LSBFIRST,
|
||||
uint8_t address_width = 1);
|
||||
|
||||
Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice,
|
||||
uint16_t reg_addr, uint8_t width = 1,
|
||||
uint8_t byteorder = LSBFIRST,
|
||||
uint8_t address_width = 1);
|
||||
|
||||
bool read(uint8_t *buffer, uint8_t len);
|
||||
bool read(uint8_t *value);
|
||||
bool read(uint16_t *value);
|
||||
uint32_t read(void);
|
||||
uint32_t readCached(void);
|
||||
bool write(uint8_t *buffer, uint8_t len);
|
||||
bool write(uint32_t value, uint8_t numbytes = 0);
|
||||
|
||||
uint8_t width(void);
|
||||
|
||||
void setWidth(uint8_t width);
|
||||
void setAddress(uint16_t address);
|
||||
void setAddressWidth(uint16_t address_width);
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
||||
void print(Stream *s = &Serial);
|
||||
void println(Stream *s = &Serial);
|
||||
#else
|
||||
void print(Stream *s);
|
||||
void println(Stream *s);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Adafruit_I2CDevice *_i2cdevice;
|
||||
Adafruit_SPIDevice *_spidevice;
|
||||
Adafruit_GenericDevice *_genericdevice;
|
||||
Adafruit_BusIO_SPIRegType _spiregtype;
|
||||
uint16_t _address;
|
||||
uint8_t _width, _addrwidth, _byteorder;
|
||||
uint8_t _buffer[4]; // we won't support anything larger than uint32 for
|
||||
// non-buffered read
|
||||
uint32_t _cached = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief The class which defines a slice of bits from within a device register
|
||||
* (a location to read/write data from)
|
||||
*/
|
||||
class Adafruit_BusIO_RegisterBits {
|
||||
public:
|
||||
Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits,
|
||||
uint8_t shift);
|
||||
bool write(uint32_t value);
|
||||
uint32_t read(void);
|
||||
|
||||
private:
|
||||
Adafruit_BusIO_Register *_register;
|
||||
uint8_t _bits, _shift;
|
||||
};
|
||||
|
||||
#endif // SPI exists
|
||||
#endif // BusIO_Register_h
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Written with help by Claude!
|
||||
https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time
|
||||
chats are not shareable :(
|
||||
*/
|
||||
|
||||
#include "Adafruit_GenericDevice.h"
|
||||
|
||||
/*!
|
||||
* @brief Create a Generic device with the provided read/write functions
|
||||
* @param obj Pointer to object instance
|
||||
* @param read_func Function pointer for reading raw data
|
||||
* @param write_func Function pointer for writing raw data
|
||||
* @param readreg_func Function pointer for reading registers (optional)
|
||||
* @param writereg_func Function pointer for writing registers (optional) */
|
||||
Adafruit_GenericDevice::Adafruit_GenericDevice(
|
||||
void *obj, busio_genericdevice_read_t read_func,
|
||||
busio_genericdevice_write_t write_func,
|
||||
busio_genericdevice_readreg_t readreg_func,
|
||||
busio_genericdevice_writereg_t writereg_func) {
|
||||
_obj = obj;
|
||||
_read_func = read_func;
|
||||
_write_func = write_func;
|
||||
_readreg_func = readreg_func;
|
||||
_writereg_func = writereg_func;
|
||||
_begun = false;
|
||||
}
|
||||
|
||||
/*! @brief Simple begin function (doesn't do much at this time)
|
||||
@return true always
|
||||
*/
|
||||
bool Adafruit_GenericDevice::begin(void) {
|
||||
_begun = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Marks the GenericDevice as no longer in use.
|
||||
@note: Since this is a GenericDevice, if you are using this with a Serial
|
||||
object, this does NOT disable serial communication or release the RX/TX pins.
|
||||
That must be done manually by calling Serial.end().
|
||||
*/
|
||||
void Adafruit_GenericDevice::end(void) { _begun = false; }
|
||||
|
||||
/*! @brief Write a buffer of data
|
||||
@param buffer Pointer to buffer of data to write
|
||||
@param len Number of bytes to write
|
||||
@return true if write was successful, otherwise false */
|
||||
bool Adafruit_GenericDevice::write(const uint8_t *buffer, size_t len) {
|
||||
if (!_begun)
|
||||
return false;
|
||||
return _write_func(_obj, buffer, len);
|
||||
}
|
||||
|
||||
/*! @brief Read data into a buffer
|
||||
@param buffer Pointer to buffer to read data into
|
||||
@param len Number of bytes to read
|
||||
@return true if read was successful, otherwise false */
|
||||
bool Adafruit_GenericDevice::read(uint8_t *buffer, size_t len) {
|
||||
if (!_begun)
|
||||
return false;
|
||||
return _read_func(_obj, buffer, len);
|
||||
}
|
||||
|
||||
/*! @brief Read from a register location
|
||||
@param addr_buf Buffer containing register address
|
||||
@param addrsiz Size of register address in bytes
|
||||
@param buf Buffer to store read data
|
||||
@param bufsiz Size of data to read in bytes
|
||||
@return true if read was successful, otherwise false */
|
||||
bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz,
|
||||
uint8_t *buf, uint16_t bufsiz) {
|
||||
if (!_begun || !_readreg_func)
|
||||
return false;
|
||||
return _readreg_func(_obj, addr_buf, addrsiz, buf, bufsiz);
|
||||
}
|
||||
|
||||
/*! @brief Write to a register location
|
||||
@param addr_buf Buffer containing register address
|
||||
@param addrsiz Size of register address in bytes
|
||||
@param buf Buffer containing data to write
|
||||
@param bufsiz Size of data to write in bytes
|
||||
@return true if write was successful, otherwise false */
|
||||
bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz,
|
||||
const uint8_t *buf,
|
||||
uint16_t bufsiz) {
|
||||
if (!_begun || !_writereg_func)
|
||||
return false;
|
||||
return _writereg_func(_obj, addr_buf, addrsiz, buf, bufsiz);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef ADAFRUIT_GENERICDEVICE_H
|
||||
#define ADAFRUIT_GENERICDEVICE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
typedef bool (*busio_genericdevice_read_t)(void *obj, uint8_t *buffer,
|
||||
size_t len);
|
||||
typedef bool (*busio_genericdevice_write_t)(void *obj, const uint8_t *buffer,
|
||||
size_t len);
|
||||
typedef bool (*busio_genericdevice_readreg_t)(void *obj, uint8_t *addr_buf,
|
||||
uint8_t addrsiz, uint8_t *data,
|
||||
uint16_t datalen);
|
||||
typedef bool (*busio_genericdevice_writereg_t)(void *obj, uint8_t *addr_buf,
|
||||
uint8_t addrsiz,
|
||||
const uint8_t *data,
|
||||
uint16_t datalen);
|
||||
|
||||
/*!
|
||||
* @brief Class for communicating with a device via generic read/write functions
|
||||
*/
|
||||
class Adafruit_GenericDevice {
|
||||
public:
|
||||
Adafruit_GenericDevice(
|
||||
void *obj, busio_genericdevice_read_t read_func,
|
||||
busio_genericdevice_write_t write_func,
|
||||
busio_genericdevice_readreg_t readreg_func = nullptr,
|
||||
busio_genericdevice_writereg_t writereg_func = nullptr);
|
||||
|
||||
bool begin(void);
|
||||
void end(void);
|
||||
|
||||
bool read(uint8_t *buffer, size_t len);
|
||||
bool write(const uint8_t *buffer, size_t len);
|
||||
bool readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf,
|
||||
uint16_t bufsiz);
|
||||
bool writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf,
|
||||
uint16_t bufsiz);
|
||||
|
||||
protected:
|
||||
/*! @brief Function pointer for reading raw data from the device */
|
||||
busio_genericdevice_read_t _read_func;
|
||||
/*! @brief Function pointer for writing raw data to the device */
|
||||
busio_genericdevice_write_t _write_func;
|
||||
/*! @brief Function pointer for reading a 'register' from the device */
|
||||
busio_genericdevice_readreg_t _readreg_func;
|
||||
/*! @brief Function pointer for writing a 'register' to the device */
|
||||
busio_genericdevice_writereg_t _writereg_func;
|
||||
|
||||
bool _begun; ///< whether we have initialized yet (in case the function needs
|
||||
///< to do something)
|
||||
|
||||
private:
|
||||
void *_obj; ///< Pointer to object instance
|
||||
};
|
||||
|
||||
#endif // ADAFRUIT_GENERICDEVICE_H
|
||||
320
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_I2CDevice.cpp
Normal file
320
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_I2CDevice.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
#include "Adafruit_I2CDevice.h"
|
||||
|
||||
// #define DEBUG_SERIAL Serial
|
||||
|
||||
/*!
|
||||
* @brief Create an I2C device at a given address
|
||||
* @param addr The 7-bit I2C address for the device
|
||||
* @param theWire The I2C bus to use, defaults to &Wire
|
||||
*/
|
||||
Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) {
|
||||
_addr = addr;
|
||||
_wire = theWire;
|
||||
_begun = false;
|
||||
#ifdef ARDUINO_ARCH_SAMD
|
||||
_maxBufferSize = 250; // as defined in Wire.h's RingBuffer
|
||||
#elif defined(ESP32)
|
||||
_maxBufferSize = I2C_BUFFER_LENGTH;
|
||||
#else
|
||||
_maxBufferSize = 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Initializes and does basic address detection
|
||||
* @param addr_detect Whether we should attempt to detect the I2C address
|
||||
* with a scan. 99% of sensors/devices don't mind, but once in a while they
|
||||
* don't respond well to a scan!
|
||||
* @return True if I2C initialized and a device with the addr found
|
||||
*/
|
||||
bool Adafruit_I2CDevice::begin(bool addr_detect) {
|
||||
_wire->begin();
|
||||
_begun = true;
|
||||
|
||||
if (addr_detect) {
|
||||
return detected();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief De-initialize device, turn off the Wire interface
|
||||
*/
|
||||
void Adafruit_I2CDevice::end(void) {
|
||||
// Not all port implement Wire::end(), such as
|
||||
// - ESP8266
|
||||
// - AVR core without WIRE_HAS_END
|
||||
// - ESP32: end() is implemented since 2.0.1 which is latest at the moment.
|
||||
// Temporarily disable for now to give time for user to update.
|
||||
#if !(defined(ESP8266) || \
|
||||
(defined(ARDUINO_ARCH_AVR) && !defined(WIRE_HAS_END)) || \
|
||||
defined(ARDUINO_ARCH_ESP32))
|
||||
_wire->end();
|
||||
_begun = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Scans I2C for the address - note will give a false-positive
|
||||
* if there's no pullups on I2C
|
||||
* @return True if I2C initialized and a device with the addr found
|
||||
*/
|
||||
bool Adafruit_I2CDevice::detected(void) {
|
||||
// Init I2C if not done yet
|
||||
if (!_begun && !begin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A basic scanner, see if it ACK's
|
||||
_wire->beginTransmission(_addr);
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("Address 0x"));
|
||||
DEBUG_SERIAL.print(_addr, HEX);
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_MBED
|
||||
_wire->write(0); // forces a write request instead of a read
|
||||
#endif
|
||||
if (_wire->endTransmission() == 0) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println(F(" Detected"));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println(F(" Not detected"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write a buffer or two to the I2C device. Cannot be more than
|
||||
* maxBufferSize() bytes.
|
||||
* @param buffer Pointer to buffer of data to write. This is const to
|
||||
* ensure the content of this buffer doesn't change.
|
||||
* @param len Number of bytes from buffer to write
|
||||
* @param prefix_buffer Pointer to optional array of data to write before
|
||||
* buffer. Cannot be more than maxBufferSize() bytes. This is const to
|
||||
* ensure the content of this buffer doesn't change.
|
||||
* @param prefix_len Number of bytes from prefix buffer to write
|
||||
* @param stop Whether to send an I2C STOP signal on write
|
||||
* @return True if write was successful, otherwise false.
|
||||
*/
|
||||
bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop,
|
||||
const uint8_t *prefix_buffer,
|
||||
size_t prefix_len) {
|
||||
if ((len + prefix_len) > maxBufferSize()) {
|
||||
// currently not guaranteed to work if more than 32 bytes!
|
||||
// we will need to find out if some platforms have larger
|
||||
// I2C buffer sizes :/
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
_wire->beginTransmission(_addr);
|
||||
|
||||
// Write the prefix data (usually an address)
|
||||
if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
|
||||
if (_wire->write(prefix_buffer, prefix_len) != prefix_len) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the data itself
|
||||
if (_wire->write(buffer, len) != len) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
|
||||
DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x"));
|
||||
DEBUG_SERIAL.print(_addr, HEX);
|
||||
DEBUG_SERIAL.print(F(" :: "));
|
||||
if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
|
||||
for (uint16_t i = 0; i < prefix_len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(prefix_buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
}
|
||||
}
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
if (i % 32 == 31) {
|
||||
DEBUG_SERIAL.println();
|
||||
}
|
||||
}
|
||||
|
||||
if (stop) {
|
||||
DEBUG_SERIAL.print("\tSTOP");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_wire->endTransmission(stop) == 0) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println();
|
||||
// DEBUG_SERIAL.println("Sent!");
|
||||
#endif
|
||||
return true;
|
||||
} else {
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.println("\tFailed to send!");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read from I2C into a buffer from the I2C device.
|
||||
* Cannot be more than maxBufferSize() bytes.
|
||||
* @param buffer Pointer to buffer of data to read into
|
||||
* @param len Number of bytes from buffer to read.
|
||||
* @param stop Whether to send an I2C STOP signal on read
|
||||
* @return True if read was successful, otherwise false.
|
||||
*/
|
||||
bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) {
|
||||
size_t pos = 0;
|
||||
while (pos < len) {
|
||||
size_t read_len =
|
||||
((len - pos) > maxBufferSize()) ? maxBufferSize() : (len - pos);
|
||||
bool read_stop = (pos < (len - read_len)) ? false : stop;
|
||||
if (!_read(buffer + pos, read_len, read_stop))
|
||||
return false;
|
||||
pos += read_len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Adafruit_I2CDevice::_read(uint8_t *buffer, size_t len, bool stop) {
|
||||
#if defined(TinyWireM_h)
|
||||
size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len);
|
||||
#elif defined(ARDUINO_ARCH_MEGAAVR)
|
||||
size_t recv = _wire->requestFrom(_addr, len, stop);
|
||||
#else
|
||||
size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop);
|
||||
#endif
|
||||
|
||||
if (recv != len) {
|
||||
// Not enough data available to fulfill our obligation!
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("\tI2CDevice did not receive enough data: "));
|
||||
DEBUG_SERIAL.println(recv);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
buffer[i] = _wire->read();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("\tI2CREAD @ 0x"));
|
||||
DEBUG_SERIAL.print(_addr, HEX);
|
||||
DEBUG_SERIAL.print(F(" :: "));
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
if (len % 32 == 31) {
|
||||
DEBUG_SERIAL.println();
|
||||
}
|
||||
}
|
||||
DEBUG_SERIAL.println();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write some data, then read some data from I2C into another buffer.
|
||||
* Cannot be more than maxBufferSize() bytes. The buffers can point to
|
||||
* same/overlapping locations.
|
||||
* @param write_buffer Pointer to buffer of data to write from
|
||||
* @param write_len Number of bytes from buffer to write.
|
||||
* @param read_buffer Pointer to buffer of data to read into.
|
||||
* @param read_len Number of bytes from buffer to read.
|
||||
* @param stop Whether to send an I2C STOP signal between the write and read
|
||||
* @return True if write & read was successful, otherwise false.
|
||||
*/
|
||||
bool Adafruit_I2CDevice::write_then_read(const uint8_t *write_buffer,
|
||||
size_t write_len, uint8_t *read_buffer,
|
||||
size_t read_len, bool stop) {
|
||||
if (!write(write_buffer, write_len, stop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return read(read_buffer, read_len);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Returns the 7-bit address of this device
|
||||
* @return The 7-bit address of this device
|
||||
*/
|
||||
uint8_t Adafruit_I2CDevice::address(void) { return _addr; }
|
||||
|
||||
/*!
|
||||
* @brief Change the I2C clock speed to desired (relies on
|
||||
* underlying Wire support!
|
||||
* @param desiredclk The desired I2C SCL frequency
|
||||
* @return True if this platform supports changing I2C speed.
|
||||
* Not necessarily that the speed was achieved!
|
||||
*/
|
||||
bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) {
|
||||
#if defined(__AVR_ATmega328__) || \
|
||||
defined(__AVR_ATmega328P__) // fix arduino core set clock
|
||||
// calculate TWBR correctly
|
||||
|
||||
if ((F_CPU / 18) < desiredclk) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
Serial.println(F("I2C.setSpeed too high."));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2;
|
||||
if (atwbr > 16320) {
|
||||
#ifdef DEBUG_SERIAL
|
||||
Serial.println(F("I2C.setSpeed too low."));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (atwbr <= 255) {
|
||||
atwbr /= 1;
|
||||
TWSR = 0x0;
|
||||
} else if (atwbr <= 1020) {
|
||||
atwbr /= 4;
|
||||
TWSR = 0x1;
|
||||
} else if (atwbr <= 4080) {
|
||||
atwbr /= 16;
|
||||
TWSR = 0x2;
|
||||
} else { // if (atwbr <= 16320)
|
||||
atwbr /= 64;
|
||||
TWSR = 0x3;
|
||||
}
|
||||
TWBR = atwbr;
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
Serial.print(F("TWSR prescaler = "));
|
||||
Serial.println(pow(4, TWSR));
|
||||
Serial.print(F("TWBR = "));
|
||||
Serial.println(atwbr);
|
||||
#endif
|
||||
return true;
|
||||
#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \
|
||||
!defined(TinyWireM_h)
|
||||
_wire->setClock(desiredclk);
|
||||
return true;
|
||||
|
||||
#else
|
||||
(void)desiredclk;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
36
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_I2CDevice.h
Normal file
36
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_I2CDevice.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef Adafruit_I2CDevice_h
|
||||
#define Adafruit_I2CDevice_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
///< The class which defines how we will talk to this device over I2C
|
||||
class Adafruit_I2CDevice {
|
||||
public:
|
||||
Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire = &Wire);
|
||||
uint8_t address(void);
|
||||
bool begin(bool addr_detect = true);
|
||||
void end(void);
|
||||
bool detected(void);
|
||||
|
||||
bool read(uint8_t *buffer, size_t len, bool stop = true);
|
||||
bool write(const uint8_t *buffer, size_t len, bool stop = true,
|
||||
const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
|
||||
bool write_then_read(const uint8_t *write_buffer, size_t write_len,
|
||||
uint8_t *read_buffer, size_t read_len,
|
||||
bool stop = false);
|
||||
bool setSpeed(uint32_t desiredclk);
|
||||
|
||||
/*! @brief How many bytes we can read in a transaction
|
||||
* @return The size of the Wire receive/transmit buffer */
|
||||
size_t maxBufferSize() { return _maxBufferSize; }
|
||||
|
||||
private:
|
||||
uint8_t _addr;
|
||||
TwoWire *_wire;
|
||||
bool _begun;
|
||||
size_t _maxBufferSize;
|
||||
bool _read(uint8_t *buffer, size_t len, bool stop);
|
||||
};
|
||||
|
||||
#endif // Adafruit_I2CDevice_h
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _ADAFRUIT_I2C_REGISTER_H_
|
||||
#define _ADAFRUIT_I2C_REGISTER_H_
|
||||
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
typedef Adafruit_BusIO_Register Adafruit_I2CRegister;
|
||||
typedef Adafruit_BusIO_RegisterBits Adafruit_I2CRegisterBits;
|
||||
|
||||
#endif
|
||||
512
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_SPIDevice.cpp
Normal file
512
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_SPIDevice.cpp
Normal file
@@ -0,0 +1,512 @@
|
||||
#include "Adafruit_SPIDevice.h"
|
||||
|
||||
// #define DEBUG_SERIAL Serial
|
||||
|
||||
#ifdef BUSIO_USE_FAST_PINIO
|
||||
#define BUSIO_SET_CLOCK_LOW() (*clkPort = *clkPort & ~clkPinMask)
|
||||
#define BUSIO_SET_CLOCK_HIGH() (*clkPort = *clkPort | clkPinMask)
|
||||
#define BUSIO_READ_MISO() (*misoPort & misoPinMask)
|
||||
#define BUSIO_WRITE_MOSI(value) \
|
||||
do { \
|
||||
if (value) \
|
||||
*mosiPort = *mosiPort | mosiPinMask; \
|
||||
else \
|
||||
*mosiPort = *mosiPort & ~mosiPinMask; \
|
||||
} while (0)
|
||||
#else
|
||||
#define BUSIO_SET_CLOCK_LOW() digitalWrite(_sck, LOW)
|
||||
#define BUSIO_SET_CLOCK_HIGH() digitalWrite(_sck, HIGH)
|
||||
#define BUSIO_READ_MISO() digitalRead(_miso)
|
||||
#define BUSIO_WRITE_MOSI(value) digitalWrite(_mosi, value)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Create an SPI device with the given CS pin and settings
|
||||
* @param cspin The arduino pin number to use for chip select
|
||||
* @param freq The SPI clock frequency to use, defaults to 1MHz
|
||||
* @param dataOrder The SPI data order to use for bits within each byte,
|
||||
* defaults to SPI_BITORDER_MSBFIRST
|
||||
* @param dataMode The SPI mode to use, defaults to SPI_MODE0
|
||||
* @param theSPI The SPI bus to use, defaults to &theSPI
|
||||
*/
|
||||
Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq,
|
||||
BusIOBitOrder dataOrder,
|
||||
uint8_t dataMode, SPIClass *theSPI) {
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
_cs = cspin;
|
||||
_sck = _mosi = _miso = -1;
|
||||
_spi = theSPI;
|
||||
_begun = false;
|
||||
_spiSetting = new SPISettings(freq, dataOrder, dataMode);
|
||||
_freq = freq;
|
||||
_dataOrder = dataOrder;
|
||||
_dataMode = dataMode;
|
||||
#else
|
||||
// unused, but needed to suppress compiler warns
|
||||
(void)cspin;
|
||||
(void)freq;
|
||||
(void)dataOrder;
|
||||
(void)dataMode;
|
||||
(void)theSPI;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create an SPI device with the given CS pin and settings
|
||||
* @param cspin The arduino pin number to use for chip select
|
||||
* @param sckpin The arduino pin number to use for SCK
|
||||
* @param misopin The arduino pin number to use for MISO, set to -1 if not
|
||||
* used
|
||||
* @param mosipin The arduino pin number to use for MOSI, set to -1 if not
|
||||
* used
|
||||
* @param freq The SPI clock frequency to use, defaults to 1MHz
|
||||
* @param dataOrder The SPI data order to use for bits within each byte,
|
||||
* defaults to SPI_BITORDER_MSBFIRST
|
||||
* @param dataMode The SPI mode to use, defaults to SPI_MODE0
|
||||
*/
|
||||
Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin,
|
||||
int8_t misopin, int8_t mosipin,
|
||||
uint32_t freq, BusIOBitOrder dataOrder,
|
||||
uint8_t dataMode) {
|
||||
_cs = cspin;
|
||||
_sck = sckpin;
|
||||
_miso = misopin;
|
||||
_mosi = mosipin;
|
||||
|
||||
#ifdef BUSIO_USE_FAST_PINIO
|
||||
csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin));
|
||||
csPinMask = digitalPinToBitMask(cspin);
|
||||
if (mosipin != -1) {
|
||||
mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin));
|
||||
mosiPinMask = digitalPinToBitMask(mosipin);
|
||||
}
|
||||
if (misopin != -1) {
|
||||
misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin));
|
||||
misoPinMask = digitalPinToBitMask(misopin);
|
||||
}
|
||||
clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin));
|
||||
clkPinMask = digitalPinToBitMask(sckpin);
|
||||
#endif
|
||||
|
||||
_freq = freq;
|
||||
_dataOrder = dataOrder;
|
||||
_dataMode = dataMode;
|
||||
_begun = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Release memory allocated in constructors
|
||||
*/
|
||||
Adafruit_SPIDevice::~Adafruit_SPIDevice() {
|
||||
if (_spiSetting)
|
||||
delete _spiSetting;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Initializes SPI bus and sets CS pin high
|
||||
* @return Always returns true because there's no way to test success of SPI
|
||||
* init
|
||||
*/
|
||||
bool Adafruit_SPIDevice::begin(void) {
|
||||
if (_cs != -1) {
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH);
|
||||
}
|
||||
|
||||
if (_spi) { // hardware SPI
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
_spi->begin();
|
||||
#endif
|
||||
} else {
|
||||
pinMode(_sck, OUTPUT);
|
||||
|
||||
if ((_dataMode == SPI_MODE0) || (_dataMode == SPI_MODE1)) {
|
||||
// idle low on mode 0 and 1
|
||||
digitalWrite(_sck, LOW);
|
||||
} else {
|
||||
// idle high on mode 2 or 3
|
||||
digitalWrite(_sck, HIGH);
|
||||
}
|
||||
if (_mosi != -1) {
|
||||
pinMode(_mosi, OUTPUT);
|
||||
digitalWrite(_mosi, HIGH);
|
||||
}
|
||||
if (_miso != -1) {
|
||||
pinMode(_miso, INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
_begun = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Transfer (send/receive) a buffer over hard/soft SPI, without
|
||||
* transaction management
|
||||
* @param buffer The buffer to send and receive at the same time
|
||||
* @param len The number of bytes to transfer
|
||||
*/
|
||||
void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
|
||||
//
|
||||
// HARDWARE SPI
|
||||
//
|
||||
if (_spi) {
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
#if defined(SPARK)
|
||||
_spi->transfer(buffer, buffer, len, nullptr);
|
||||
#elif defined(STM32)
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
_spi->transfer(buffer[i]);
|
||||
}
|
||||
#else
|
||||
_spi->transfer(buffer, len);
|
||||
#endif
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// SOFTWARE SPI
|
||||
//
|
||||
uint8_t startbit;
|
||||
if (_dataOrder == SPI_BITORDER_LSBFIRST) {
|
||||
startbit = 0x1;
|
||||
} else {
|
||||
startbit = 0x80;
|
||||
}
|
||||
|
||||
bool towrite, lastmosi = !(buffer[0] & startbit);
|
||||
uint8_t bitdelay_us = (1000000 / _freq) / 2;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint8_t reply = 0;
|
||||
uint8_t send = buffer[i];
|
||||
|
||||
/*
|
||||
Serial.print("\tSending software SPI byte 0x");
|
||||
Serial.print(send, HEX);
|
||||
Serial.print(" -> 0x");
|
||||
*/
|
||||
|
||||
// Serial.print(send, HEX);
|
||||
for (uint8_t b = startbit; b != 0;
|
||||
b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1) {
|
||||
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) {
|
||||
towrite = send & b;
|
||||
if ((_mosi != -1) && (lastmosi != towrite)) {
|
||||
BUSIO_WRITE_MOSI(towrite);
|
||||
lastmosi = towrite;
|
||||
}
|
||||
|
||||
BUSIO_SET_CLOCK_HIGH();
|
||||
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
if (_miso != -1) {
|
||||
if (BUSIO_READ_MISO())
|
||||
reply |= b;
|
||||
}
|
||||
|
||||
BUSIO_SET_CLOCK_LOW();
|
||||
|
||||
} else if (_dataMode == SPI_MODE3) {
|
||||
|
||||
if (_mosi != -1) { // transmit on falling edge
|
||||
BUSIO_WRITE_MOSI(send & b);
|
||||
}
|
||||
|
||||
BUSIO_SET_CLOCK_LOW();
|
||||
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
BUSIO_SET_CLOCK_HIGH();
|
||||
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
if (_miso != -1) { // read on rising edge
|
||||
if (BUSIO_READ_MISO()) {
|
||||
reply |= b;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // || _dataMode == SPI_MODE1)
|
||||
|
||||
BUSIO_SET_CLOCK_HIGH();
|
||||
|
||||
if (bitdelay_us) {
|
||||
delayMicroseconds(bitdelay_us);
|
||||
}
|
||||
|
||||
if (_mosi != -1) {
|
||||
BUSIO_WRITE_MOSI(send & b);
|
||||
}
|
||||
|
||||
BUSIO_SET_CLOCK_LOW();
|
||||
|
||||
if (_miso != -1) {
|
||||
if (BUSIO_READ_MISO()) {
|
||||
reply |= b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_miso != -1) {
|
||||
buffer[i] = reply;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Transfer (send/receive) one byte over hard/soft SPI, without
|
||||
* transaction management
|
||||
* @param send The byte to send
|
||||
* @return The byte received while transmitting
|
||||
*/
|
||||
uint8_t Adafruit_SPIDevice::transfer(uint8_t send) {
|
||||
uint8_t data = send;
|
||||
transfer(&data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Manually begin a transaction (calls beginTransaction if hardware
|
||||
* SPI)
|
||||
*/
|
||||
void Adafruit_SPIDevice::beginTransaction(void) {
|
||||
if (_spi) {
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
_spi->beginTransaction(*_spiSetting);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Manually end a transaction (calls endTransaction if hardware SPI)
|
||||
*/
|
||||
void Adafruit_SPIDevice::endTransaction(void) {
|
||||
if (_spi) {
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
_spi->endTransaction();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Assert/Deassert the CS pin if it is defined
|
||||
* @param value The state the CS is set to
|
||||
*/
|
||||
void Adafruit_SPIDevice::setChipSelect(int value) {
|
||||
if (_cs != -1) {
|
||||
digitalWrite(_cs, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write a buffer or two to the SPI device, with transaction
|
||||
* management.
|
||||
* @brief Manually begin a transaction (calls beginTransaction if hardware
|
||||
* SPI) with asserting the CS pin
|
||||
*/
|
||||
void Adafruit_SPIDevice::beginTransactionWithAssertingCS() {
|
||||
beginTransaction();
|
||||
setChipSelect(LOW);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Manually end a transaction (calls endTransaction if hardware SPI)
|
||||
* with deasserting the CS pin
|
||||
*/
|
||||
void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
|
||||
setChipSelect(HIGH);
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write a buffer or two to the SPI device, with transaction
|
||||
* management.
|
||||
* @param buffer Pointer to buffer of data to write
|
||||
* @param len Number of bytes from buffer to write
|
||||
* @param prefix_buffer Pointer to optional array of data to write before
|
||||
* buffer.
|
||||
* @param prefix_len Number of bytes from prefix buffer to write
|
||||
* @return Always returns true because there's no way to test success of SPI
|
||||
* writes
|
||||
*/
|
||||
bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len,
|
||||
const uint8_t *prefix_buffer,
|
||||
size_t prefix_len) {
|
||||
beginTransactionWithAssertingCS();
|
||||
|
||||
// do the writing
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
if (_spi) {
|
||||
if (prefix_len > 0) {
|
||||
_spi->transferBytes((uint8_t *)prefix_buffer, nullptr, prefix_len);
|
||||
}
|
||||
if (len > 0) {
|
||||
_spi->transferBytes((uint8_t *)buffer, nullptr, len);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
for (size_t i = 0; i < prefix_len; i++) {
|
||||
transfer(prefix_buffer[i]);
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
transfer(buffer[i]);
|
||||
}
|
||||
}
|
||||
endTransactionWithDeassertingCS();
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
|
||||
if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
|
||||
for (uint16_t i = 0; i < prefix_len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(prefix_buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
}
|
||||
}
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
if (i % 32 == 31) {
|
||||
DEBUG_SERIAL.println();
|
||||
}
|
||||
}
|
||||
DEBUG_SERIAL.println();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read from SPI into a buffer from the SPI device, with transaction
|
||||
* management.
|
||||
* @param buffer Pointer to buffer of data to read into
|
||||
* @param len Number of bytes from buffer to read.
|
||||
* @param sendvalue The 8-bits of data to write when doing the data read,
|
||||
* defaults to 0xFF
|
||||
* @return Always returns true because there's no way to test success of SPI
|
||||
* writes
|
||||
*/
|
||||
bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
|
||||
memset(buffer, sendvalue, len); // clear out existing buffer
|
||||
|
||||
beginTransactionWithAssertingCS();
|
||||
transfer(buffer, len);
|
||||
endTransactionWithDeassertingCS();
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
if (len % 32 == 31) {
|
||||
DEBUG_SERIAL.println();
|
||||
}
|
||||
}
|
||||
DEBUG_SERIAL.println();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write some data, then read some data from SPI into another buffer,
|
||||
* with transaction management. The buffers can point to same/overlapping
|
||||
* locations. This does not transmit-receive at the same time!
|
||||
* @param write_buffer Pointer to buffer of data to write from
|
||||
* @param write_len Number of bytes from buffer to write.
|
||||
* @param read_buffer Pointer to buffer of data to read into.
|
||||
* @param read_len Number of bytes from buffer to read.
|
||||
* @param sendvalue The 8-bits of data to write when doing the data read,
|
||||
* defaults to 0xFF
|
||||
* @return Always returns true because there's no way to test success of SPI
|
||||
* writes
|
||||
*/
|
||||
bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer,
|
||||
size_t write_len, uint8_t *read_buffer,
|
||||
size_t read_len, uint8_t sendvalue) {
|
||||
beginTransactionWithAssertingCS();
|
||||
// do the writing
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
if (_spi) {
|
||||
if (write_len > 0) {
|
||||
_spi->transferBytes((uint8_t *)write_buffer, nullptr, write_len);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
for (size_t i = 0; i < write_len; i++) {
|
||||
transfer(write_buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
|
||||
for (uint16_t i = 0; i < write_len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(write_buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
if (write_len % 32 == 31) {
|
||||
DEBUG_SERIAL.println();
|
||||
}
|
||||
}
|
||||
DEBUG_SERIAL.println();
|
||||
#endif
|
||||
|
||||
// do the reading
|
||||
for (size_t i = 0; i < read_len; i++) {
|
||||
read_buffer[i] = transfer(sendvalue);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
|
||||
for (uint16_t i = 0; i < read_len; i++) {
|
||||
DEBUG_SERIAL.print(F("0x"));
|
||||
DEBUG_SERIAL.print(read_buffer[i], HEX);
|
||||
DEBUG_SERIAL.print(F(", "));
|
||||
if (read_len % 32 == 31) {
|
||||
DEBUG_SERIAL.println();
|
||||
}
|
||||
}
|
||||
DEBUG_SERIAL.println();
|
||||
#endif
|
||||
|
||||
endTransactionWithDeassertingCS();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Write some data and read some data at the same time from SPI
|
||||
* into the same buffer, with transaction management. This is basicaly a wrapper
|
||||
* for transfer() with CS-pin and transaction management. This /does/
|
||||
* transmit-receive at the same time!
|
||||
* @param buffer Pointer to buffer of data to write/read to/from
|
||||
* @param len Number of bytes from buffer to write/read.
|
||||
* @return Always returns true because there's no way to test success of SPI
|
||||
* writes
|
||||
*/
|
||||
bool Adafruit_SPIDevice::write_and_read(uint8_t *buffer, size_t len) {
|
||||
beginTransactionWithAssertingCS();
|
||||
transfer(buffer, len);
|
||||
endTransactionWithDeassertingCS();
|
||||
|
||||
return true;
|
||||
}
|
||||
149
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_SPIDevice.h
Normal file
149
firmware_adxl345_spi/lib/Adafruit BusIO/Adafruit_SPIDevice.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#ifndef Adafruit_SPIDevice_h
|
||||
#define Adafruit_SPIDevice_h
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if !defined(SPI_INTERFACES_COUNT) || \
|
||||
(defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
|
||||
// HW SPI available
|
||||
#include <SPI.h>
|
||||
#define BUSIO_HAS_HW_SPI
|
||||
#else
|
||||
// SW SPI ONLY
|
||||
enum { SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3 };
|
||||
typedef uint8_t SPIClass;
|
||||
#endif
|
||||
|
||||
// some modern SPI definitions don't have BitOrder enum
|
||||
#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \
|
||||
defined(ESP8266) || defined(TEENSYDUINO) || defined(SPARK) || \
|
||||
defined(ARDUINO_ARCH_SPRESENSE) || defined(MEGATINYCORE) || \
|
||||
defined(DXCORE) || defined(ARDUINO_AVR_ATmega4809) || \
|
||||
defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \
|
||||
defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \
|
||||
defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \
|
||||
defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32) || \
|
||||
defined(ARDUINO_ARCH_XMC)
|
||||
|
||||
typedef enum _BitOrder {
|
||||
SPI_BITORDER_MSBFIRST = MSBFIRST,
|
||||
SPI_BITORDER_LSBFIRST = LSBFIRST,
|
||||
} BusIOBitOrder;
|
||||
|
||||
#elif defined(ESP32) || defined(__ASR6501__) || defined(__ASR6502__)
|
||||
|
||||
// some modern SPI definitions don't have BitOrder enum and have different SPI
|
||||
// mode defines
|
||||
typedef enum _BitOrder {
|
||||
SPI_BITORDER_MSBFIRST = SPI_MSBFIRST,
|
||||
SPI_BITORDER_LSBFIRST = SPI_LSBFIRST,
|
||||
} BusIOBitOrder;
|
||||
|
||||
#else
|
||||
// Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST
|
||||
#define SPI_BITORDER_MSBFIRST MSBFIRST
|
||||
#define SPI_BITORDER_LSBFIRST LSBFIRST
|
||||
typedef BitOrder BusIOBitOrder;
|
||||
#endif
|
||||
|
||||
#if defined(__IMXRT1062__) // Teensy 4.x
|
||||
// *Warning* I disabled the usage of FAST_PINIO as the set/clear operations
|
||||
// used in the cpp file are not atomic and can effect multiple IO pins
|
||||
// and if an interrupt happens in between the time the code reads the register
|
||||
// and writes out the updated value, that changes one or more other IO pins
|
||||
// on that same IO port, those change will be clobbered when the updated
|
||||
// values are written back. A fast version can be implemented that uses the
|
||||
// ports set and clear registers which are atomic.
|
||||
// typedef volatile uint32_t BusIO_PortReg;
|
||||
// typedef uint32_t BusIO_PortMask;
|
||||
// #define BUSIO_USE_FAST_PINIO
|
||||
|
||||
#elif defined(__MBED__) || defined(__ZEPHYR__)
|
||||
// Boards based on RTOS cores like mbed or Zephyr are not going to expose the
|
||||
// low level registers needed for fast pin manipulation
|
||||
#undef BUSIO_USE_FAST_PINIO
|
||||
|
||||
#elif defined(ARDUINO_ARCH_XMC)
|
||||
#undef BUSIO_USE_FAST_PINIO
|
||||
|
||||
#elif defined(__AVR__) || defined(TEENSYDUINO)
|
||||
typedef volatile uint8_t BusIO_PortReg;
|
||||
typedef uint8_t BusIO_PortMask;
|
||||
#define BUSIO_USE_FAST_PINIO
|
||||
|
||||
#elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \
|
||||
defined(ARDUINO_ARCH_SAMD)
|
||||
typedef volatile uint32_t BusIO_PortReg;
|
||||
typedef uint32_t BusIO_PortMask;
|
||||
#define BUSIO_USE_FAST_PINIO
|
||||
|
||||
#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \
|
||||
!defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_SILABS) && \
|
||||
!defined(ARDUINO_UNOR4_MINIMA) && !defined(ARDUINO_UNOR4_WIFI) && \
|
||||
!defined(PORTDUINO)
|
||||
typedef volatile uint32_t BusIO_PortReg;
|
||||
typedef uint32_t BusIO_PortMask;
|
||||
#if !defined(__ASR6501__) && !defined(__ASR6502__)
|
||||
#define BUSIO_USE_FAST_PINIO
|
||||
#endif
|
||||
|
||||
#else
|
||||
#undef BUSIO_USE_FAST_PINIO
|
||||
#endif
|
||||
|
||||
/**! The class which defines how we will talk to this device over SPI **/
|
||||
class Adafruit_SPIDevice {
|
||||
public:
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
|
||||
BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
|
||||
uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = &SPI);
|
||||
#else
|
||||
Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
|
||||
BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
|
||||
uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = nullptr);
|
||||
#endif
|
||||
Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi,
|
||||
uint32_t freq = 1000000,
|
||||
BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
|
||||
uint8_t dataMode = SPI_MODE0);
|
||||
~Adafruit_SPIDevice();
|
||||
|
||||
bool begin(void);
|
||||
bool read(uint8_t *buffer, size_t len, uint8_t sendvalue = 0xFF);
|
||||
bool write(const uint8_t *buffer, size_t len,
|
||||
const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
|
||||
bool write_then_read(const uint8_t *write_buffer, size_t write_len,
|
||||
uint8_t *read_buffer, size_t read_len,
|
||||
uint8_t sendvalue = 0xFF);
|
||||
bool write_and_read(uint8_t *buffer, size_t len);
|
||||
|
||||
uint8_t transfer(uint8_t send);
|
||||
void transfer(uint8_t *buffer, size_t len);
|
||||
void beginTransaction(void);
|
||||
void endTransaction(void);
|
||||
void beginTransactionWithAssertingCS();
|
||||
void endTransactionWithDeassertingCS();
|
||||
|
||||
private:
|
||||
#ifdef BUSIO_HAS_HW_SPI
|
||||
SPIClass *_spi = nullptr;
|
||||
SPISettings *_spiSetting = nullptr;
|
||||
#else
|
||||
uint8_t *_spi = nullptr;
|
||||
uint8_t *_spiSetting = nullptr;
|
||||
#endif
|
||||
uint32_t _freq;
|
||||
BusIOBitOrder _dataOrder;
|
||||
uint8_t _dataMode;
|
||||
void setChipSelect(int value);
|
||||
|
||||
int8_t _cs, _sck, _mosi, _miso;
|
||||
#ifdef BUSIO_USE_FAST_PINIO
|
||||
BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort;
|
||||
BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask;
|
||||
#endif
|
||||
bool _begun;
|
||||
};
|
||||
|
||||
#endif // Adafruit_SPIDevice_h
|
||||
11
firmware_adxl345_spi/lib/Adafruit BusIO/CMakeLists.txt
Normal file
11
firmware_adxl345_spi/lib/Adafruit BusIO/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
# Adafruit Bus IO Library
|
||||
# https://github.com/adafruit/Adafruit_BusIO
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
idf_component_register(SRCS "Adafruit_I2CDevice.cpp" "Adafruit_BusIO_Register.cpp" "Adafruit_SPIDevice.cpp" "Adafruit_GenericDevice.cpp"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES arduino-esp32)
|
||||
|
||||
project(Adafruit_BusIO)
|
||||
21
firmware_adxl345_spi/lib/Adafruit BusIO/LICENSE
Normal file
21
firmware_adxl345_spi/lib/Adafruit BusIO/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Adafruit Industries
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
8
firmware_adxl345_spi/lib/Adafruit BusIO/README.md
Normal file
8
firmware_adxl345_spi/lib/Adafruit BusIO/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Adafruit Bus IO Library [](https://github.com/adafruit/Adafruit_BusIO/actions)
|
||||
|
||||
|
||||
This is a helper library to abstract away I2C, SPI, and 'generic transport' (e.g. UART) transactions and registers
|
||||
|
||||
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
|
||||
|
||||
MIT license, all text above must be included in any redistribution
|
||||
1
firmware_adxl345_spi/lib/Adafruit BusIO/component.mk
Normal file
1
firmware_adxl345_spi/lib/Adafruit BusIO/component.mk
Normal file
@@ -0,0 +1 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS = .
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
Advanced example of using bstracted transport for reading and writing
|
||||
register data from a UART-based device such as a TMC2209
|
||||
|
||||
Written with help by Claude!
|
||||
https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time
|
||||
chats are not shareable :(
|
||||
*/
|
||||
|
||||
#include "Adafruit_BusIO_Register.h"
|
||||
#include "Adafruit_GenericDevice.h"
|
||||
|
||||
// Debugging macros
|
||||
#define DEBUG_SERIAL Serial
|
||||
|
||||
#ifdef DEBUG_SERIAL
|
||||
#define DEBUG_PRINT(x) DEBUG_SERIAL.print(x)
|
||||
#define DEBUG_PRINTLN(x) DEBUG_SERIAL.println(x)
|
||||
#define DEBUG_PRINT_HEX(x) \
|
||||
do { \
|
||||
if (x < 0x10) \
|
||||
DEBUG_SERIAL.print('0'); \
|
||||
DEBUG_SERIAL.print(x, HEX); \
|
||||
DEBUG_SERIAL.print(' '); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#define DEBUG_PRINT_HEX(x)
|
||||
#endif
|
||||
|
||||
#define TMC2209_IOIN 0x06
|
||||
|
||||
class TMC2209_UART {
|
||||
private:
|
||||
Stream *_uart_stream;
|
||||
uint8_t _addr;
|
||||
|
||||
static bool uart_read(void *thiz, uint8_t *buffer, size_t len) {
|
||||
TMC2209_UART *dev = (TMC2209_UART *)thiz;
|
||||
uint16_t timeout = 100;
|
||||
while (dev->_uart_stream->available() < len && timeout--) {
|
||||
delay(1);
|
||||
}
|
||||
if (timeout == 0) {
|
||||
DEBUG_PRINTLN("Read timeout!");
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_PRINT("Reading: ");
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
buffer[i] = dev->_uart_stream->read();
|
||||
DEBUG_PRINT_HEX(buffer[i]);
|
||||
}
|
||||
DEBUG_PRINTLN("");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) {
|
||||
TMC2209_UART *dev = (TMC2209_UART *)thiz;
|
||||
DEBUG_PRINT("Writing: ");
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
DEBUG_PRINT_HEX(buffer[i]);
|
||||
}
|
||||
DEBUG_PRINTLN("");
|
||||
|
||||
dev->_uart_stream->write(buffer, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool uart_readreg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz,
|
||||
uint8_t *data, uint16_t datalen) {
|
||||
TMC2209_UART *dev = (TMC2209_UART *)thiz;
|
||||
while (dev->_uart_stream->available())
|
||||
dev->_uart_stream->read();
|
||||
|
||||
uint8_t packet[4] = {0x05, uint8_t(dev->_addr << 1), addr_buf[0], 0x00};
|
||||
|
||||
packet[3] = calcCRC(packet, 3);
|
||||
if (!uart_write(thiz, packet, 4))
|
||||
return false;
|
||||
|
||||
// Read back echo
|
||||
uint8_t echo[4];
|
||||
if (!uart_read(thiz, echo, 4))
|
||||
return false;
|
||||
|
||||
// Verify echo
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if (echo[i] != packet[i]) {
|
||||
DEBUG_PRINTLN("Echo mismatch");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t response[8]; // sync + 0xFF + reg + 4 data bytes + CRC
|
||||
if (!uart_read(thiz, response, 8))
|
||||
return false;
|
||||
|
||||
// Verify response
|
||||
if (response[0] != 0x05) {
|
||||
DEBUG_PRINTLN("Invalid sync byte");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response[1] != 0xFF) {
|
||||
DEBUG_PRINTLN("Invalid reply address");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response[2] != addr_buf[0]) {
|
||||
DEBUG_PRINTLN("Register mismatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t crc = calcCRC(response, 7);
|
||||
if (crc != response[7]) {
|
||||
DEBUG_PRINTLN("CRC mismatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(data, &response[3], 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool uart_writereg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz,
|
||||
const uint8_t *data, uint16_t datalen) {
|
||||
TMC2209_UART *dev = (TMC2209_UART *)thiz;
|
||||
while (dev->_uart_stream->available())
|
||||
dev->_uart_stream->read();
|
||||
|
||||
uint8_t packet[8] = {0x05,
|
||||
uint8_t(dev->_addr << 1),
|
||||
uint8_t(addr_buf[0] | 0x80),
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
data[3],
|
||||
0x00};
|
||||
|
||||
packet[7] = calcCRC(packet, 7);
|
||||
if (!uart_write(thiz, packet, 8))
|
||||
return false;
|
||||
|
||||
uint8_t echo[8];
|
||||
if (!uart_read(thiz, echo, 8))
|
||||
return false;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (echo[i] != packet[i]) {
|
||||
DEBUG_PRINTLN("Write echo mismatch");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t calcCRC(uint8_t *data, uint8_t length) {
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
uint8_t currentByte = data[i];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
if ((crc >> 7) ^ (currentByte & 0x01)) {
|
||||
crc = (crc << 1) ^ 0x07;
|
||||
} else {
|
||||
crc = crc << 1;
|
||||
}
|
||||
currentByte = currentByte >> 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
public:
|
||||
TMC2209_UART(Stream *serial, uint8_t addr)
|
||||
: _uart_stream(serial), _addr(addr) {}
|
||||
|
||||
Adafruit_GenericDevice *createDevice() {
|
||||
return new Adafruit_GenericDevice(this, uart_read, uart_write, uart_readreg,
|
||||
uart_writereg);
|
||||
}
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
;
|
||||
delay(100);
|
||||
Serial.println("TMC2209 Generic Device register read/write test!");
|
||||
|
||||
Serial1.begin(115200);
|
||||
|
||||
TMC2209_UART uart(&Serial1, 0);
|
||||
Adafruit_GenericDevice *device = uart.createDevice();
|
||||
device->begin();
|
||||
|
||||
// Create register object for IOIN
|
||||
Adafruit_BusIO_Register ioin_reg(device,
|
||||
TMC2209_IOIN, // device and register address
|
||||
4, // width = 4 bytes
|
||||
MSBFIRST, // byte order
|
||||
1); // address width = 1 byte
|
||||
Serial.print("IOIN = 0x");
|
||||
Serial.println(ioin_reg.read(), HEX);
|
||||
|
||||
// Create RegisterBits for VERSION field (bits 31:24)
|
||||
Adafruit_BusIO_RegisterBits version_bits(
|
||||
&ioin_reg, 8, 24); // 8 bits wide, starting at bit 24
|
||||
|
||||
Serial.println("Reading VERSION...");
|
||||
uint8_t version = version_bits.read();
|
||||
|
||||
Serial.print("VERSION = 0x");
|
||||
Serial.println(version, HEX);
|
||||
}
|
||||
|
||||
void loop() { delay(1000); }
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Abstracted transport for reading and writing data from a UART-based
|
||||
device such as a TMC2209
|
||||
|
||||
Written with help by Claude!
|
||||
https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time
|
||||
chats are not shareable :(
|
||||
*/
|
||||
|
||||
#include "Adafruit_GenericDevice.h"
|
||||
|
||||
/**
|
||||
* Basic UART device class that demonstrates using GenericDevice with a Stream
|
||||
* interface. This example shows how to wrap a Stream (like HardwareSerial or
|
||||
* SoftwareSerial) with read/write callbacks that can be used by BusIO's
|
||||
* register functions.
|
||||
*/
|
||||
class UARTDevice {
|
||||
public:
|
||||
UARTDevice(Stream *serial) : _serial(serial) {}
|
||||
|
||||
// Static callback for writing data to UART
|
||||
// Called by GenericDevice when data needs to be sent
|
||||
static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) {
|
||||
UARTDevice *dev = (UARTDevice *)thiz;
|
||||
dev->_serial->write(buffer, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Static callback for reading data from UART
|
||||
// Includes timeout and will return false if not enough data available
|
||||
static bool uart_read(void *thiz, uint8_t *buffer, size_t len) {
|
||||
UARTDevice *dev = (UARTDevice *)thiz;
|
||||
uint16_t timeout = 100;
|
||||
while (dev->_serial->available() < len && timeout--) {
|
||||
delay(1);
|
||||
}
|
||||
if (timeout == 0) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
buffer[i] = dev->_serial->read();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create a GenericDevice instance using our callbacks
|
||||
Adafruit_GenericDevice *createDevice() {
|
||||
return new Adafruit_GenericDevice(this, uart_read, uart_write);
|
||||
}
|
||||
|
||||
private:
|
||||
Stream *_serial; // Underlying Stream instance (HardwareSerial, etc)
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
;
|
||||
delay(100);
|
||||
|
||||
Serial.println("Generic Device test!");
|
||||
|
||||
// Initialize UART for device communication
|
||||
Serial1.begin(115200);
|
||||
|
||||
// Create UART wrapper and BusIO device
|
||||
UARTDevice uart(&Serial1);
|
||||
Adafruit_GenericDevice *device = uart.createDevice();
|
||||
device->begin();
|
||||
|
||||
// Test write/read cycle
|
||||
uint8_t write_buf[4] = {0x5, 0x0, 0x0, 0x48};
|
||||
uint8_t read_buf[8];
|
||||
|
||||
Serial.println("Writing data...");
|
||||
if (!device->write(write_buf, 4)) {
|
||||
Serial.println("Write failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("Reading response...");
|
||||
if (!device->read(read_buf, 8)) {
|
||||
Serial.println("Read failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Print response bytes
|
||||
Serial.print("Got response: ");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(read_buf[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() { delay(1000); }
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <Adafruit_I2CDevice.h>
|
||||
|
||||
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(0x10);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("I2C address detection test");
|
||||
|
||||
if (!i2c_dev.begin()) {
|
||||
Serial.print("Did not find device at 0x");
|
||||
Serial.println(i2c_dev.address(), HEX);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
Serial.print("Device found on address 0x");
|
||||
Serial.println(i2c_dev.address(), HEX);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include <Adafruit_I2CDevice.h>
|
||||
|
||||
#define I2C_ADDRESS 0x60
|
||||
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("I2C device read and write test");
|
||||
|
||||
if (!i2c_dev.begin()) {
|
||||
Serial.print("Did not find device at 0x");
|
||||
Serial.println(i2c_dev.address(), HEX);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
Serial.print("Device found on address 0x");
|
||||
Serial.println(i2c_dev.address(), HEX);
|
||||
|
||||
uint8_t buffer[32];
|
||||
// Try to read 32 bytes
|
||||
i2c_dev.read(buffer, 32);
|
||||
Serial.print("Read: ");
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(buffer[i], HEX);
|
||||
Serial.print(", ");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// read a register by writing first, then reading
|
||||
buffer[0] = 0x0C; // we'll reuse the same buffer
|
||||
i2c_dev.write_then_read(buffer, 1, buffer, 2, false);
|
||||
Serial.print("Write then Read: ");
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(buffer[i], HEX);
|
||||
Serial.print(", ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
#include <Adafruit_I2CDevice.h>
|
||||
|
||||
#define I2C_ADDRESS 0x60
|
||||
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("I2C device register test");
|
||||
|
||||
if (!i2c_dev.begin()) {
|
||||
Serial.print("Did not find device at 0x");
|
||||
Serial.println(i2c_dev.address(), HEX);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
Serial.print("Device found on address 0x");
|
||||
Serial.println(i2c_dev.address(), HEX);
|
||||
|
||||
Adafruit_BusIO_Register id_reg =
|
||||
Adafruit_BusIO_Register(&i2c_dev, 0x0C, 2, LSBFIRST);
|
||||
uint16_t id;
|
||||
id_reg.read(&id);
|
||||
Serial.print("ID register = 0x");
|
||||
Serial.println(id, HEX);
|
||||
|
||||
Adafruit_BusIO_Register thresh_reg =
|
||||
Adafruit_BusIO_Register(&i2c_dev, 0x01, 2, LSBFIRST);
|
||||
uint16_t thresh;
|
||||
thresh_reg.read(&thresh);
|
||||
Serial.print("Initial threshold register = 0x");
|
||||
Serial.println(thresh, HEX);
|
||||
|
||||
thresh_reg.write(~thresh);
|
||||
|
||||
Serial.print("Post threshold register = 0x");
|
||||
Serial.println(thresh_reg.read(), HEX);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
|
||||
// Define which interface to use by setting the unused interface to NULL!
|
||||
|
||||
#define SPIDEVICE_CS 10
|
||||
Adafruit_SPIDevice *spi_dev = NULL; // new Adafruit_SPIDevice(SPIDEVICE_CS);
|
||||
|
||||
#define I2C_ADDRESS 0x5D
|
||||
Adafruit_I2CDevice *i2c_dev = new Adafruit_I2CDevice(I2C_ADDRESS);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("I2C or SPI device register test");
|
||||
|
||||
if (spi_dev && !spi_dev->begin()) {
|
||||
Serial.println("Could not initialize SPI device");
|
||||
}
|
||||
|
||||
if (i2c_dev) {
|
||||
if (i2c_dev->begin()) {
|
||||
Serial.print("Device found on I2C address 0x");
|
||||
Serial.println(i2c_dev->address(), HEX);
|
||||
} else {
|
||||
Serial.print("Did not find I2C device at 0x");
|
||||
Serial.println(i2c_dev->address(), HEX);
|
||||
}
|
||||
}
|
||||
|
||||
Adafruit_BusIO_Register id_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F);
|
||||
uint8_t id = 0;
|
||||
id_reg.read(&id);
|
||||
Serial.print("ID register = 0x");
|
||||
Serial.println(id, HEX);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <Adafruit_SPIDevice.h>
|
||||
|
||||
#define SPIDEVICE_CS 10
|
||||
Adafruit_SPIDevice spi_dev =
|
||||
Adafruit_SPIDevice(SPIDEVICE_CS, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
|
||||
// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 13, 12, 11,
|
||||
// 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("SPI device mode test");
|
||||
|
||||
if (!spi_dev.begin()) {
|
||||
Serial.println("Could not initialize SPI device");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println("\n\nTransfer test");
|
||||
for (uint16_t x = 0; x <= 0xFF; x++) {
|
||||
uint8_t i = x;
|
||||
Serial.print("0x");
|
||||
Serial.print(i, HEX);
|
||||
spi_dev.read(&i, 1, i);
|
||||
Serial.print("/");
|
||||
Serial.print(i, HEX);
|
||||
Serial.print(", ");
|
||||
delay(25);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <Adafruit_SPIDevice.h>
|
||||
|
||||
#define SPIDEVICE_CS 10
|
||||
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("SPI device read and write test");
|
||||
|
||||
if (!spi_dev.begin()) {
|
||||
Serial.println("Could not initialize SPI device");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
uint8_t buffer[32];
|
||||
|
||||
// Try to read 32 bytes
|
||||
spi_dev.read(buffer, 32);
|
||||
Serial.print("Read: ");
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(buffer[i], HEX);
|
||||
Serial.print(", ");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// read a register by writing first, then reading
|
||||
buffer[0] = 0x8F; // we'll reuse the same buffer
|
||||
spi_dev.write_then_read(buffer, 1, buffer, 2, false);
|
||||
Serial.print("Write then Read: ");
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(buffer[i], HEX);
|
||||
Serial.print(", ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,268 @@
|
||||
/***************************************************
|
||||
|
||||
This is an example for how to use Adafruit_BusIO_RegisterBits from
|
||||
Adafruit_BusIO library.
|
||||
|
||||
Designed specifically to work with the Adafruit RTD Sensor
|
||||
----> https://www.adafruit.com/products/3328
|
||||
uisng a MAX31865 RTD-to-Digital Converter
|
||||
----> https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
|
||||
|
||||
This sensor uses SPI to communicate, 4 pins are required to
|
||||
interface.
|
||||
A fifth pin helps to detect when a new conversion is ready.
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Example written (2020/3) by Andreas Hardtung/AnHard.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
#include <Adafruit_SPIDevice.h>
|
||||
|
||||
#define MAX31865_SPI_SPEED (5000000)
|
||||
#define MAX31865_SPI_BITORDER (SPI_BITORDER_MSBFIRST)
|
||||
#define MAX31865_SPI_MODE (SPI_MODE1)
|
||||
|
||||
#define MAX31865_SPI_CS (10)
|
||||
#define MAX31865_READY_PIN (2)
|
||||
|
||||
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(
|
||||
MAX31865_SPI_CS, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER,
|
||||
MAX31865_SPI_MODE, &SPI); // Hardware SPI
|
||||
// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, 13, 12, 11,
|
||||
// MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE); // Software
|
||||
// SPI
|
||||
|
||||
// MAX31865 chip related
|
||||
// *********************************************************************************************
|
||||
Adafruit_BusIO_Register config_reg =
|
||||
Adafruit_BusIO_Register(&spi_dev, 0x00, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
|
||||
Adafruit_BusIO_RegisterBits bias_bit =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 1, 7);
|
||||
Adafruit_BusIO_RegisterBits auto_bit =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 1, 6);
|
||||
Adafruit_BusIO_RegisterBits oneS_bit =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 1, 5);
|
||||
Adafruit_BusIO_RegisterBits wire_bit =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 1, 4);
|
||||
Adafruit_BusIO_RegisterBits faultT_bits =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 2, 2);
|
||||
Adafruit_BusIO_RegisterBits faultR_bit =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 1, 1);
|
||||
Adafruit_BusIO_RegisterBits fi50hz_bit =
|
||||
Adafruit_BusIO_RegisterBits(&config_reg, 1, 0);
|
||||
|
||||
Adafruit_BusIO_Register rRatio_reg =
|
||||
Adafruit_BusIO_Register(&spi_dev, 0x01, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
|
||||
Adafruit_BusIO_RegisterBits rRatio_bits =
|
||||
Adafruit_BusIO_RegisterBits(&rRatio_reg, 15, 1);
|
||||
Adafruit_BusIO_RegisterBits fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&rRatio_reg, 1, 0);
|
||||
|
||||
Adafruit_BusIO_Register maxRratio_reg =
|
||||
Adafruit_BusIO_Register(&spi_dev, 0x03, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
|
||||
Adafruit_BusIO_RegisterBits maxRratio_bits =
|
||||
Adafruit_BusIO_RegisterBits(&maxRratio_reg, 15, 1);
|
||||
|
||||
Adafruit_BusIO_Register minRratio_reg =
|
||||
Adafruit_BusIO_Register(&spi_dev, 0x05, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
|
||||
Adafruit_BusIO_RegisterBits minRratio_bits =
|
||||
Adafruit_BusIO_RegisterBits(&minRratio_reg, 15, 1);
|
||||
|
||||
Adafruit_BusIO_Register fault_reg =
|
||||
Adafruit_BusIO_Register(&spi_dev, 0x07, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
|
||||
Adafruit_BusIO_RegisterBits range_high_fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 7);
|
||||
Adafruit_BusIO_RegisterBits range_low_fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 6);
|
||||
Adafruit_BusIO_RegisterBits refin_high_fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 5);
|
||||
Adafruit_BusIO_RegisterBits refin_low_fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 4);
|
||||
Adafruit_BusIO_RegisterBits rtdin_low_fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 3);
|
||||
Adafruit_BusIO_RegisterBits voltage_fault_bit =
|
||||
Adafruit_BusIO_RegisterBits(&fault_reg, 1, 2);
|
||||
|
||||
// Print the details of the configuration register.
|
||||
void printConfig(void) {
|
||||
Serial.print("BIAS: ");
|
||||
if (bias_bit.read())
|
||||
Serial.print("ON");
|
||||
else
|
||||
Serial.print("OFF");
|
||||
Serial.print(", AUTO: ");
|
||||
if (auto_bit.read())
|
||||
Serial.print("ON");
|
||||
else
|
||||
Serial.print("OFF");
|
||||
Serial.print(", ONES: ");
|
||||
if (oneS_bit.read())
|
||||
Serial.print("ON");
|
||||
else
|
||||
Serial.print("OFF");
|
||||
Serial.print(", WIRE: ");
|
||||
if (wire_bit.read())
|
||||
Serial.print("3");
|
||||
else
|
||||
Serial.print("2/4");
|
||||
Serial.print(", FAULTCLEAR: ");
|
||||
if (faultR_bit.read())
|
||||
Serial.print("ON");
|
||||
else
|
||||
Serial.print("OFF");
|
||||
Serial.print(", ");
|
||||
if (fi50hz_bit.read())
|
||||
Serial.print("50HZ");
|
||||
else
|
||||
Serial.print("60HZ");
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Check and print faults. Then clear them.
|
||||
void checkFaults(void) {
|
||||
if (fault_bit.read()) {
|
||||
Serial.print("MAX: ");
|
||||
Serial.println(maxRratio_bits.read());
|
||||
Serial.print("VAL: ");
|
||||
Serial.println(rRatio_bits.read());
|
||||
Serial.print("MIN: ");
|
||||
Serial.println(minRratio_bits.read());
|
||||
|
||||
if (range_high_fault_bit.read())
|
||||
Serial.println("Range high fault");
|
||||
if (range_low_fault_bit.read())
|
||||
Serial.println("Range low fault");
|
||||
if (refin_high_fault_bit.read())
|
||||
Serial.println("REFIN high fault");
|
||||
if (refin_low_fault_bit.read())
|
||||
Serial.println("REFIN low fault");
|
||||
if (rtdin_low_fault_bit.read())
|
||||
Serial.println("RTDIN low fault");
|
||||
if (voltage_fault_bit.read())
|
||||
Serial.println("Voltage fault");
|
||||
|
||||
faultR_bit.write(1); // clear fault
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
#if (MAX31865_1_READY_PIN != -1)
|
||||
pinMode(MAX31865_READY_PIN, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("SPI Adafruit_BusIO_RegisterBits test on MAX31865");
|
||||
|
||||
if (!spi_dev.begin()) {
|
||||
Serial.println("Could not initialize SPI device");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Set up for automode 50Hz. We don't care about selfheating. We want the
|
||||
// highest possible sampling rate.
|
||||
auto_bit.write(0); // Don't switch filtermode while auto_mode is on.
|
||||
fi50hz_bit.write(1); // Set filter to 50Hz mode.
|
||||
faultR_bit.write(1); // Clear faults.
|
||||
bias_bit.write(1); // In automode we want to have the bias current always on.
|
||||
delay(5); // Wait until bias current settles down.
|
||||
// 10.5 time constants of the input RC network is required.
|
||||
// 10ms worst case for 10kω reference resistor and a 0.1µF capacitor
|
||||
// across the RTD inputs. Adafruit Module has 0.1µF and only
|
||||
// 430/4300ω So here 0.43/4.3ms
|
||||
auto_bit.write(
|
||||
1); // Now we can set automode. Automatically starting first conversion.
|
||||
|
||||
// Test the READY_PIN
|
||||
#if (defined(MAX31865_READY_PIN) && (MAX31865_READY_PIN != -1))
|
||||
int i = 0;
|
||||
while (digitalRead(MAX31865_READY_PIN) && i++ <= 100) {
|
||||
delay(1);
|
||||
}
|
||||
if (i >= 100) {
|
||||
Serial.print("ERROR: Max31865 Pin detection does not work. PIN:");
|
||||
Serial.println(MAX31865_READY_PIN);
|
||||
}
|
||||
#else
|
||||
delay(100);
|
||||
#endif
|
||||
|
||||
// Set ratio range.
|
||||
// Setting the temperatures would need some more calculation - not related to
|
||||
// Adafruit_BusIO_RegisterBits.
|
||||
uint16_t ratio = rRatio_bits.read();
|
||||
maxRratio_bits.write((ratio < 0x8fffu - 1000u) ? ratio + 1000u : 0x8fffu);
|
||||
minRratio_bits.write((ratio > 1000u) ? ratio - 1000u : 0u);
|
||||
|
||||
printConfig();
|
||||
checkFaults();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#if (defined(MAX31865_READY_PIN) && (MAX31865_1_READY_PIN != -1))
|
||||
// Is conversion ready?
|
||||
if (!digitalRead(MAX31865_READY_PIN))
|
||||
#else
|
||||
// Warant conversion is ready.
|
||||
delay(21); // 21ms for 50Hz-mode. 19ms in 60Hz-mode.
|
||||
#endif
|
||||
{
|
||||
// Read ratio, calculate temperature, scale, filter and print.
|
||||
Serial.println(rRatio2C(rRatio_bits.read()) * 100.0f,
|
||||
0); // Temperature scaled by 100
|
||||
// Check, print, clear faults.
|
||||
checkFaults();
|
||||
}
|
||||
|
||||
// Do something else.
|
||||
// delay(15000);
|
||||
}
|
||||
|
||||
// Module/Sensor related. Here Adafruit PT100 module with a 2_Wire PT100 Class C
|
||||
// *****************************
|
||||
float rRatio2C(uint16_t ratio) {
|
||||
// A simple linear conversion.
|
||||
const float R0 = 100.0f;
|
||||
const float Rref = 430.0f;
|
||||
const float alphaPT = 0.003850f;
|
||||
const float ADCmax = (1u << 15) - 1.0f;
|
||||
const float rscale = Rref / ADCmax;
|
||||
// Measured temperature in boiling water 101.08°C with factor a = 1 and b = 0.
|
||||
// Rref and MAX at about 22±2°C. Measured temperature in ice/water bath 0.76°C
|
||||
// with factor a = 1 and b = 0. Rref and MAX at about 22±2°C.
|
||||
// const float a = 1.0f / (alphaPT * R0);
|
||||
const float a = (100.0f / 101.08f) / (alphaPT * R0);
|
||||
// const float b = 0.0f; // 101.08
|
||||
const float b = -0.76f; // 100.32 > 101.08
|
||||
|
||||
return filterRing(((ratio * rscale) - R0) * a + b);
|
||||
}
|
||||
|
||||
// General purpose
|
||||
// *********************************************************************************************
|
||||
#define RINGLENGTH 250
|
||||
float filterRing(float newVal) {
|
||||
static float ring[RINGLENGTH] = {0.0};
|
||||
static uint8_t ringIndex = 0;
|
||||
static bool ringFull = false;
|
||||
|
||||
if (ringIndex == RINGLENGTH) {
|
||||
ringFull = true;
|
||||
ringIndex = 0;
|
||||
}
|
||||
ring[ringIndex] = newVal;
|
||||
uint8_t loopEnd = (ringFull) ? RINGLENGTH : ringIndex + 1;
|
||||
float ringSum = 0.0f;
|
||||
for (uint8_t i = 0; i < loopEnd; i++)
|
||||
ringSum += ring[i];
|
||||
ringIndex++;
|
||||
return ringSum / loopEnd;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
#include <Adafruit_SPIDevice.h>
|
||||
|
||||
#define SPIDEVICE_CS 10
|
||||
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS);
|
||||
|
||||
void setup() {
|
||||
while (!Serial) {
|
||||
delay(10);
|
||||
}
|
||||
Serial.begin(115200);
|
||||
Serial.println("SPI device register test");
|
||||
|
||||
if (!spi_dev.begin()) {
|
||||
Serial.println("Could not initialize SPI device");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
Adafruit_BusIO_Register id_reg =
|
||||
Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD);
|
||||
uint8_t id = 0;
|
||||
id_reg.read(&id);
|
||||
Serial.print("ID register = 0x");
|
||||
Serial.println(id, HEX);
|
||||
|
||||
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(
|
||||
&spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST);
|
||||
uint16_t thresh = 0;
|
||||
thresh_reg.read(&thresh);
|
||||
Serial.print("Initial threshold register = 0x");
|
||||
Serial.println(thresh, HEX);
|
||||
|
||||
thresh_reg.write(~thresh);
|
||||
|
||||
Serial.print("Post threshold register = 0x");
|
||||
Serial.println(thresh_reg.read(), HEX);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit BusIO
|
||||
version=1.17.4
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=This is a library for abstracting away UART, I2C and SPI interfacing
|
||||
paragraph=This is a library for abstracting away UART, I2C and SPI interfacing
|
||||
category=Signal Input/Output
|
||||
url=https://github.com/adafruit/Adafruit_BusIO
|
||||
architectures=*
|
||||
BIN
firmware_adxl345_spi/lib/Archiwum/ADXL345DriverSPI.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/ADXL345DriverSPI.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/ADXL345FreshSPI.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/ADXL345FreshSPI.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit ADXL345.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit ADXL345.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit BusIO.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit BusIO.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit Unified Sensor.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit Unified Sensor.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit-GFX-Library.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit-GFX-Library.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit_SSD1306.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/Adafruit_SSD1306.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/LCD-I2C.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/LCD-I2C.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/LiquidCrystal_I2C-master.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/LiquidCrystal_I2C-master.zip
Normal file
Binary file not shown.
BIN
firmware_adxl345_spi/lib/Archiwum/SerialCommands.zip
Normal file
BIN
firmware_adxl345_spi/lib/Archiwum/SerialCommands.zip
Normal file
Binary file not shown.
13
firmware_adxl345_spi/lib/ArduinoThread/.gitignore
vendored
Normal file
13
firmware_adxl345_spi/lib/ArduinoThread/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
1
firmware_adxl345_spi/lib/ArduinoThread/.piopm
Normal file
1
firmware_adxl345_spi/lib/ArduinoThread/.piopm
Normal file
@@ -0,0 +1 @@
|
||||
{"type": "library", "name": "ArduinoThread", "version": "2.1.1", "spec": {"owner": "ivanseidel", "id": 7097, "name": "ArduinoThread", "requirements": null, "uri": null}}
|
||||
21
firmware_adxl345_spi/lib/ArduinoThread/LICENSE.txt
Normal file
21
firmware_adxl345_spi/lib/ArduinoThread/LICENSE.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Ivan Seidel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
205
firmware_adxl345_spi/lib/ArduinoThread/README.md
Normal file
205
firmware_adxl345_spi/lib/ArduinoThread/README.md
Normal file
@@ -0,0 +1,205 @@
|
||||

|
||||
|
||||
Arduino does not support "REAL" parallel tasks (aka Threads), but we can make use of this Library to
|
||||
improve our code, and easily schedule tasks with fixed (or variable) time between runs.
|
||||
|
||||
This Library helps to maintain organized and to facilitate the use of multiple tasks. We can
|
||||
use Timers Interrupts, and make it really powerfull, running "pseudo-background" tasks under the rug.
|
||||
|
||||
For example, I personaly use it for all my projects, and put all sensor aquisition and
|
||||
filtering inside it, leaving the main loop, just for logic and "cool" part.
|
||||
|
||||
#### ArduinoThreads is a library for managing the periodic execution of multiple tasks.
|
||||
|
||||
Blinking an LED is often the very first thing an Arduino user learns. And this demonstrates that periodically performing one single task, like toggling the LED state, is really easy. However, one may quickly discover that managing multiple periodic tasks is not so simple if the tasks have different execution periods.
|
||||
|
||||
ArduinoThreads is designed to simplify programs that need to perform multiple periodic tasks. The user defines a Thread object for each of those tasks, then lets the library manage their scheduled execution.
|
||||
|
||||
It should be noted that these are not “threads” in the real computer-science meaning of the term: tasks are implemented as functions that are periodically run to completion. On the one hand, this means that the only way a task can “yield” the CPU is by returning to the caller, and it is thus inadvisable to delay() or do long waits inside a task. On the other hand, this makes ArduinoThreads memory friendly, as no stack needs to be allocated per task.
|
||||
|
||||
## Installation
|
||||
|
||||
1. "Download":https://github.com/ivanseidel/ArduinoThread/archive/master.zip the Master branch from gitHub.
|
||||
2. Unzip and modify the Folder name to "ArduinoThread" (Remove the '-master')
|
||||
3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software).
|
||||
4. Restart Arduino IDE
|
||||
|
||||
**If you are here, because another Library requires this class, just don't waste time reading bellow. Install and ready.**
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
There are many examples showing many ways to use it. Here, we will explain Class itself,
|
||||
what it does and "how" it does.
|
||||
|
||||
There are basicaly, three Classes included in this Library:
|
||||
`Thread`, `ThreadController` and `StaticThreadController` (both controllers inherit from Thread).
|
||||
|
||||
- `Thread class`: This is the basic class, witch contains methods to set and run callbacks,
|
||||
check if the Thread should be runned, and also creates a unique ThreadID on the instantiation.
|
||||
|
||||
- `ThreadController class`: Responsable for "holding" multiple Threads. Can also be called
|
||||
as "a group of Threads", and is used to perform run in every Thread ONLY when needed.
|
||||
|
||||
- `StaticThreadController class`: Slighly faster and smaller version of `ThreadController`.
|
||||
It works similar to `ThreadController`, but once constructed it can't add or remove threads to run.
|
||||
|
||||
* The instantiation of a Thread class is very simple:
|
||||
|
||||
```c++
|
||||
Thread myThread = Thread();
|
||||
// or, if initializing a pointer
|
||||
Thread* myThread = new Thread();
|
||||
```
|
||||
|
||||
|
||||
* Setting up a thread is essential. You can configure many things:
|
||||
|
||||
```c++
|
||||
myThread.enabled = true; // Default enabled value is true
|
||||
myThread.setInterval(10); // Setts the wanted interval to be 10ms
|
||||
/*
|
||||
This is useful for debugging
|
||||
(Thread Name is disabled by default, to use less memory)
|
||||
(Enable it by definint USE_THREAD_NAMES on 'Thread.h')
|
||||
*/
|
||||
myThread.ThreadName = "myThread tag";
|
||||
// This will set the callback of the Thread: "What should I run"?
|
||||
myThread.onRun(callback_function); // callback_function is the name of the function
|
||||
```
|
||||
|
||||
Ok, creating Threads are not so hard. But what do we do with them now?
|
||||
|
||||
* First, let's see how Threads should work, to understand what a `ThreadController` is and does
|
||||
|
||||
```c++
|
||||
// First check if our Thread "should" be runned
|
||||
if(myThread.shouldRun()){
|
||||
// Yes, the Thread should be runned, let's run it
|
||||
myThread.run();
|
||||
}
|
||||
```
|
||||
|
||||
Now that you got the idea, let's think a little bit: What if i have 3, 5, 100 Threads. Do I need to check EACH one?!?
|
||||
|
||||
* The answer is: NO. Create a `ThreadController` or `StaticThreadController`,
|
||||
and put all your boring-complex Threads inside it!
|
||||
|
||||
```c++
|
||||
// Instantiate a new ThreadController
|
||||
ThreadController controller = ThreadController();
|
||||
// Now, put a bunch of Threads inside it, FEED it!
|
||||
controller.add(&myThread); // Notice the & before the thread, IF it's not instantied as a pointer.
|
||||
controller.add(&hisThread);
|
||||
controller.add(&sensorReadings);
|
||||
...
|
||||
```
|
||||
or
|
||||
```c++
|
||||
// Instantiate a new StaticThreadController with the number of threads to be supplied as template parameter
|
||||
StaticThreadController<3> controller (&myThread, &hisThread, &sensorReadings);
|
||||
// You don't need to do anything else, controller now contains all the threads.
|
||||
...
|
||||
```
|
||||
|
||||
* You have created, configured, grouped it. What is missing? Yes, whe should RUN it!
|
||||
|
||||
```c++
|
||||
// call run on a Thread, a ThreadController or a StaticThreadController to run it
|
||||
controller.run();
|
||||
```
|
||||
|
||||
This will run all the Threads that NEED to be runned.
|
||||
|
||||
Congratulations, you have learned the basics of `ArduinoThread`. If you want some TIPS, see bellow.
|
||||
|
||||
|
||||
### TIPs and Warnings
|
||||
|
||||
* ThreadController is not a `LinkedList`. It's "MAXIMUM" size (the maximum Threads that it can
|
||||
store) is defined on ThreadController.h (default is 15)
|
||||
|
||||
* !!!! VERY IMPORTANT !!!! When extending `Thread` class and implementing the function
|
||||
`run()`, always remember to put `runned();` after all, otherwhise the `Thread` will ALWAYS run.
|
||||
|
||||
* It's a good idea, to create a Timer interrupt and call a ThreadController.run() there.
|
||||
That way, you don't need to worry about reading sensors and doing time-sensitive stuff
|
||||
on your main code (loop). Check `ControllerWithTimer` example.
|
||||
|
||||
* Inheriting from `Thread` or even `ThreadController` is always a good idea.
|
||||
For example, I always create base classes of sensors that extends `Thread`,
|
||||
so that I can "register" the sensors inside a ThreadController, and forget
|
||||
about really reading sensors, just getting theirs values within my main code.
|
||||
Checkout `SensorThread` example.
|
||||
|
||||
* Remember that `ThreadController` is in fact, a Thread. If you want to enable
|
||||
or disable a GROUP of Threads, think about putting all of them inside a ThreadController,
|
||||
and adding this ThreadController to another ThreadController (YES! One ThreadController
|
||||
inside another). Check `ControllerInController` example.
|
||||
|
||||
* There is a `StaticThreadController` which is better to use when you know exact number of
|
||||
threads to run. You cannot add or remove threads in runtime, but `StaticThreadController`
|
||||
doesn't have additional memory overhead to keep all the treads together, doesn't have any
|
||||
limitations how many threads to store (except of available memory) and also the code may be slighly
|
||||
more optimized because all the threads always exist and no need to do any runtime checks.
|
||||
|
||||
* Check the full example `CustomTimedThread` for a cool application of Threads that runs
|
||||
for a period, after a button is pressed.
|
||||
|
||||
* Running tasks on the Timer interrupts must be tought REALLY carefully
|
||||
|
||||
You cannot use "sleep()" inside a interrupt, because it will get into a infinite loop.
|
||||
|
||||
Things must do stuff quickly. Waiting too loooong on a interrupt, means waiting too
|
||||
loooong on the main code (loop)
|
||||
|
||||
Things might get "scrambled". Since Timers interrupts actualy "BREAK" your code in half
|
||||
and start running the interrupt, you might want to call `noInterrupts` and `interrupts`
|
||||
on places where cannot be interrupted:
|
||||
|
||||
```c++
|
||||
noInterrupts();
|
||||
// Put the code that CANNOT be interrupted...
|
||||
interrupts(); // This will enable the interrupts egain. DO NOT FORGET!
|
||||
```
|
||||
|
||||
|
||||
## Library Reference
|
||||
|
||||
### You should know:
|
||||
|
||||
- `bool Thread::enabled` - Enables or disables the Thread. (do not stop it from running, but will
|
||||
return false when shouldRun() is called)
|
||||
- `void Thread::setInterval()` - Setts the desired interval for the Thread (in Ms).
|
||||
- `bool Thread::shouldRun()` - Returns true, if the Thread should be runned.
|
||||
(Basicaly,the logic is: (reached time AND is enabled?).
|
||||
- `void Thread::onRun(<function>)` - The target callback function to be called.
|
||||
- `void Thread::run()` - This will run the Thread (call the callback function).
|
||||
- `int Thread::ThreadID` - Theoretically, it's the address of memory. It's unique, and can
|
||||
be used to compare if two threads are identical.
|
||||
- `int Thread::ThreadName` - A human-redable thread name. Default is "Thread ThreadID"
|
||||
eg.: "Thread 141515"; Note that to enable this attribute, you must uncomment the line that disables it on 'Thread.h';
|
||||
- protected: `void Thread::runned()` - Used to reset internal timer of the Thread.
|
||||
This is automaticaly called AFTER a call to `run()`.
|
||||
|
||||
|
||||
- `void ThreadController::run()` - This will run the all `Threads` within the `ThreadController`,
|
||||
only if needed (if shouldRun returns true);
|
||||
- `bool ThreadController::add(Thread* _thread)` - This will add a the thread to the ThreadController,
|
||||
and return `true` if suceeded (it the array is full, returns false).
|
||||
- `void ThreadController::remove(Thread* _thread)` - This will remove the Thread from the ThreadController.
|
||||
- `void ThreadController::remove(int index)` - This will remove the thread on the position `index`.
|
||||
- `void ThreadController::clear()` - This will remove ALL threads from the ThreadController array.
|
||||
- `int ThreadController::size(bool cached = true)` - Returns how many Threads are allocated
|
||||
inside the ThreadController. If cached is `false`, will force the calculation of threads.
|
||||
- `Thread* ThreadController::get(int index)` - Returns the Thread on the position `index`.
|
||||
|
||||
|
||||
- `void StaticThreadController::run()` - This will run the all `Threads` within the `StaicThreadController`,
|
||||
only if needed (if shouldRun returns true);
|
||||
- `int StaticThreadController::size()` - Returns how many Threads are allocated inside the StaticThreadController.
|
||||
- `Thread* ThreadController::get(int index)` - Returns the Thread on the position `index` and `nullptr` if `index`
|
||||
is out of bounds.
|
||||
|
||||
### You don't need to know:
|
||||
- Nothing, yet ;)
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
StaticThreadController.h - Controlls a list of Threads with different timings
|
||||
|
||||
Basicaly, what it does is to keep track of current Threads and run when
|
||||
necessary.
|
||||
|
||||
StaticThreadController is an extended class of Thread, because of that,
|
||||
it allows you to add a StaticThreadController inside another kind of ThreadController...
|
||||
|
||||
It works exact as ThreadController except you can't add or remove treads dynamically.
|
||||
|
||||
Created by Alex Eremin, September, 2016.
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
#ifndef StaticThreadController_h
|
||||
#define StaticThreadController_h
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
template <int N>
|
||||
class StaticThreadController: public Thread{
|
||||
protected:
|
||||
//since this is a static controller, the pointers themselves can be const
|
||||
//it should be distinguished from 'const Thread* thread[N]'
|
||||
Thread * const thread[N];
|
||||
public:
|
||||
template <typename... T>
|
||||
StaticThreadController(T... params) :
|
||||
Thread(),
|
||||
thread{params...}
|
||||
{
|
||||
#ifdef USE_THREAD_NAMES
|
||||
// Overrides name
|
||||
ThreadName = "StaticThreadController ";
|
||||
ThreadName = ThreadName + ThreadID;
|
||||
#endif
|
||||
};
|
||||
|
||||
// run() Method is overrided
|
||||
void run() override
|
||||
{
|
||||
// Run this thread before
|
||||
if(_onRun != nullptr && shouldRun())
|
||||
_onRun();
|
||||
|
||||
for(int i = 0; i < N; i++){
|
||||
// Is enabled? Timeout exceeded?
|
||||
if(thread[i]->shouldRun()){
|
||||
thread[i]->run();
|
||||
}
|
||||
}
|
||||
|
||||
// StaticThreadController extends Thread, so we should flag as runned thread
|
||||
runned();
|
||||
}
|
||||
|
||||
// Return the quantity of Threads
|
||||
static constexpr int size() { return N; };
|
||||
|
||||
// Return the I Thread on the array
|
||||
// Returns nullptr if index is out of bounds
|
||||
Thread* get(int index) {
|
||||
return (index >= 0 && index < N) ? thread[index] : nullptr;
|
||||
};
|
||||
|
||||
// Return the I Thread on the array
|
||||
// Doesn't perform any bounds checks and behaviour is
|
||||
// unpredictable in case of index > N
|
||||
Thread& operator[](int index) {
|
||||
return *thread[index];
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
52
firmware_adxl345_spi/lib/ArduinoThread/Thread.cpp
Normal file
52
firmware_adxl345_spi/lib/ArduinoThread/Thread.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "Thread.h"
|
||||
|
||||
Thread::Thread(void (*callback)(void), unsigned long _interval){
|
||||
enabled = true;
|
||||
onRun(callback);
|
||||
_cached_next_run = 0;
|
||||
last_run = millis();
|
||||
|
||||
ThreadID = (int)this;
|
||||
#ifdef USE_THREAD_NAMES
|
||||
ThreadName = "Thread ";
|
||||
ThreadName = ThreadName + ThreadID;
|
||||
#endif
|
||||
|
||||
setInterval(_interval);
|
||||
};
|
||||
|
||||
void Thread::runned(unsigned long time){
|
||||
// Saves last_run
|
||||
last_run = time;
|
||||
|
||||
// Cache next run
|
||||
_cached_next_run = last_run + interval;
|
||||
}
|
||||
|
||||
void Thread::setInterval(unsigned long _interval){
|
||||
// Save interval
|
||||
interval = _interval;
|
||||
|
||||
// Cache the next run based on the last_run
|
||||
_cached_next_run = last_run + interval;
|
||||
}
|
||||
|
||||
bool Thread::shouldRun(unsigned long time){
|
||||
// If the "sign" bit is set the signed difference would be negative
|
||||
bool time_remaining = (time - _cached_next_run) & 0x80000000;
|
||||
|
||||
// Exceeded the time limit, AND is enabled? Then should run...
|
||||
return !time_remaining && enabled;
|
||||
}
|
||||
|
||||
void Thread::onRun(void (*callback)(void)){
|
||||
_onRun = callback;
|
||||
}
|
||||
|
||||
void Thread::run(){
|
||||
if(_onRun != NULL)
|
||||
_onRun();
|
||||
|
||||
// Update last_run and _cached_next_run
|
||||
runned();
|
||||
}
|
||||
89
firmware_adxl345_spi/lib/ArduinoThread/Thread.h
Normal file
89
firmware_adxl345_spi/lib/ArduinoThread/Thread.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Thread.h - An runnable object
|
||||
|
||||
Thread is responsable for holding the "action" for something,
|
||||
also, it responds if it "should" or "should not" run, based on
|
||||
the current time;
|
||||
|
||||
For instructions, go to https://github.com/ivanseidel/ArduinoThread
|
||||
|
||||
Created by Ivan Seidel Gomes, March, 2013.
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
#ifndef Thread_h
|
||||
#define Thread_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
Uncomment this line to enable ThreadName Strings.
|
||||
|
||||
It might be usefull if you are loging thread with Serial,
|
||||
or displaying a list of threads...
|
||||
*/
|
||||
// #define USE_THREAD_NAMES 1
|
||||
|
||||
class Thread{
|
||||
protected:
|
||||
// Desired interval between runs
|
||||
unsigned long interval;
|
||||
|
||||
// Last runned time in Ms
|
||||
unsigned long last_run;
|
||||
|
||||
// Scheduled run in Ms (MUST BE CACHED)
|
||||
unsigned long _cached_next_run;
|
||||
|
||||
/*
|
||||
IMPORTANT! Run after all calls to run()
|
||||
Updates last_run and cache next run.
|
||||
NOTE: This MUST be called if extending
|
||||
this class and implementing run() method
|
||||
*/
|
||||
void runned(unsigned long time);
|
||||
|
||||
// Default is to mark it runned "now"
|
||||
void runned() { runned(millis()); }
|
||||
|
||||
// Callback for run() if not implemented
|
||||
void (*_onRun)(void);
|
||||
|
||||
public:
|
||||
|
||||
// If the current Thread is enabled or not
|
||||
bool enabled;
|
||||
|
||||
// ID of the Thread (initialized from memory adr.)
|
||||
int ThreadID;
|
||||
|
||||
#ifdef USE_THREAD_NAMES
|
||||
// Thread Name (used for better UI).
|
||||
String ThreadName;
|
||||
#endif
|
||||
|
||||
Thread(void (*callback)(void) = NULL, unsigned long _interval = 0);
|
||||
|
||||
// Set the desired interval for calls, and update _cached_next_run
|
||||
virtual void setInterval(unsigned long _interval);
|
||||
|
||||
// Return if the Thread should be runned or not
|
||||
virtual bool shouldRun(unsigned long time);
|
||||
|
||||
// Default is to check whether it should run "now"
|
||||
bool shouldRun() { return shouldRun(millis()); }
|
||||
|
||||
// Callback set
|
||||
void onRun(void (*callback)(void));
|
||||
|
||||
// Runs Thread
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
#endif
|
||||
115
firmware_adxl345_spi/lib/ArduinoThread/ThreadController.cpp
Normal file
115
firmware_adxl345_spi/lib/ArduinoThread/ThreadController.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "Thread.h"
|
||||
#include "ThreadController.h"
|
||||
|
||||
ThreadController::ThreadController(unsigned long _interval): Thread(){
|
||||
cached_size = 0;
|
||||
|
||||
clear();
|
||||
setInterval(_interval);
|
||||
|
||||
#ifdef USE_THREAD_NAMES
|
||||
// Overrides name
|
||||
ThreadName = "ThreadController ";
|
||||
ThreadName = ThreadName + ThreadID;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
ThreadController run() (cool stuf)
|
||||
*/
|
||||
void ThreadController::run(){
|
||||
// Run this thread before
|
||||
if(_onRun != NULL)
|
||||
_onRun();
|
||||
|
||||
unsigned long time = millis();
|
||||
int checks = 0;
|
||||
for(int i = 0; i < MAX_THREADS && checks <= cached_size; i++){
|
||||
// Object exists? Is enabled? Timeout exceeded?
|
||||
if(thread[i]){
|
||||
checks++;
|
||||
if(thread[i]->shouldRun(time)){
|
||||
thread[i]->run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ThreadController extends Thread, so we should flag as runned thread
|
||||
runned();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
List controller (boring part)
|
||||
*/
|
||||
bool ThreadController::add(Thread* _thread){
|
||||
// Check if the Thread already exists on the array
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
if(thread[i] != NULL && thread[i]->ThreadID == _thread->ThreadID)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find an empty slot
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
if(!thread[i]){
|
||||
// Found a empty slot, now add Thread
|
||||
thread[i] = _thread;
|
||||
cached_size++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Array is full
|
||||
return false;
|
||||
}
|
||||
|
||||
void ThreadController::remove(int id){
|
||||
// Find Threads with the id, and removes
|
||||
bool found = false;
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
if(thread[i]->ThreadID == id){
|
||||
thread[i] = NULL;
|
||||
cached_size--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadController::remove(Thread* _thread){
|
||||
remove(_thread->ThreadID);
|
||||
}
|
||||
|
||||
void ThreadController::clear(){
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
thread[i] = NULL;
|
||||
}
|
||||
cached_size = 0;
|
||||
}
|
||||
|
||||
int ThreadController::size(bool cached){
|
||||
if(cached)
|
||||
return cached_size;
|
||||
|
||||
int size = 0;
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
if(thread[i])
|
||||
size++;
|
||||
}
|
||||
cached_size = size;
|
||||
|
||||
return cached_size;
|
||||
}
|
||||
|
||||
Thread* ThreadController::get(int index){
|
||||
int pos = -1;
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
if(thread[i] != NULL){
|
||||
pos++;
|
||||
|
||||
if(pos == index)
|
||||
return thread[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
53
firmware_adxl345_spi/lib/ArduinoThread/ThreadController.h
Normal file
53
firmware_adxl345_spi/lib/ArduinoThread/ThreadController.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
ThreadController.h - Controlls a list of Threads with different timings
|
||||
|
||||
Basicaly, what it does is to keep track of current Threads and run when
|
||||
necessary.
|
||||
|
||||
ThreadController is an extended class of Thread, because of that,
|
||||
it allows you to add a ThreadController inside another ThreadController...
|
||||
|
||||
For instructions, go to https://github.com/ivanseidel/ArduinoThread
|
||||
|
||||
Created by Ivan Seidel Gomes, March, 2013.
|
||||
Released into the public domain.
|
||||
*/
|
||||
|
||||
#ifndef ThreadController_h
|
||||
#define ThreadController_h
|
||||
|
||||
#include "Thread.h"
|
||||
#include "inttypes.h"
|
||||
|
||||
#define MAX_THREADS 15
|
||||
|
||||
class ThreadController: public Thread{
|
||||
protected:
|
||||
Thread* thread[MAX_THREADS];
|
||||
int cached_size;
|
||||
public:
|
||||
ThreadController(unsigned long _interval = 0);
|
||||
|
||||
// run() Method is overrided
|
||||
void run();
|
||||
|
||||
// Adds a thread in the first available slot (remove first)
|
||||
// Returns if the Thread could be added or not
|
||||
bool add(Thread* _thread);
|
||||
|
||||
// remove the thread (given the Thread* or ThreadID)
|
||||
void remove(int _id);
|
||||
void remove(Thread* _thread);
|
||||
|
||||
// Removes all threads
|
||||
void clear();
|
||||
|
||||
// Return the quantity of Threads
|
||||
int size(bool cached = true);
|
||||
|
||||
// Return the I Thread on the array
|
||||
// Returns NULL if none found
|
||||
Thread* get(int index);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <Thread.h>
|
||||
#include <ThreadController.h>
|
||||
|
||||
int ledPin = 13;
|
||||
|
||||
// ThreadController that will controll all threads
|
||||
ThreadController controll = ThreadController();
|
||||
|
||||
//My Thread
|
||||
Thread myThread = Thread();
|
||||
//His Thread
|
||||
Thread hisThread = Thread();
|
||||
//Blink Led Thread
|
||||
Thread blinkLedThread = Thread();
|
||||
//ThreadController, that will be added to controll
|
||||
ThreadController groupOfThreads = ThreadController();
|
||||
|
||||
// callback for myThread
|
||||
void niceCallback(){
|
||||
Serial.print("COOL! I'm running on: ");
|
||||
Serial.println(millis());
|
||||
}
|
||||
|
||||
// callback for hisThread
|
||||
void boringCallback(){
|
||||
Serial.println("BORING...");
|
||||
}
|
||||
|
||||
// callback for blinkLedThread
|
||||
void blinkLed(){
|
||||
static bool ledStatus = false;
|
||||
ledStatus = !ledStatus;
|
||||
|
||||
digitalWrite(ledPin, ledStatus);
|
||||
|
||||
Serial.print("blinking: ");
|
||||
Serial.println(ledStatus);
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
pinMode(ledPin, OUTPUT);
|
||||
|
||||
// Configure myThread
|
||||
myThread.onRun(niceCallback);
|
||||
myThread.setInterval(500);
|
||||
|
||||
// Configure hisThread
|
||||
hisThread.onRun(boringCallback);
|
||||
hisThread.setInterval(250);
|
||||
|
||||
// Configure blinkLedThread
|
||||
blinkLedThread.onRun(blinkLed);
|
||||
blinkLedThread.setInterval(100);
|
||||
|
||||
// Adds myThread to the controll
|
||||
controll.add(&myThread);
|
||||
|
||||
// Adds hisThread and blinkLedThread to groupOfThreads
|
||||
groupOfThreads.add(&hisThread);
|
||||
groupOfThreads.add(&blinkLedThread);
|
||||
|
||||
// Add groupOfThreads to controll
|
||||
controll.add(&groupOfThreads);
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// run ThreadController
|
||||
// this will check every thread inside ThreadController,
|
||||
// if it should run. If yes, he will run it;
|
||||
controll.run();
|
||||
|
||||
// Rest of code
|
||||
float h = 3.1415;
|
||||
h/=2;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include <Thread.h>
|
||||
#include <ThreadController.h>
|
||||
|
||||
/*
|
||||
This example, requires a Timer Interrupt Library.
|
||||
If you are using Arduino NANO, UNO... (with ATmega168/328)
|
||||
Please go to: http://playground.arduino.cc/code/timer1
|
||||
If you are using Arduino DUE,
|
||||
Please go to: https://github.com/ivanseidel/DueTimer
|
||||
|
||||
Include the library corresponding to your Arduino.
|
||||
*/
|
||||
// #include <DueTimer.h>
|
||||
// #include <TimerOne.h>
|
||||
|
||||
// ThreadController that will controll all threads
|
||||
ThreadController controll = ThreadController();
|
||||
|
||||
//My Thread
|
||||
Thread myThread = Thread();
|
||||
//His Thread
|
||||
Thread hisThread = Thread();
|
||||
|
||||
// callback for myThread
|
||||
void myThreadCallback(){
|
||||
Serial.println("myThread\t\tcallback");
|
||||
}
|
||||
|
||||
// callback for hisThread
|
||||
void hisThreadCallback(){
|
||||
Serial.println("\thisThread\tcallback");
|
||||
}
|
||||
|
||||
// This is the callback for the Timer
|
||||
void timerCallback(){
|
||||
controll.run();
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
// Configure myThread
|
||||
myThread.onRun(myThreadCallback);
|
||||
myThread.setInterval(500);
|
||||
|
||||
// Configure myThread
|
||||
hisThread.onRun(hisThreadCallback);
|
||||
hisThread.setInterval(200);
|
||||
|
||||
// Adds both threads to the controller
|
||||
controll.add(&myThread); // & to pass the pointer to it
|
||||
controll.add(&hisThread);
|
||||
|
||||
/*
|
||||
If using DueTimer...
|
||||
*/
|
||||
// Timer1.attachInterrupt(timerCallback).start(20000);
|
||||
|
||||
/*
|
||||
If using TimerOne...
|
||||
*/
|
||||
// Timer1.initialize(20000);
|
||||
// Timer1.attachInterrupt(timerCallback);
|
||||
// Timer1.start();
|
||||
}
|
||||
|
||||
void waitSerial(){
|
||||
while (!Serial.available());
|
||||
delay(10);
|
||||
while (Serial.available() && Serial.read());
|
||||
}
|
||||
|
||||
void loop(){
|
||||
while(1){
|
||||
noInterrupts(); // Call to disable interrupts
|
||||
Serial.println("Type anyting to stop myThread!");
|
||||
interrupts(); // Call to enable interrupts
|
||||
waitSerial();
|
||||
myThread.enabled = false;
|
||||
|
||||
noInterrupts();
|
||||
Serial.println("Type anyting to stop hisThread!");
|
||||
interrupts();
|
||||
waitSerial();
|
||||
hisThread.enabled = false;
|
||||
|
||||
noInterrupts();
|
||||
Serial.println("Type anyting to enable myThread!");
|
||||
interrupts();
|
||||
waitSerial();
|
||||
myThread.enabled = true;
|
||||
|
||||
noInterrupts();
|
||||
Serial.println("Type anyting to enable hisThread!");
|
||||
interrupts();
|
||||
waitSerial();
|
||||
hisThread.enabled = true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
This is an example from ArduinoThread. You can find more information
|
||||
in https://github.com/ivanseidel/ArduinoThread.
|
||||
|
||||
Coded by Ivan Seidel, Jun/2014 - ivanseidel@gmail.com
|
||||
|
||||
Dont be afraid. 90% is commented lines. READ them, they will teach you.
|
||||
*/
|
||||
|
||||
#include <Thread.h>
|
||||
#include <ThreadController.h>
|
||||
|
||||
/*
|
||||
This example provides an object-oriented approach to
|
||||
develop a custom Thread that overrides the 'shouldRun'
|
||||
method, to only run the thread after a button was pushed.
|
||||
|
||||
After the push, it should 'keep' running for a desired time.
|
||||
|
||||
It should also provide us, a way to easily implement this
|
||||
controll multiple times, without trouble.
|
||||
|
||||
We are giving this Custom Thread the name 'ButtonThread'.
|
||||
|
||||
Exemplifying what it does:
|
||||
+ ButtonThread added to our mainController ThreadList
|
||||
=> Instantiated with a custom Pin #,
|
||||
=> and a time duration (in miliseconds)
|
||||
|
||||
+ ButtonThread is not running.
|
||||
|
||||
+ When the button is pressed:
|
||||
+ Thread will start and keep running.
|
||||
+ If the thread runned for our defined period,
|
||||
we stop it.
|
||||
|
||||
================ HOW TO SETUP HARDWARE ==================
|
||||
In order to make this example work with any arduino, hook up
|
||||
the pins on the board to 3 buttons. You can change the inputs
|
||||
if you need below here.
|
||||
|
||||
The Buttons are being SOFTWARE pulled UP (to VCC), and when
|
||||
pushed, should go LOW. Connect like this:
|
||||
(Arduino Input) <----> (Btn) <----> GND (-)
|
||||
|
||||
We are using digital pins 9, 10 and 11 as input.
|
||||
It also uses a LED, but we are using the default one in the board.
|
||||
|
||||
=============== WHAT YO LEARN WITH THIS =================
|
||||
1) Threads are actually running in 'parallel'.
|
||||
|
||||
Synce each thread process time is very tiny, they appear
|
||||
as being runned in parallel.
|
||||
|
||||
Because of that, clicking multiple buttons at any time,
|
||||
will looks like there is a program for each one of them.
|
||||
|
||||
2) If you keep the button 'pressed', it will continue to run.
|
||||
|
||||
Since we are 'enabling' the thread, and reseting the timer
|
||||
flag (_lastButtonPushed) every time the button is pressed,
|
||||
we should notice that in btn1Callback, where we print this
|
||||
flag, it will never go beyond 0 if we keep pressing it.
|
||||
|
||||
3) The LED turns off, only because the Thread runs a last time
|
||||
with the flag 'enabled' as false. This way, we can turn the
|
||||
LED off and remain OFF until we press it egain.
|
||||
|
||||
I hope you enjoy, and learn some advanced-cool stuf with this tutorial.
|
||||
Any feedback is apreciated!
|
||||
*/
|
||||
#define BTN1 9
|
||||
#define BTN2 10
|
||||
#define BTN3 11
|
||||
|
||||
#define LED 13
|
||||
|
||||
// ThreadController that will controll all button threads
|
||||
ThreadController controll = ThreadController();
|
||||
|
||||
// Here we implement our custom ButtonThread, that Inherits from Thread
|
||||
class ButtonThread: public Thread{
|
||||
public:
|
||||
// Our custom thread attributes
|
||||
int pin;
|
||||
long duration;
|
||||
long _lastButtonPushed;
|
||||
|
||||
/*
|
||||
Our Constructor. This will initialize the thread
|
||||
with it's corresponding pin and duration after clicked.
|
||||
*/
|
||||
ButtonThread(int _pin, long _duration): Thread(){
|
||||
// Set our attributes on construct
|
||||
pin = _pin;
|
||||
duration = _duration;
|
||||
_lastButtonPushed = 0;
|
||||
|
||||
// Thread will start disabled
|
||||
enabled = false;
|
||||
|
||||
// Configure the pin as INPUT and enable pull-up
|
||||
pinMode(pin, INPUT);
|
||||
digitalWrite(pin, HIGH);
|
||||
}
|
||||
|
||||
/*
|
||||
Override the method responsible for
|
||||
checking if the thread should run.
|
||||
|
||||
It will first check if the button is pressed.
|
||||
If so, we enable the thread, and then let the
|
||||
"Old" default Thread method 'shouldRun' return if
|
||||
it should run.
|
||||
*/
|
||||
bool shouldRun(long time){
|
||||
// Override enabled on thread when pin goes LOW.
|
||||
if(digitalRead(pin) == LOW){
|
||||
enabled = true;
|
||||
/*
|
||||
Here, we save the current time in this object,
|
||||
to compare it later.
|
||||
|
||||
the 'time' parameter in this method, is an override for the
|
||||
'millis()' method. It allows who is checking the thread, to
|
||||
pass a custom time.
|
||||
|
||||
This is sintax for writing an 'inline' if is very usefull,
|
||||
it's the same as:
|
||||
if(time > 0){
|
||||
_lastButtonPushed = time;
|
||||
}else{
|
||||
_lastButtonPushed = millis();
|
||||
}
|
||||
*/
|
||||
_lastButtonPushed = (time ? time : millis());
|
||||
}
|
||||
|
||||
// Let default method check for it.
|
||||
return Thread::shouldRun(time);
|
||||
}
|
||||
|
||||
/*
|
||||
We 'disable' the thread after the duration on the
|
||||
'run' method.
|
||||
|
||||
What we should do here, is check if the time saved
|
||||
in the _lastButtonPushed variable plus the duration,
|
||||
is greater than our current time. If that's true, it
|
||||
means we exceeded the thread time, and that we must
|
||||
disable it and prevent from running.
|
||||
*/
|
||||
void run(){
|
||||
// Check if time elapsed since last button push
|
||||
if(millis() > _lastButtonPushed + duration){
|
||||
// It exceeded time. We should disable it.
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
Run the thread.
|
||||
|
||||
Note that this method will only get called
|
||||
from the ThreadList, IF the 'shouldRun' returns true.
|
||||
|
||||
If the thread is not enabled anymore, it will run a 'last'
|
||||
time with the flag 'enabled' as false, meaning it's the last
|
||||
run in the period. You can use it for doing something only
|
||||
before it stops running.
|
||||
*/
|
||||
Thread::run();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
ButtonThreads objects instantiation
|
||||
(we are instantiating 2 as a member, and one
|
||||
as pointer in the setup, just to show you
|
||||
different ways of doing it)
|
||||
*/
|
||||
|
||||
// Thread 1 will be reading BTN1 pin, and will run for 3 secs
|
||||
ButtonThread btn1Thread(BTN1, 3000);
|
||||
|
||||
// Thread 2 will be reading BTN1 pin, and will run for 5 secs
|
||||
ButtonThread btn2Thread = ButtonThread(BTN2, 5000);
|
||||
|
||||
// Thread 3 will be instantiated in the setup()
|
||||
ButtonThread *btn3Thread;
|
||||
|
||||
|
||||
/*
|
||||
Callback for ButtonThreads
|
||||
*/
|
||||
void btn1Callback(){
|
||||
// When it's running, this thread will write to the serial.
|
||||
/*
|
||||
This math will print 'how long' the thread has been running,
|
||||
since the button was/is pressed.
|
||||
|
||||
After pressing it, it should print as 0, and goes up untill
|
||||
the thread duration (in this case, +-5000ms).
|
||||
*/
|
||||
Serial.print("BTN 1 Thread: ");
|
||||
Serial.println(millis() - btn1Thread._lastButtonPushed);
|
||||
}
|
||||
|
||||
void btn2Callback(){
|
||||
/*
|
||||
This thread will remain with the LED on pin 13 turned on
|
||||
while it is running.
|
||||
|
||||
We detect that this method is called for the LAST time, if
|
||||
the flag 'enabled' is FALSE on the btn2Thread object.
|
||||
|
||||
So, basically: If it's TRUE, we should turn ON the led, if not
|
||||
we should turn OFF. We can simplify that into one line.
|
||||
(Same 'inline' sintax as above)
|
||||
*/
|
||||
digitalWrite(LED, btn2Thread.enabled ? HIGH : LOW);
|
||||
}
|
||||
|
||||
void btn3Callback(){
|
||||
// When it's running, this thread will also write to the serial
|
||||
Serial.println("BTN 3 Thread");
|
||||
}
|
||||
|
||||
void setup(){
|
||||
// Configure serial and output pins
|
||||
Serial.begin(9600);
|
||||
pinMode(LED, OUTPUT);
|
||||
|
||||
// Configure btn1Thread callback
|
||||
// (During the 'enabled' time, it will run every 100ms, aka Interval)
|
||||
btn1Thread.onRun(btn1Callback);
|
||||
btn1Thread.setInterval(100);
|
||||
|
||||
// Configure btn2Thread callback and interval
|
||||
btn2Thread.onRun(btn2Callback);
|
||||
btn2Thread.setInterval(200);
|
||||
|
||||
// Instantiate btn3Thread
|
||||
btn3Thread = new ButtonThread(BTN3, 4000);
|
||||
// Configure btn3Thread callback and interval
|
||||
btn3Thread->onRun(btn3Callback);
|
||||
btn3Thread->setInterval(100);
|
||||
|
||||
// Adds all threads to the controller
|
||||
controll.add(&btn1Thread); // & to pass the pointer to it
|
||||
controll.add(&btn2Thread);
|
||||
controll.add(btn3Thread); // Its already a pointer, no need for &
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// Here we just run the main thread controller
|
||||
controll.run();
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
#include "Thread.h"
|
||||
#include "ThreadController.h"
|
||||
/*
|
||||
This is a more "complex" for of using Threads.
|
||||
You can also inherit from Thread, and do your entire code on the class.
|
||||
|
||||
This allows you, to create for example:
|
||||
Sensor Readings (aquire, filter, and save localy values)
|
||||
Custom Blinks, Beeps...
|
||||
Anything you can imagine.
|
||||
|
||||
Threads are more "usefull" when used within Timer interrupts
|
||||
|
||||
This way of coding is more "reusable", and "correct" (Object Oriented)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
This example, requires a Timer Interrupt Library.
|
||||
If you are using Arduino NANO, UNO... (with ATmega168/328)
|
||||
Please go to: http://playground.arduino.cc/code/timer1
|
||||
If you are using Arduino DUE,
|
||||
Please go to: https://github.com/ivanseidel/DueTimer
|
||||
|
||||
Include the library corresponding to your Arduino.
|
||||
*/
|
||||
#include <DueTimer.h>
|
||||
// #include <TimerOne.h>
|
||||
|
||||
// Create a new Class, called SensorThread, that inherits from Thread
|
||||
class SensorThread: public Thread
|
||||
{
|
||||
public:
|
||||
int value;
|
||||
int pin;
|
||||
|
||||
// No, "run" cannot be anything...
|
||||
// Because Thread uses the method "run" to run threads,
|
||||
// we MUST overload this method here. using anything other
|
||||
// than "run" will not work properly...
|
||||
void run(){
|
||||
// Reads the analog pin, and saves it localy
|
||||
value = map(analogRead(pin), 0,1023,0,255);
|
||||
runned();
|
||||
}
|
||||
};
|
||||
|
||||
// Now, let's use our new class of Thread
|
||||
SensorThread analog1 = SensorThread();
|
||||
SensorThread analog2 = SensorThread();
|
||||
|
||||
// Instantiate a new ThreadController
|
||||
ThreadController controller = ThreadController();
|
||||
|
||||
// This is the callback for the Timer
|
||||
void timerCallback(){
|
||||
controller.run();
|
||||
}
|
||||
|
||||
void setup(){
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
// Configures Thread analog1
|
||||
analog1.pin = A1;
|
||||
analog1.setInterval(100);
|
||||
|
||||
// Configures Thread analog2
|
||||
analog2.pin = A2;
|
||||
analog2.setInterval(100);
|
||||
|
||||
// Add the Threads to our ThreadController
|
||||
controller.add(&analog1);
|
||||
controller.add(&analog2);
|
||||
|
||||
/*
|
||||
If using DueTimer...
|
||||
*/
|
||||
Timer1.attachInterrupt(timerCallback).start(10000);
|
||||
|
||||
/*
|
||||
If using TimerOne...
|
||||
*/
|
||||
// Timer1.initialize(20000);
|
||||
// Timer1.attachInterrupt(timerCallback);
|
||||
// Timer1.start();
|
||||
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// Do complex-crazy-timeconsuming-tasks here
|
||||
delay(1000);
|
||||
|
||||
// Get the fresh readings
|
||||
Serial.print("Analog1 Thread: ");
|
||||
Serial.println(analog1.value);
|
||||
|
||||
Serial.print("Analog2 Thread: ");
|
||||
Serial.println(analog2.value);
|
||||
|
||||
// Do more complex-crazy-timeconsuming-tasks here
|
||||
delay(1000);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <Thread.h>
|
||||
int ledPin = 13;
|
||||
|
||||
//My simple Thread
|
||||
Thread myThread = Thread();
|
||||
|
||||
// callback for myThread
|
||||
void niceCallback(){
|
||||
static bool ledStatus = false;
|
||||
ledStatus = !ledStatus;
|
||||
|
||||
digitalWrite(ledPin, ledStatus);
|
||||
|
||||
Serial.print("COOL! I'm running on: ");
|
||||
Serial.println(millis());
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
pinMode(ledPin, OUTPUT);
|
||||
|
||||
myThread.onRun(niceCallback);
|
||||
myThread.setInterval(500);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// checks if thread should run
|
||||
if(myThread.shouldRun())
|
||||
myThread.run();
|
||||
|
||||
// Other code...
|
||||
int x = 0;
|
||||
x = 1 + 2;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include <Thread.h>
|
||||
#include <ThreadController.h>
|
||||
|
||||
// ThreadController that will controll all threads
|
||||
ThreadController controll = ThreadController();
|
||||
|
||||
//My Thread (as a pointer)
|
||||
Thread* myThread = new Thread();
|
||||
//His Thread (not pointer)
|
||||
Thread hisThread = Thread();
|
||||
|
||||
// callback for myThread
|
||||
void niceCallback(){
|
||||
Serial.print("COOL! I'm running on: ");
|
||||
Serial.println(millis());
|
||||
}
|
||||
|
||||
// callback for hisThread
|
||||
void boringCallback(){
|
||||
Serial.println("BORING...");
|
||||
}
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
// Configure myThread
|
||||
myThread->onRun(niceCallback);
|
||||
myThread->setInterval(500);
|
||||
|
||||
// Configure myThread
|
||||
hisThread.onRun(boringCallback);
|
||||
hisThread.setInterval(250);
|
||||
|
||||
// Adds both threads to the controller
|
||||
controll.add(myThread);
|
||||
controll.add(&hisThread); // & to pass the pointer to it
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// run ThreadController
|
||||
// this will check every thread inside ThreadController,
|
||||
// if it should run. If yes, he will run it;
|
||||
controll.run();
|
||||
|
||||
// Rest of code
|
||||
float h = 3.1415;
|
||||
h/=2;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <Thread.h>
|
||||
#include <StaticThreadController.h>
|
||||
|
||||
//My Thread (as a pointer)
|
||||
Thread* myThread = new Thread();
|
||||
//His Thread (not pointer)
|
||||
Thread hisThread = Thread();
|
||||
|
||||
// callback for myThread
|
||||
void niceCallback(){
|
||||
Serial.print("COOL! I'm running on: ");
|
||||
Serial.println(millis());
|
||||
}
|
||||
|
||||
// callback for hisThread
|
||||
void boringCallback(){
|
||||
Serial.println("BORING...");
|
||||
}
|
||||
|
||||
// callback for theThread
|
||||
void justCallback(){
|
||||
Serial.println("executing...");
|
||||
}
|
||||
|
||||
//The Thread (as a pointer) with justCallback initialized
|
||||
Thread* theThread = new Thread(justCallback);
|
||||
|
||||
// StaticThreadController that will controll all threads
|
||||
// All non-pointers go with '&', but pointers go without '&',
|
||||
StaticThreadController<3> controll (myThread, &hisThread, theThread);
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
|
||||
// Configure myThread
|
||||
myThread->onRun(niceCallback);
|
||||
myThread->setInterval(500);
|
||||
|
||||
// Configure hisThread
|
||||
hisThread.onRun(boringCallback);
|
||||
hisThread.setInterval(250);
|
||||
|
||||
// Set interval for theThread using StaticThreadController interface
|
||||
controll[3].setInterval(375);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// run StaticThreadController
|
||||
// this will check every thread inside ThreadController,
|
||||
// if it should run. If yes, he will run it;
|
||||
controll.run();
|
||||
|
||||
// Rest of code
|
||||
float h = 3.1415;
|
||||
h/=2;
|
||||
}
|
||||
32
firmware_adxl345_spi/lib/ArduinoThread/keywords.txt
Normal file
32
firmware_adxl345_spi/lib/ArduinoThread/keywords.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
#######################################
|
||||
# Syntax Coloring
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Thread KEYWORD1
|
||||
ThreadController KEYWORD1
|
||||
StaticThreadController KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
runned KEYWORD2
|
||||
setInterval KEYWORD2
|
||||
shouldRun KEYWORD2
|
||||
onRun KEYWORD2
|
||||
run KEYWORD2
|
||||
|
||||
# Specific of ThreadController or StaticThreadController
|
||||
add KEYWORD2
|
||||
remove KEYWORD2
|
||||
clear KEYWORD2
|
||||
size KEYWORD2
|
||||
get KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
13
firmware_adxl345_spi/lib/ArduinoThread/library.json
Normal file
13
firmware_adxl345_spi/lib/ArduinoThread/library.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "ArduinoThread",
|
||||
"keywords": "thread, task",
|
||||
"description": "A library for managing the periodic execution of multiple tasks",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ivanseidel/ArduinoThread.git"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
//"platforms": "atmelavr", LK 2025
|
||||
"platforms": "*"
|
||||
"version": "2.1.1"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=ArduinoThread
|
||||
version=2.1.1
|
||||
author=Ivan Seidel <ivanseidel@gmail.com>
|
||||
maintainer=Ivan Seidel <ivanseidel@gmail.com>
|
||||
sentence=A simple way to run Threads on Arduino
|
||||
paragraph=This Library helps to maintain organized and to facilitate the use of multiple tasks. We can use Timers Interrupts, and make it really powerfull, running "pseudo-background" tasks on the rug.
|
||||
category=Timing
|
||||
url=https://github.com/ivanseidel/ArduinoThread
|
||||
architectures=*
|
||||
22
firmware_adxl345_spi/lib/LiquidCrystal_I2C/LICENSE
Normal file
22
firmware_adxl345_spi/lib/LiquidCrystal_I2C/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2016 Libor Gabaj
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
858
firmware_adxl345_spi/lib/LiquidCrystal_I2C/README.md
Normal file
858
firmware_adxl345_spi/lib/LiquidCrystal_I2C/README.md
Normal file
@@ -0,0 +1,858 @@
|
||||
<a id="library"></a>
|
||||
# LiquidCrystal_I2C
|
||||
It is the reimplementation of the standard Arduino LCD library, configured to work with parallel HD44780 compatible LCDs, and interfaced via a Chinese PCF8574 I2C serial extender.
|
||||
|
||||
|
||||
<a id="credit"></a>
|
||||
## Credit
|
||||
The reimplementation has been inspired by and credit goes to:
|
||||
|
||||
- Mario H. atmega@xs4all.nl LiquidCrystal_I2C V2.0
|
||||
- Murray R. Van Luyn vanluynm@iinet.net.au Mods for Chinese I2C converter board
|
||||
|
||||
|
||||
<a id="dependency"></a>
|
||||
## Dependency
|
||||
The library class extends the system library *Print* and includes following sytem header files.
|
||||
|
||||
- **inttypes.h**: Integer type conversions. This header file includes the exact-width integer definitions and extends them with additional facilities provided by the implementation.
|
||||
- **Print.h**: Base class that provides *print()* and *println()*.
|
||||
- **Wire.h**: TWI/I2C library for Arduino & Wiring.
|
||||
|
||||
|
||||
<a id="interface"></a>
|
||||
## Interface
|
||||
Some of listed functions come out of Arduino [LCD API 1.0](http://playground.arduino.cc/Code/LCDAPI), some of them are specific for this library. It is possible to use functions from the system library [Print](#dependency), which is extended by the *LiquidCrystal_I2C*.
|
||||
|
||||
*) The function is an alias of another (usually previous) one.
|
||||
|
||||
##### Initialization
|
||||
- [LiquidCrystal_I2C()](#LiquidCrystal_I2C)
|
||||
- [begin()](#begin)
|
||||
- [init()](#init)
|
||||
- [clear()](#clear)
|
||||
- [home()](#home)
|
||||
|
||||
##### Printing
|
||||
- [print()](#print)
|
||||
- [write()](#write)
|
||||
|
||||
##### Display control
|
||||
- [noDisplay()](#noDisplay)
|
||||
- *[off()](#noDisplay)
|
||||
- [display()](#display)
|
||||
- *[on()](#display)
|
||||
- [scrollDisplayLeft()](#scrollDisplayLeft)
|
||||
- [scrollDisplayRight()](#scrollDisplayRight)
|
||||
- [leftToRight()](#leftToRight)
|
||||
- [rightToLeft()](#rightToLeft)
|
||||
- [noAutoscroll()](#noAutoscroll)
|
||||
- [autoscroll()](#autoscroll)
|
||||
- [noBacklight()](#noBacklight)
|
||||
- [backlight()](#backlight)
|
||||
- *[setBacklight()](#backlight)
|
||||
|
||||
##### Cursor manipulation
|
||||
- [noCursor()](#noCursor)
|
||||
- *[cursor_off()](#noCursor)
|
||||
- [cursor()](#cursor)
|
||||
- *[cursor_on()](#cursor)
|
||||
- [noBlink()](#noBlink)
|
||||
- *[blink_off()](#noBlink)
|
||||
- [blink()](#blink)
|
||||
- *[blink_on()](#blink)
|
||||
- [setCursor()](#setCursor)
|
||||
|
||||
##### Graphs
|
||||
- [init_bargraph()](#init_bargraph)
|
||||
- [draw_horizontal_graph()](#draw_horizontal_graph)
|
||||
- [draw_vertical_graph()](#draw_vertical_graph)
|
||||
|
||||
##### Utilities
|
||||
- [createChar()](#createChar)
|
||||
- *[load_custom_character()](#createChar)
|
||||
- [command()](#command)
|
||||
|
||||
|
||||
<a id="LiquidCrystal_I2C"></a>
|
||||
## LiquidCrystal_I2C()
|
||||
#### Description
|
||||
Constructor of the object controlling an LCD. It defines address of the LCD and its geometry.
|
||||
|
||||
- More LCDs can be connected to the same I2C bus if they are hardware configured for different addresses.
|
||||
- For each of LCDs the separate object has to be created.
|
||||
- When the display powers up, it is configured as follows:
|
||||
|
||||
1. Display clear
|
||||
1. Function set:
|
||||
- DL = 1; 8-bit interface data
|
||||
- N = 0; 1-line display
|
||||
- F = 0; 5x8 dot character font
|
||||
1. Display on/off control:
|
||||
- D = 0; Display off
|
||||
- C = 0; Cursor off
|
||||
- B = 0; Blinking off
|
||||
1. Entry mode set:
|
||||
- I/D = 1; Increment by 1
|
||||
- S = 0; No shift
|
||||
|
||||
- Note, however, that resetting the Arduino does not reset the LCD, so we cannot assume that it is in that state when a sketch starts (and the constructor is called).
|
||||
|
||||
#### Syntax
|
||||
LiquidCrystal_I2C(uint8_t addr, uint8_t cols, uint8_t rows);
|
||||
|
||||
#### Parameters
|
||||
- **addr**: I2C addres of the LCD predefined by the serial extender.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
- *Usual values*:
|
||||
- **0x3F** for LCDs *2004* with 20 columns and 4 rows.
|
||||
- **0x27** for LCDs *1602* with 16 columns and 2 rows.
|
||||
|
||||
|
||||
<a id="prm_cols"></a>
|
||||
- **cols**: Number of characters in a row defined by the hardware construction of the LCD screen.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
- *Usual values*: 20, 16, 8
|
||||
|
||||
|
||||
<a id="prm_rows"></a>
|
||||
- **rows**: Number of rows in the LCD screen defined by the hardware construction of the LCD.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
- *Usual values*: 4, 2, 1
|
||||
|
||||
#### Returns
|
||||
- **LCD object**: Object controlling the LCD communicating at defined address.
|
||||
|
||||
#### Example
|
||||
|
||||
``` cpp
|
||||
lcd = LiquidCrystal_I2C(0x27, 16, 2);
|
||||
```
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="begin"></a>
|
||||
## begin()
|
||||
#### Description
|
||||
Initialize the LCD with its specific geometry parameters.
|
||||
|
||||
#### Syntax
|
||||
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
|
||||
|
||||
#### Parameters
|
||||
- **cols**: Number of characters in a row defined by the hardware construction of the LCD screen.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
- *Usual values*: 20, 16, 8
|
||||
|
||||
|
||||
- **rows**: Number of rows in the LCD screen defined by the hardware construction of the LCD.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
- *Usual values*: 4, 2, 1
|
||||
|
||||
|
||||
- **charsize**: Geometry of the LCD's character defined by a library constant.
|
||||
- *Valid values*: unsigned byte LCD_5x8DOTS, LCD_5x10DOT
|
||||
- *Default value*: LCD_5x8DOTS
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[LiquidCrystal_I2C()](#LiquidCrystal_I2C)
|
||||
|
||||
[init()](#init)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="init"></a>
|
||||
## init()
|
||||
#### Description
|
||||
Initializes the display with values put to the [constructor](LiquidCrystal_I2C), clears the screen, and puts cursor to the upper left corner of the screen, i.e., to the home position 0,0. It is a wrapper function for function [begin()](#begin) with forgoing initialization of [Wire](#dependecy) library.
|
||||
|
||||
#### Syntax
|
||||
void init();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[LiquidCrystal_I2C()](#LiquidCrystal_I2C)
|
||||
|
||||
[begin()](#begin)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="clear"></a>
|
||||
## clear()
|
||||
#### Description
|
||||
Overloaded function for clearing the entire LCD screen or just a part of a row.
|
||||
- Using the function without any parameters clears the entire srceen.
|
||||
- For clearing the entire row use the function just with the first parameter.
|
||||
- The functions sets the cursor to the start column and row after clearing, i.e., after calling without parameters to the home position (0, 0), or after calling with parameters to the starts of cleared row segment.
|
||||
|
||||
#### Syntax
|
||||
void clear();
|
||||
void clear(uint8_t rowStart, uint8_t colStart = 0, uint8_t colCnt = 255);
|
||||
|
||||
#### Parameters
|
||||
- **rowStart**: Number of a row to be cleared counting from 0.
|
||||
- *Valid values*: unsigned byte 0 to [rows - 1](#prm_rows) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **colStart**: Order number of the first character in a cleared row counting from 0, which the cleared segment starts from.
|
||||
- *Valid values*: unsigned byte 0 to [cols - 1](#prm_cols) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: 0 (start of a row)
|
||||
|
||||
|
||||
- **colCnt**: Number of cleared characters in a cleard row.
|
||||
- *Valid values*: unsigned byte 0 to [cols](#prm_cols) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: 255, but internally limited to (*cols* - *colStart*)
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[LiquidCrystal_I2C()](#LiquidCrystal_I2C)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="home"></a>
|
||||
## home()
|
||||
#### Description
|
||||
Places the cursor to the home position (0, 0) and leaves displayed characters.
|
||||
|
||||
#### Syntax
|
||||
void init();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[LiquidCrystal_I2C()](#LiquidCrystal_I2C)
|
||||
|
||||
[clear()](#clear)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="print"></a>
|
||||
## print()
|
||||
#### Description
|
||||
Prints text or number to the LCD. It is inhereted function from the parent system one. The function is overloaded and acts according the data type of the input data to be printed.
|
||||
|
||||
#### Syntax
|
||||
byte print(char|byte|int|long|string data, int base);
|
||||
|
||||
#### Parameters
|
||||
- **data**: String or number that should be printed on the LCD from current cursor position.
|
||||
- *Valid values*: arbitrary
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **base**: Optional base in which to print numbers.
|
||||
- *Valid values*: integer in form of preprocesor constants
|
||||
- BIN: binary base 2
|
||||
- DEC: decimal base 10
|
||||
- OCT: octal base 8
|
||||
- HEX hexadecimal base 16
|
||||
- *Default value*: string
|
||||
|
||||
#### Returns
|
||||
- **ProcessBytes**: Number of successfully printed bytes.
|
||||
|
||||
#### Example
|
||||
|
||||
``` cpp
|
||||
lcd = LiquidCrystal_I2C(0x27, 16, 2);
|
||||
void setup()
|
||||
{
|
||||
lcd.print("Hello, world!");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(128, HEX);
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
```
|
||||
>Hello, world!
|
||||
>80
|
||||
|
||||
|
||||
#### See also
|
||||
[write()](#write)
|
||||
|
||||
[setCursor()](#setCursor)
|
||||
|
||||
[LiquidCrystal_I2C()](#LiquidCrystal_I2C)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="write"></a>
|
||||
## write()
|
||||
#### Description
|
||||
Writes a raw value to the display.
|
||||
|
||||
#### Syntax
|
||||
size_t write(uint8_t value);
|
||||
|
||||
#### Parameters
|
||||
- **value**: Value that should be write to the LCD at address set before.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
|
||||
#### Returns
|
||||
- **ProcessBytes**: Number of successfully processed bytes; always 1.
|
||||
|
||||
#### See also
|
||||
[print()](#print)
|
||||
|
||||
[command()](#command)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="noDisplay"></a>
|
||||
## noDisplay()
|
||||
#### Description
|
||||
Turns the display off quickly. If the display does not have an option to turn on the display, the function just turns backlight on.
|
||||
|
||||
#### Syntax
|
||||
void noDisplay();
|
||||
|
||||
#### Alias
|
||||
void off();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[display()](#display)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="display"></a>
|
||||
## display()
|
||||
#### Description
|
||||
Turns the display on quickly. If the display does not have an option to turn off the display, the function just turns backlight off.
|
||||
|
||||
#### Syntax
|
||||
void display();
|
||||
|
||||
#### Alias
|
||||
void on();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[noDisplay()](#noDisplay)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="scrollDisplayLeft"></a>
|
||||
## scrollDisplayLeft()
|
||||
#### Description
|
||||
Scrolls the display text to the left without changing the RAM. The function scrolls entire 40 character buffer. If you print 40 characters to a row and start scrolling, you get continuous moving banner in a row especially on 1602 LCDs.
|
||||
|
||||
#### Syntax
|
||||
void scrollDisplayLeft();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[scrollDisplayRight()](#scrollDisplayRight)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="scrollDisplayRight"></a>
|
||||
## scrollDisplayRight()
|
||||
#### Description
|
||||
Scrolls the display text to the right without changing the RAM. The function scrolls entire 40 character buffer. If you print 40 characters to a row and start scrolling, you get continuous moving banner in a row especially on 1602 LCDs.
|
||||
|
||||
#### Syntax
|
||||
void scrollDisplayRight();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[scrollDisplayLeft()](#scrollDisplayLeft)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="leftToRight"></a>
|
||||
## leftToRight()
|
||||
#### Description
|
||||
Sets the flow of text from left to right as it is normal for Latin languages.
|
||||
|
||||
#### Syntax
|
||||
void leftToRight();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[rightToLeft()](#rightToLeft)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="rightToLeft"></a>
|
||||
## rightToLeft()
|
||||
#### Description
|
||||
Sets the flow of text from right to left as it is normal for Arabic languages.
|
||||
|
||||
#### Syntax
|
||||
void rightToLeft();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[leftToRight()](#leftToRight)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="noAutoscroll"></a>
|
||||
## noAutoscroll()
|
||||
#### Description
|
||||
Justifies the text from the cursor to the left.
|
||||
|
||||
#### Syntax
|
||||
void noAutoscroll();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[autoscroll()](#autoscroll)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="autoscroll"></a>
|
||||
## autoscroll()
|
||||
#### Description
|
||||
Justifies the text from the cursor to the right.
|
||||
|
||||
#### Syntax
|
||||
void autoscroll();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[noAutoscroll()](#noAutoscroll)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="noBacklight"></a>
|
||||
## noBacklight()
|
||||
#### Description
|
||||
Turns the backlight off.
|
||||
|
||||
#### Syntax
|
||||
void noBacklight();
|
||||
|
||||
#### Alias
|
||||
void setBacklight(0);
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[backlight()](#backlight)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="backlight"></a>
|
||||
## backlight()
|
||||
#### Description
|
||||
Turns the backlight on.
|
||||
|
||||
#### Syntax
|
||||
void backlight();
|
||||
|
||||
#### Alias
|
||||
void setBacklight(1);
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[noBacklight()](#noBacklight)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="noCursor"></a>
|
||||
## noCursor()
|
||||
#### Description
|
||||
Turns the block cursor off.
|
||||
|
||||
#### Syntax
|
||||
void noCursor();
|
||||
|
||||
#### Alias
|
||||
void cursor_off();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[cursor()](#cursor)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="cursor"></a>
|
||||
## cursor()
|
||||
#### Description
|
||||
Turns the block cursor on.
|
||||
|
||||
#### Syntax
|
||||
void cursor();
|
||||
|
||||
#### Alias
|
||||
void cursor_on();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[noCursor()](#noCursor)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="noBlink"></a>
|
||||
## noBlink()
|
||||
#### Description
|
||||
Turns on the blinking underline cursor.
|
||||
|
||||
#### Syntax
|
||||
void noBlink();
|
||||
|
||||
#### Alias
|
||||
void blink_off();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[blink()](#blink)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="blink"></a>
|
||||
## blink()
|
||||
#### Description
|
||||
Turns off the blinking underline cursor.
|
||||
|
||||
#### Syntax
|
||||
void blink();
|
||||
|
||||
#### Alias
|
||||
void blink_on();
|
||||
|
||||
#### Parameters
|
||||
None
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[noBlink()](#noBlink)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="setCursor"></a>
|
||||
## setCursor()
|
||||
#### Description
|
||||
Fills the first 8 character generator RAM (CGRAM) locations with custom characters.
|
||||
|
||||
#### Syntax
|
||||
void setCursor(uint8_t col, uint8_t row);
|
||||
|
||||
#### Parameters
|
||||
- **col**: Number of a column where the cursor will be located counting from 0.
|
||||
- *Valid values*: unsigned byte 0 to [cols - 1](#prm_cols) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **row**: Number of a row where the cursor will be located counting from 0.
|
||||
- *Valid values*: unsigned byte 0 to [rows - 1](#prm_rows) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[home()](#home)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="init_bargraph"></a>
|
||||
## init_bargraph()
|
||||
#### Description
|
||||
Initializes particular bar graph. The function creates a set of custom
|
||||
characters for displaying bar graphs. Some number of first current custom
|
||||
characters (5 or 8) will be overwritten according to the type of graph.
|
||||
|
||||
#### Syntax
|
||||
uint8_t init_bargraph(uint8_t graphtype);
|
||||
|
||||
#### Parameters
|
||||
- **graphtype**: Type of a graph.
|
||||
- *Valid values*: unsigned integer
|
||||
- LCDI2C_VERTICAL_BAR_GRAPH - rewrites all 8 custom characters
|
||||
- LCDI2C_HORIZONTAL_BAR_GRAPH - rewrites first 5 custom characters
|
||||
- LCDI2C_HORIZONTAL_LINE_GRAPH - rewrites first 5 custom characters
|
||||
- *Default value*: none
|
||||
|
||||
#### Returns
|
||||
- **ResultCode**: Numeric code determining processing of the initialization.
|
||||
- 0: success
|
||||
- 1: failure, e.g., not recognized graph type
|
||||
|
||||
#### See also
|
||||
[draw_horizontal_graph()](#draw_horizontal_graph)
|
||||
|
||||
[draw_vertical_graph()](#draw_vertical_graph)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="draw_horizontal_graph"></a>
|
||||
## draw_horizontal_graph()
|
||||
#### Description
|
||||
Displays horizontal graph from desired cursor position with input value.
|
||||
- The bar graph is composed of solid, full rectangle characters eventually except final character with reduced vertical pipes. Value of the bar graph is displayed as equivalent number of pipes in the graph segment.
|
||||
- The line graph is composed of one pipe running across a LCD row. Value
|
||||
of the bar graph is displayed as a pipe at equivalent dot position in the graph segment.
|
||||
- The function is overloaded by data type of a displayed graph value, which
|
||||
determines its form.
|
||||
- Zero value of the graph is displayed as the very left pipe in the graph segment due to counting from 0, so that the graph always displays something.
|
||||
|
||||
#### Syntax
|
||||
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
|
||||
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint16_t percentage);
|
||||
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, float ratio);
|
||||
|
||||
#### Parameters
|
||||
- **row**: Row positon of graph segment counting from 0 to physical number of rows.
|
||||
- *Valid values*: non-negative integer 0 to [rows - 1](#prm_rows) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **col**: Column position of graph segment counting from 0 physical number of columns on a row.
|
||||
- *Valid values*: non-negative integer 0 to [cols - 1](#prm_cols) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **len**: Length of a graph segment in characters limited to remaining physical columns from starting *col* position.
|
||||
- *Valid values*: non-negative integer 0 to [cols - col](#prm_cols) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **pixel_col_end**: Displayed value in pipes (horizontal dots) counting from 0 to number of pipes of the graph segment. A sketch should calculate the number of segment pipes in order to map an application value to displayed value.
|
||||
- *Valid values*: non-negative integer 0 to 5 * *len*
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **percentage**: Displayed value in percentage of a graph segment length. Accepted value is rounded to integer per cents.
|
||||
- *Valid values*: non-negative integer 0 to 100
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **ratio**: Displayed value as a fragment of a graph segment length.
|
||||
- *Valid values*: non-negative decimal 0. to 1.
|
||||
- *Default value*: none
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[init_bargraph()](#init_bargraph)
|
||||
|
||||
[draw_vertical_graph()](#draw_vertical_graph)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="draw_vertical_graph"></a>
|
||||
## draw_vertical_graph()
|
||||
#### Description
|
||||
Displays vertical bar from desired cursor position with input value.
|
||||
- The bar graph is composed of solid, full rectangle characters eventually except final character with reduced horizontal dashes. Value of the bar graph is displayed as equivalent number of dashes in the graph segment.
|
||||
- The function is overloaded by data type of a displayed graph value, which
|
||||
determines its form.
|
||||
|
||||
#### Syntax
|
||||
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end);
|
||||
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint16_t percentage);
|
||||
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, float ratio);
|
||||
|
||||
#### Parameters
|
||||
- **row**: Row positon of graph segment counting from 0 to physical limit.
|
||||
- *Valid values*: non-negative integer 0 to [rows - 1](#prm_rows) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **col**: Column position of graph segment counting from 0 physical limit.
|
||||
- *Valid values*: non-negative integer 0 to [cols - 1](#prm_cols) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **len**: Length of a graph segment in rows limited to remaining physical rows from starting *row* position.
|
||||
- *Valid values*: non-negative integer 0 to [row + 1](#prm_rows) of the [constructor](#LiquidCrystal_I2C)
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **pixel_col_end**: Displayed value in dashes (vertical dots) counting from 0 to number of dashes of the graph segment. A sketch should calculate the number of segment dashes in order to map an application value to displayed value.
|
||||
- *Valid values*: non-negative integer 0 to 8 * *len* or 10 * *len*
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **percentage**: Displayed value in percentage of a graph segment length. Accepted value is rounded to integer per cents.
|
||||
- *Valid values*: non-negative integer 0 to 100
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **ratio**: Displayed value as a fragment of a graph segment length.
|
||||
- *Valid values*: non-negative decimal 0. to 1.
|
||||
- *Default value*: none
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[init_bargraph()](#init_bargraph)
|
||||
|
||||
[draw_horizontal_graph()](#draw_horizontal_graph)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="createChar"></a>
|
||||
## createChar()
|
||||
#### Description
|
||||
Fills the first 8 character generator RAM (CGRAM) locations with custom characters.
|
||||
|
||||
#### Syntax
|
||||
void createChar(uint8_t, uint8_t[]);
|
||||
|
||||
#### Alias
|
||||
void load_custom_character(uint8_t char_num, uint8_t *rows);
|
||||
|
||||
#### Parameters
|
||||
- **char_num**: Position of a custom character in CGRAM for custom chars.
|
||||
- *Valid values*: 0 - 7
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **uint8_t[]**: Array of custom characters definitions.
|
||||
- *Valid values*: Character row byte patterns from the top of the char.
|
||||
- Array length 8 bytes for 5x8 characters.
|
||||
- Array length 10 bytes for 5x10 characters.
|
||||
- *Default value*: none
|
||||
|
||||
|
||||
- **rows**: Pointer to the array of custom characters definitions.
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[init_bargraph()](#init_bargraph)
|
||||
|
||||
[Back to interface](#interface)
|
||||
|
||||
|
||||
<a id="command"></a>
|
||||
## command()
|
||||
#### Description
|
||||
Sends a command to the display. It is useful for commands not supported
|
||||
by the library.
|
||||
|
||||
#### Syntax
|
||||
void command(uint8_t value);
|
||||
|
||||
#### Parameters
|
||||
- **value**: Command code that should be send to the LCD.
|
||||
- *Valid values*: unsigned byte
|
||||
- *Default value*: none
|
||||
|
||||
#### Returns
|
||||
None
|
||||
|
||||
#### See also
|
||||
[write()](#write)
|
||||
|
||||
[Back to interface](#interface)
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
NAME:
|
||||
Demonstration of Autoscroll function
|
||||
|
||||
DESCRIPTION:
|
||||
This sketch demonstrates the use of the autoscroll() and noAutoscroll()
|
||||
functions to make new text scroll or not.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.0.0
|
||||
Updated: 20.03.2016
|
||||
|
||||
CREDIT:
|
||||
The example taken and rewritten for I2C from official Arduino standard library
|
||||
(https://github.com/arduino/Arduino/tree/master/libraries/LiquidCrystal)
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry and library initialization
|
||||
const byte lcdAddr = 0x27; // Address of I2C backpack
|
||||
const byte lcdCols = 16; // Number of character in a row
|
||||
const byte lcdRows = 2; // Number of lines
|
||||
//const byte lcdAddr = 0x3F; // Address of I2C backpack
|
||||
//const byte lcdCols = 20; // Number of character in a row
|
||||
//const byte lcdRows = 4; // Number of lines
|
||||
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Demo parameters
|
||||
const byte lcdScrollRow = 0; // Number of a demo row counting from 0
|
||||
const unsigned int digitDelay = 500; // Miliseconds before displaying next digit
|
||||
|
||||
// Function for displaying demo digits
|
||||
void printDigits() {
|
||||
for (byte thisChar = 0; thisChar < 10; thisChar++) {
|
||||
lcd.print(thisChar);
|
||||
delay(digitDelay);
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
lcd.init();
|
||||
lcd.backlight();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
lcd.setCursor(0, lcdScrollRow);
|
||||
printDigits();
|
||||
|
||||
// Set the cursor to the last column of the demo row and turn on autoscroll
|
||||
lcd.setCursor(lcdCols, lcdScrollRow);
|
||||
lcd.autoscroll();
|
||||
printDigits();
|
||||
lcd.noAutoscroll();
|
||||
lcd.clear();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
NAME:
|
||||
Demo sketch for complete printing test of LCD
|
||||
|
||||
DESCRIPTION:
|
||||
The sketch demonstrates capabalities of the LCD by displaying several
|
||||
test.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDITS:
|
||||
Inspired by the example LCD_Test in the library LCDi2cW
|
||||
from "4-2-2009 dale@wentztech.com".
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.1.0
|
||||
Updated: 04.03.2015
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry for LCD 1602
|
||||
const byte lcdAddr = 0x27; // Typical address of I2C backpack for 1602
|
||||
const byte lcdCols = 16; // Number of characters in a row of display
|
||||
const byte lcdRows = 2; // Number of lines of display
|
||||
|
||||
// LCD address and geometry for LCD 2004
|
||||
//const byte lcdAddr = 0x3F; // Typical address of I2C backpack for 2004
|
||||
//const byte lcdCols = 20; // Number of characters in a row of display
|
||||
//const byte lcdRows = 4; // Number of lines of display
|
||||
|
||||
// Initialize library and setting LCD geometry
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Demo constants
|
||||
const int testDelay = 500; // Delay between tests in ms
|
||||
const int demoDelay = 3000; // Delay between demos in ms
|
||||
const byte demoNumMin = 1; // Range of demo tests
|
||||
const byte demoNumMax = 255;
|
||||
const byte charNumMin = 0; // Code of first displayed character
|
||||
const byte charNumMax = 255; // Code of last displayed character
|
||||
|
||||
// Demo variables
|
||||
byte col, row;
|
||||
unsigned int demoNum, charNum;
|
||||
char buffer[lcdCols + 1];
|
||||
|
||||
void setup() {
|
||||
// Initialize LCD
|
||||
lcd.init();
|
||||
lcd.backlight(); // Switch on the backlight LED, if any or wired
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
demoNum = max(demoNumMin, 1);
|
||||
while(demoNum >= demoNumMin && demoNum <= demoNumMax) {
|
||||
lcd.clear();
|
||||
lcd.cursor_off();
|
||||
lcd.blink_off();
|
||||
sprintf(buffer, "%u.", demoNum);
|
||||
lcd.print(buffer);
|
||||
|
||||
switch (demoNum) {
|
||||
case 1:
|
||||
lcd.print(F("Hello World!"));
|
||||
break;
|
||||
case 2:
|
||||
lcd.print(F("Dash Cursor"));
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.cursor_on();
|
||||
break;
|
||||
case 3:
|
||||
lcd.print (F("Block Cursor"));
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.blink_on();
|
||||
break;
|
||||
case 4:
|
||||
lcd.print(F("No Cursor"));
|
||||
lcd.setCursor(0, 1);
|
||||
break;
|
||||
case 5:
|
||||
lcd.print(F("Characters"));
|
||||
lcd.cursor_on();
|
||||
charNum = charNumMin;
|
||||
while(charNum <= charNumMax) {
|
||||
row = 1;
|
||||
do {
|
||||
lcd.clear(row);
|
||||
col = 0;
|
||||
lcd.setCursor(col, row);
|
||||
do {
|
||||
lcd.write(char(charNum++));
|
||||
delay(testDelay);
|
||||
} while(++col < lcdCols && charNum <= charNumMax);
|
||||
} while(++row < lcdRows && charNum <= charNumMax);
|
||||
}
|
||||
lcd.cursor_off();
|
||||
break;
|
||||
case 6:
|
||||
for (byte row=0; row < lcdRows; row++) {
|
||||
lcd.print(F("Line "));
|
||||
lcd.print(row);
|
||||
delay(testDelay);
|
||||
lcd.setCursor(0, row + 1);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
lcd.print(F("Count to 255"));
|
||||
for (unsigned int i = 0; i < 256; i++) {
|
||||
lcd.clear(1);
|
||||
sprintf(buffer, "%03u 0x%02X %c", i, i, i);
|
||||
lcd.print(buffer);
|
||||
if (lcdCols >= 20) {
|
||||
lcd.print(" B");
|
||||
lcd.print(i, BIN);
|
||||
}
|
||||
delay(testDelay);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
lcd.print(F("Positions"));
|
||||
lcd.setCursor(0, 1);
|
||||
for (byte col = 0; col < lcdCols; col++) {
|
||||
lcd.write(col%10 + char('0'));
|
||||
delay(testDelay);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
lcd.print(F("Clearing"));
|
||||
for (byte row = 1; row < lcdRows; row++) {
|
||||
// Fill row
|
||||
lcd.setCursor(0, row);
|
||||
for (byte col = 0; col < lcdCols; col++) {
|
||||
lcd.write(col%10 + char('0'));
|
||||
}
|
||||
delay(testDelay);
|
||||
// Clear row
|
||||
for (byte i = 0; i < lcdCols / 2; i++) {
|
||||
lcd.setCursor(lcdCols / 2 - i - 1, row);
|
||||
lcd.write(' ');
|
||||
lcd.setCursor(lcdCols / 2 + i, row);
|
||||
lcd.write(' ');
|
||||
delay(testDelay);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
demoNum = 0;
|
||||
continue;
|
||||
}
|
||||
delay(demoDelay);
|
||||
demoNum++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
|
||||
uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
|
||||
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
|
||||
uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
|
||||
uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
|
||||
uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
|
||||
uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
|
||||
uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
|
||||
|
||||
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
|
||||
|
||||
void setup()
|
||||
{
|
||||
lcd.init(); // initialize the lcd
|
||||
lcd.backlight();
|
||||
|
||||
lcd.createChar(0, bell);
|
||||
lcd.createChar(1, note);
|
||||
lcd.createChar(2, clock);
|
||||
lcd.createChar(3, heart);
|
||||
lcd.createChar(4, duck);
|
||||
lcd.createChar(5, check);
|
||||
lcd.createChar(6, cross);
|
||||
lcd.createChar(7, retarrow);
|
||||
lcd.home();
|
||||
|
||||
lcd.print("Hello world...");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(" i ");
|
||||
lcd.write(3);
|
||||
lcd.print(" arduinos!");
|
||||
delay(5000);
|
||||
displayKeyCodes();
|
||||
|
||||
}
|
||||
|
||||
// display all keycodes
|
||||
void displayKeyCodes(void) {
|
||||
uint8_t i = 0;
|
||||
while (1) {
|
||||
lcd.clear();
|
||||
lcd.print("Codes 0x"); lcd.print(i, HEX);
|
||||
lcd.print("-0x"); lcd.print(i+16, HEX);
|
||||
lcd.setCursor(0, 1);
|
||||
for (int j=0; j<16; j++) {
|
||||
lcd.write(i+j);
|
||||
}
|
||||
i+=16;
|
||||
|
||||
delay(4000);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 20 chars and 4 line display
|
||||
|
||||
void setup()
|
||||
{
|
||||
lcd.init(); // initialize the lcd
|
||||
|
||||
// Print a message to the LCD.
|
||||
lcd.backlight();
|
||||
lcd.print("Hello, world!");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
NAME:
|
||||
Demo sketch for Histogram composed of Vertical Bar Graphs
|
||||
|
||||
DESCRIPTION:
|
||||
The sketch demonstrates usage of LiquidCrystal_I2C library version 2.x
|
||||
for programing histograms with help of vertical graphs.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* All graph values are displayed in number of vertical pixels.
|
||||
* The sketch demostrates a histogram
|
||||
- in second row with one row height
|
||||
- in full display are with
|
||||
with values changed randomly.
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.0.0
|
||||
Updated: 01.03.2015
|
||||
*/
|
||||
|
||||
/* Needed libraries
|
||||
Dispite the LCD library includes Wire library, the ArduinoIDE does not
|
||||
includes nested libraries, if they are not in the same folder.
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry for LCD 1602
|
||||
const byte lcdAddr = 0x27; // Typical address of I2C backpack for 1602
|
||||
const byte lcdCols = 16; // Number of characters in a row of display
|
||||
const byte lcdRows = 2; // Number of lines of display
|
||||
|
||||
// LCD address and geometry for LCD 2004
|
||||
//const byte lcdAddr = 0x3F; // Typical address of I2C backpack for 2004
|
||||
//const byte lcdCols = 20; // Number of characters in a row of display
|
||||
//const byte lcdRows = 4; // Number of lines of display
|
||||
|
||||
// Initialize library and setting LCD geometry
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Demo constants
|
||||
const int graphDelay = 100; // Delay between histograms
|
||||
const int demoTime = 5000; // Showing time of a demo
|
||||
|
||||
// Demo variables
|
||||
byte graphPixelsCur, graphPixelsMax;
|
||||
unsigned long demoStart;
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Initialize LCD
|
||||
lcd.init();
|
||||
lcd.backlight(); // Switch on the backlight LED, if any or wired
|
||||
|
||||
/* Initialize graph
|
||||
* Macro is defined in LiquidCrystal_I2C library.
|
||||
* Function uses all 8 custom character positions (0-7)
|
||||
and creates custom characters for displaying vertical bar.
|
||||
*/
|
||||
lcd.init_bargraph(LCDI2C_VERTICAL_BAR_GRAPH);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Demo 1: One row histogram
|
||||
lcd.clear();
|
||||
lcd.print("Histogram");
|
||||
graphPixelsMax = LCD_CHARACTER_VERTICAL_DOTS;
|
||||
demoStart = millis();
|
||||
while(millis() - demoStart < demoTime) {
|
||||
for(byte graphCol = 0; graphCol < lcdCols; graphCol++) {
|
||||
graphPixelsCur = random(0, graphPixelsMax);
|
||||
lcd.draw_vertical_graph(1, graphCol, 1, graphPixelsCur);
|
||||
}
|
||||
delay(graphDelay);
|
||||
}
|
||||
// Demo 2: Full display histogram
|
||||
lcd.clear();
|
||||
graphPixelsMax = lcdRows * LCD_CHARACTER_VERTICAL_DOTS;
|
||||
demoStart = millis();
|
||||
while(millis() - demoStart < demoTime) {
|
||||
for(byte graphCol = 0; graphCol < lcdCols; graphCol++) {
|
||||
graphPixelsCur = random(0, graphPixelsMax);
|
||||
lcd.draw_vertical_graph(lcdRows - 1, graphCol, lcdRows, graphPixelsCur);
|
||||
}
|
||||
delay(graphDelay);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
NAME:
|
||||
Demo sketch for Horizontal Bar Graph
|
||||
|
||||
DESCRIPTION:
|
||||
The sketch demonstrates usage of LiquidCrystal_I2C library version 2.x
|
||||
for programing horizontal graphs, which mimics progress bar.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* All graph values are displayed in number of horizontal pixels.
|
||||
* The sketch demostrates
|
||||
- 1. Continues full row progress bar
|
||||
- 2. Continues half row central progress bar
|
||||
- 3. Random full row progress bar
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.0.0
|
||||
Updated: 01.03.2015
|
||||
*/
|
||||
|
||||
/* Needed libraries
|
||||
Dispite the LCD library includes Wire library, the ArduinoIDE does not
|
||||
includes nested libraries, if they are not in the same folder.
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry for LCD 1602
|
||||
const byte lcdAddr = 0x27; // Typical address of I2C backpack for 1602
|
||||
const byte lcdCols = 16; // Number of characters in a row of display
|
||||
const byte lcdRows = 2; // Number of lines of display
|
||||
|
||||
// LCD address and geometry for LCD 2004
|
||||
//const byte lcdAddr = 0x3F; // Typical address of I2C backpack for 2004
|
||||
//const byte lcdCols = 20; // Number of characters in a row of display
|
||||
//const byte lcdRows = 4; // Number of lines of display
|
||||
|
||||
// Initialize library and setting LCD geometry
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Cursor coordinates and character row pattern for progress bar
|
||||
const byte graphRow = 1; // In this row the graph is displayed
|
||||
const byte labelRow = 0; // In this row the label is displayed
|
||||
const byte valueCol = lcdCols - 2; // In this column starts graph value
|
||||
const int graphDelay = 100; // Delay between graph values in ms
|
||||
const int demoDelay = 3000; // Delay between demos in ms
|
||||
|
||||
// Demo parameters
|
||||
const char graphType[] = " Bar";
|
||||
const char* graphLbls[] = {"Full", "Half", "Random"};
|
||||
const byte graphLens[] = {lcdCols, lcdCols / 2, lcdCols};
|
||||
const byte graphCols[] = {0, lcdCols / 4, 0};
|
||||
|
||||
// Demo variables
|
||||
byte graphPixelsCur, graphPixelsMax;
|
||||
|
||||
// Function for displaying graph label
|
||||
void printLabel(byte demo) {
|
||||
// Create label
|
||||
char labelText[valueCol];
|
||||
sprintf(labelText, "%1u.%s%s", demo + 1, graphLbls[demo], graphType);
|
||||
// Display label on clear display
|
||||
lcd.clear();
|
||||
lcd.setCursor(0, labelRow);
|
||||
lcd.print(labelText);
|
||||
|
||||
}
|
||||
|
||||
// Function for displaying graph value
|
||||
void printValue(byte value) {
|
||||
lcd.clear(labelRow, valueCol); // Clear value space
|
||||
lcd.setCursor(valueCol, labelRow);
|
||||
lcd.print(value);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Initialize LCD
|
||||
lcd.init();
|
||||
lcd.backlight(); // Switch on the backlight LED, if any or wired
|
||||
|
||||
/* Initialize graph
|
||||
* Macro is defined in LiquidCrystal_I2C library.
|
||||
* Function uses the first 5 custom character positions (0-4)
|
||||
and creates custom characters for displaying progress bar.
|
||||
*/
|
||||
lcd.init_bargraph(LCDI2C_HORIZONTAL_BAR_GRAPH);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for(byte demoNum = 0; demoNum < sizeof(graphLens)/sizeof(graphLens[0]); demoNum++) {
|
||||
graphPixelsMax = graphLens[demoNum] * LCD_CHARACTER_HORIZONTAL_DOTS;
|
||||
printLabel(demoNum);
|
||||
switch (demoNum) {
|
||||
case 0:
|
||||
case 1:
|
||||
// Demo 1: Graph in full row with sequence values
|
||||
// Demo 2: Graph in half row with sequence values
|
||||
// Descending graph values
|
||||
for (byte i = graphPixelsMax; i > 0; i--) {
|
||||
graphPixelsCur = i - 1;
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_horizontal_graph(graphRow, graphCols[demoNum], graphLens[demoNum], graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
// Ascending graph values
|
||||
for (byte i = 0; i < graphPixelsMax; i++) {
|
||||
graphPixelsCur = i;
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_horizontal_graph(graphRow, graphCols[demoNum], graphLens[demoNum], graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Demo 3: Graph in full row with random values
|
||||
for (byte i = 0; i < graphPixelsMax; i++) {
|
||||
graphPixelsCur = random(0, graphPixelsMax);
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_horizontal_graph(graphRow, graphCols[demoNum], graphLens[demoNum], graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
break;
|
||||
}
|
||||
delay(demoDelay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
NAME:
|
||||
Demo sketch for Horizontal Line Graph
|
||||
|
||||
DESCRIPTION:
|
||||
The sketch demonstrates usage of LiquidCrystal_I2C library version 2.x
|
||||
for programing horizontal graphs, which mimics scale graphs.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* All graph values are displayed in number of horizontal pixels.
|
||||
* The sketch demostrates
|
||||
- 1. Continues full row scale graph
|
||||
- 2. Continues half row central scale graph
|
||||
- 3. Random full row scale graph
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.0.0
|
||||
Updated: 01.03.2015
|
||||
*/
|
||||
|
||||
/* Needed libraries
|
||||
Dispite the LCD library includes Wire library, the ArduinoIDE does not
|
||||
includes nested libraries, if they are not in the same folder.
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry for LCD 1602
|
||||
const byte lcdAddr = 0x27; // Typical address of I2C backpack for 1602
|
||||
const byte lcdCols = 16; // Number of characters in a row of display
|
||||
const byte lcdRows = 2; // Number of lines of display
|
||||
|
||||
// LCD address and geometry for LCD 2004
|
||||
//const byte lcdAddr = 0x3F; // Typical address of I2C backpack for 2004
|
||||
//const byte lcdCols = 20; // Number of characters in a row of display
|
||||
//const byte lcdRows = 4; // Number of lines of display
|
||||
|
||||
// Initialize library and setting LCD geometry
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Cursor coordinates and character row pattern for progress bar
|
||||
const byte graphRow = 1; // In this row the graph is displayed
|
||||
const byte labelRow = 0; // In this row the label is displayed
|
||||
const byte valueCol = lcdCols - 2; // In this column starts graph value
|
||||
const int graphDelay = 200; // Delay between graph values in ms
|
||||
const int demoDelay = 3000; // Delay between demos in ms
|
||||
|
||||
// Demo parameters
|
||||
const char graphType[] = "Scale";
|
||||
const char* graphLbls[] = {"Full ", "Half ", "Random"};
|
||||
const byte graphLens[] = {lcdCols, lcdCols / 2, lcdCols};
|
||||
const byte graphCols[] = {0, lcdCols / 4, 0};
|
||||
|
||||
// Demo variables
|
||||
byte graphPixelsCur, graphPixelsMax;
|
||||
|
||||
// Function for displaying graph label
|
||||
void printLabel(byte demo) {
|
||||
// Create label
|
||||
char labelText[valueCol];
|
||||
sprintf(labelText, "%1u.%s%s", demo + 1, graphLbls[demo], graphType);
|
||||
// Display label on clear display
|
||||
lcd.clear();
|
||||
lcd.setCursor(0, labelRow);
|
||||
lcd.print(labelText);
|
||||
|
||||
}
|
||||
|
||||
// Function for displaying graph value
|
||||
void printValue(byte value) {
|
||||
lcd.clear(labelRow, valueCol); // Clear value space
|
||||
lcd.setCursor(valueCol, labelRow);
|
||||
lcd.print(value);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Initialize LCD
|
||||
lcd.init();
|
||||
lcd.backlight(); // Switch on the backlight LED, if any or wired
|
||||
|
||||
/* Initialize graph
|
||||
* Macro is defined in LiquidCrystal_I2C library.
|
||||
* Function uses the first 5 custom character positions (0-4)
|
||||
and creates custom characters for displaying progress bar.
|
||||
*/
|
||||
lcd.init_bargraph(LCDI2C_HORIZONTAL_LINE_GRAPH);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for(byte demoNum = 0; demoNum < sizeof(graphLens)/sizeof(graphLens[0]); demoNum++) {
|
||||
graphPixelsMax = graphLens[demoNum] * LCD_CHARACTER_HORIZONTAL_DOTS;
|
||||
printLabel(demoNum);
|
||||
switch (demoNum) {
|
||||
case 0:
|
||||
case 1:
|
||||
// Demo 1: Graph in full row with sequence values
|
||||
// Demo 2: Graph in half row with sequence values
|
||||
// Descending graph values
|
||||
for (byte i = graphPixelsMax; i > 0; i--) {
|
||||
graphPixelsCur = i - 1;
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_horizontal_graph(graphRow, graphCols[demoNum], graphLens[demoNum], graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
// Ascending graph values
|
||||
for (byte i = 0; i < graphPixelsMax; i++) {
|
||||
graphPixelsCur = i;
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_horizontal_graph(graphRow, graphCols[demoNum], graphLens[demoNum], graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Demo 3: Graph in full row with random values
|
||||
for (byte i = 0; i < graphPixelsMax; i++) {
|
||||
graphPixelsCur = random(0, graphPixelsMax);
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_horizontal_graph(graphRow, graphCols[demoNum], graphLens[demoNum], graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
break;
|
||||
}
|
||||
delay(demoDelay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
LiquidCrystal_I2C lcd1(0x26,16,2); // set the LCD address of the first lcd to 0x26 for a 16 chars and 2 line display
|
||||
LiquidCrystal_I2C lcd2(0x27,16,2); // set the LCD address of the second lcd to 0x27 for a 16 chars and 2 line display
|
||||
|
||||
void setup()
|
||||
{
|
||||
lcd1.init(); // initialize the first lcd
|
||||
lcd2.init(); // initialize the second lcd
|
||||
|
||||
// Print a message on the first LCD.
|
||||
lcd1.backlight();
|
||||
lcd1.print("Hello, #1 world!");
|
||||
|
||||
// Print a message on the second LCD.
|
||||
lcd2.backlight();
|
||||
lcd2.print("Hello, #2 world!");
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<a id="library"></a>
|
||||
# LiquidCrystal_I2C
|
||||
It is the reimplementation of the standard Arduino LCD library, configured to work with parallel HD44780 compatible LCDs, and interfaced via a Chinese PCF8574 I2C serial extender.
|
||||
|
||||
<a id="examples"></a>
|
||||
## Examples
|
||||
##### Autoscroll
|
||||
Demonstrates autoscroll function.
|
||||
|
||||
##### CompleteTest
|
||||
Demo sketch for complete printing test of the LCD. The test suit consist of 9 tests each labeled in the first row.
|
||||
|
||||
##### CustomChars
|
||||
Creation of 8 custom characters in form of graphical symbols.
|
||||
|
||||
##### HelloWorld
|
||||
Standard initial example. Use it for checking basic functionality and address of the LCD.
|
||||
|
||||
##### Histogram
|
||||
Demo sketch for several histograms composed of vertical bar graphs. The values for graphs are generated randomly.
|
||||
1. The first demo histogram is displayed in one row only.
|
||||
1. The second demo histogram display across all rows of the LCD and uses its entire screen.
|
||||
|
||||
##### HorizontalBarGraph
|
||||
Demo sketch for horizontal bar graphs.
|
||||
1. The first demo histogram uses full row for continues increasing and decreasing values (breathing graph).
|
||||
1. The second demo histogram is a breathing graph using just one half of a row.
|
||||
1. The third demo histogram displays values generated randomly.
|
||||
|
||||
##### HorizontalLineGraph
|
||||
Demo sketch for horizontal line graphs. A value is represented just with a pipe on a row.
|
||||
1. The first demo histogram uses full row for continues increasing and decreasing values (running graph).
|
||||
1. The second demo histogram is a running graph using just one half of a row.
|
||||
1. The third demo histogram displays values generated randomly.
|
||||
|
||||
##### MultipleLcd
|
||||
Using multiple LCD on the same I2C bus but communicating on different addresses.
|
||||
|
||||
##### Scroll
|
||||
Demonstrates scrolling text to the left and right without changing text.
|
||||
|
||||
##### SerialDisplay
|
||||
Sketch receives characters from the serial port and displays them on the LCD one by one.
|
||||
|
||||
##### VerticalBarGraph
|
||||
Demo sketch for vertical bar graph. The graph uses all rows in the last column for continues increasing and decreasing values (breathing graph).
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
NAME:
|
||||
Demonstration scrolling text to the left and right without changing text.
|
||||
|
||||
DESCRIPTION:
|
||||
This sketch demonstrates the use of the scrollDisplayLeft() and
|
||||
scrollDisplayRight() functions to make new text scroll to the left and right.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.0.0
|
||||
Updated: 20.03.2016
|
||||
|
||||
CREDIT:
|
||||
The example taken and rewritten for I2C from official Arduino standard library
|
||||
(https://github.com/arduino/Arduino/tree/master/libraries/LiquidCrystal)
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry and library initialization
|
||||
const byte lcdAddr = 0x27; // Address of I2C backpack
|
||||
const byte lcdCols = 16; // Number of character in a row
|
||||
const byte lcdRows = 2; // Number of lines
|
||||
//const byte lcdAddr = 0x3F; // Address of I2C backpack
|
||||
//const byte lcdCols = 20; // Number of character in a row
|
||||
//const byte lcdRows = 4; // Number of lines
|
||||
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Demo parameters
|
||||
const char demoText[]= "Hello World!";
|
||||
const unsigned int scrollDelay = 500; // Miliseconds before scrolling next char
|
||||
const unsigned int demoDelay = 2000; // Miliseconds between demo loops
|
||||
byte textLen; // Number of visible characters in the text
|
||||
|
||||
void setup() {
|
||||
textLen = sizeof(demoText) - 1;
|
||||
lcd.init();
|
||||
lcd.backlight();
|
||||
lcd.print(demoText);
|
||||
delay(demoDelay);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Scroll entire text in a row to the left outside the screen
|
||||
for (byte positionCounter = 0; positionCounter < textLen; positionCounter++) {
|
||||
lcd.scrollDisplayLeft();
|
||||
delay(scrollDelay);
|
||||
}
|
||||
// Scroll hidden text through entire row to the right outside the screen
|
||||
for (byte positionCounter = 0; positionCounter < textLen + lcdCols; positionCounter++) {
|
||||
lcd.scrollDisplayRight();
|
||||
delay(scrollDelay);
|
||||
}
|
||||
// Scroll text to the right back to original position
|
||||
for (byte positionCounter = 0; positionCounter < lcdCols; positionCounter++) {
|
||||
lcd.scrollDisplayLeft();
|
||||
delay(scrollDelay);
|
||||
}
|
||||
delay(demoDelay);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Displays text sent over the serial port (e.g. from the Serial Monitor) on
|
||||
* an attached LCD.
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
|
||||
|
||||
void setup()
|
||||
{
|
||||
lcd.init(); // initialize the lcd
|
||||
lcd.backlight();
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// when characters arrive over the serial port...
|
||||
if (Serial.available()) {
|
||||
// wait a bit for the entire message to arrive
|
||||
delay(100);
|
||||
// clear the screen
|
||||
lcd.clear();
|
||||
// read all the available characters
|
||||
while (Serial.available() > 0) {
|
||||
// display each character to the LCD
|
||||
lcd.write(Serial.read());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
NAME:
|
||||
Demo sketch for Vertical Bar Graph
|
||||
|
||||
DESCRIPTION:
|
||||
The sketch demonstrates usage of LiquidCrystal_I2C library version 2.x
|
||||
for programing vertical graphs, which mimics histogram.
|
||||
* The sketch is intended preferrably for 16x2 LCD, but can be configured
|
||||
for 20x4 LCDs just by uncommenting and commenting related sections.
|
||||
* All graph values are displayed in number of vertical pixels.
|
||||
* The sketch demostrates vertical graphs from one row graph to full rows
|
||||
graph of the display.
|
||||
* The sketch is just for demonstration purposes, so that it is not
|
||||
optimized for memory usage.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
Version: 1.0.0
|
||||
Updated: 01.03.2015
|
||||
*/
|
||||
|
||||
/* Needed libraries
|
||||
Dispite the LCD library includes Wire library, the ArduinoIDE does not
|
||||
includes nested libraries, if they are not in the same folder.
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
// LCD address and geometry for LCD 1602
|
||||
const byte lcdAddr = 0x27; // Typical address of I2C backpack for 1602
|
||||
const byte lcdCols = 16; // Number of characters in a row of display
|
||||
const byte lcdRows = 2; // Number of lines of display
|
||||
|
||||
// LCD address and geometry for LCD 2004
|
||||
//const byte lcdAddr = 0x3F; // Typical address of I2C backpack for 2004
|
||||
//const byte lcdCols = 20; // Number of characters in a row of display
|
||||
//const byte lcdRows = 4; // Number of lines of display
|
||||
|
||||
// Initialize library and setting LCD geometry
|
||||
LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows);
|
||||
|
||||
// Cursor coordinates and character row pattern for progress bar
|
||||
const byte graphCol = lcdCols - 1; // In this column the graph is displayed
|
||||
const int graphDelay = 200; // Delay between graph values in ms
|
||||
const int demoDelay = 3000; // Delay between demos in ms
|
||||
|
||||
// Demo parameters
|
||||
const char graphType[] = " Col(s) Graph";
|
||||
|
||||
// Demo variables
|
||||
byte graphPixelsCur, graphPixelsMax;
|
||||
|
||||
// Function for displaying graph label
|
||||
void printLabel(byte rows) {
|
||||
const byte labelCol = 0;
|
||||
const byte labelRow = 0;
|
||||
// Create label
|
||||
char labelText[graphCol];
|
||||
sprintf(labelText, "%1u%s", rows, graphType);
|
||||
// Display label on clear display
|
||||
lcd.clear();
|
||||
lcd.setCursor(labelCol, labelRow);
|
||||
lcd.print(labelText);
|
||||
|
||||
}
|
||||
|
||||
// Function for displaying graph value
|
||||
void printValue(byte value) {
|
||||
const byte valueWidth = 2; // Max. digits in value
|
||||
const byte valueCol = graphCol - valueWidth - 1;
|
||||
const byte valueRow = 1;
|
||||
// Create value
|
||||
char valueFormat[4], valueText[valueWidth + 1];
|
||||
sprintf(valueFormat, "%%%1uu", valueWidth);
|
||||
sprintf(valueText, valueFormat, value);
|
||||
// Display label on clear display
|
||||
lcd.clear(valueRow, valueCol, valueWidth);
|
||||
lcd.setCursor(valueCol, valueRow);
|
||||
lcd.print(valueText);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Initialize LCD
|
||||
lcd.init();
|
||||
lcd.backlight(); // Switch on the backlight LED, if any or wired
|
||||
|
||||
/* Initialize graph
|
||||
* Macro is defined in LiquidCrystal_I2C library.
|
||||
* Function uses all 8 custom character positions (0-7)
|
||||
and creates custom characters for displaying vertical bar.
|
||||
*/
|
||||
lcd.init_bargraph(LCDI2C_VERTICAL_BAR_GRAPH);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for(byte graphHight = 1; graphHight <= lcdRows; graphHight++) {
|
||||
graphPixelsMax = graphHight * LCD_CHARACTER_VERTICAL_DOTS;
|
||||
printLabel(graphHight);
|
||||
for (byte i = graphPixelsMax; i > 0; i--) {
|
||||
graphPixelsCur = i - 1;
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_vertical_graph(graphHight - 1, graphCol, graphHight, graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
// Ascending graph values
|
||||
for (byte i = 0; i < graphPixelsMax; i++) {
|
||||
graphPixelsCur = i;
|
||||
printValue(graphPixelsCur);
|
||||
lcd.draw_vertical_graph(graphHight - 1, graphCol, graphHight, graphPixelsCur);
|
||||
delay(graphDelay);
|
||||
}
|
||||
delay(demoDelay);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://www.banggood.com/IIC-Or-I2C-Or-TWI-SPI-LCD1602-Character-LCD-Module-For-Arduino-p-88316.html?p=5G0704100426201212C9
|
||||
IDList=
|
||||
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://www.banggood.com/IIC-Or-I2C-2004-204-20-X-4-Character-LCD-Display-Module-Blue-p-908616.html?p=5G0704100426201212C9
|
||||
IDList=
|
||||
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://www.banggood.com/IIC-Or-I2C-Or-TWI-Or-SP-Serial-Interface-Module-Port-For-5V-Arduino-1602LCD-p-80365.html?p=5G0704100426201212C9
|
||||
IDList=
|
||||
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://www.banggood.com/IIC-Or-I2C-2004-204-20-X-4-Character-LCD-Display-Module-Yellow-Green-p-908821.html?p=5G0704100426201212C9
|
||||
IDList=
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
@@ -0,0 +1,7 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://playground.arduino.cc/Code/LCDi2c
|
||||
IDList=
|
||||
IconFile=http://playground.arduino.cc/favicon.png
|
||||
IconIndex=1
|
||||
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,2
|
||||
[InternetShortcut]
|
||||
URL=http://playground.arduino.cc/Code/LCDAPI
|
||||
IDList=
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 146 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,47 @@
|
||||
// LiquidCrystal_I2C V2.0 - Mario H. atmega@xs4all.nl
|
||||
// Mods for Chinese I2C converter board - Murray R. Van Luyn. vanluynm@iinet.net.au
|
||||
|
||||
The LiquidCrystal_I2C library is a modified version of the standard LiquidCrystal library as found on
|
||||
the Arduino website.
|
||||
This library is intended to be used when a parallel HD44780 compatible LCD is controlled over I2C using
|
||||
a Chinese PCF8574 extender.
|
||||
4 of the 8 outputs are used for LCD data lines 4 to 7.
|
||||
4 outputs are used for the Enable, register-select, Read/Write and backlight control lines.
|
||||
|
||||
The Chinese PCF8574 extender is available in two versions, the PCF8574 and the PCF8574A.
|
||||
The only difference between the two is the I2C base address.
|
||||
The base address for the PCF8574 is 0x27 and the base address for the PCF8574A is 0x4E.
|
||||
The examples included in this zip file assume the use of an PCF8574 set for address 0x27
|
||||
(A0, A1 and A3 un-linked, so pulled high).
|
||||
|
||||
For PCF8574 the addressing is:
|
||||
|
||||
Jp3 Jp2 Jp1
|
||||
A2 A1 A0 Dec Hex
|
||||
L L L 32 0x20
|
||||
L L H 33 0x21
|
||||
L H L 34 0x22
|
||||
L H H 35 0x23
|
||||
H L L 36 0x24
|
||||
H L H 37 0x25
|
||||
H H L 38 0x26
|
||||
H H H 39 0x27
|
||||
|
||||
For PCF8574A the addressing is:
|
||||
|
||||
Jp3 Jp2 Jp1
|
||||
A2 A1 A0 Dec Hex
|
||||
L L L 56 0x38
|
||||
L L H 57 0x39
|
||||
L H L 64 0x40
|
||||
L H H 74 0x4A
|
||||
H L L 75 0x4B
|
||||
H L H 76 0x4C
|
||||
H H L 77 0x4D
|
||||
H H H 78 0x4E
|
||||
|
||||
For compatibility reasons this library contains some aliases for functions that are known under different
|
||||
names in other libraries. This should make it fairly easy to implement the library in existing sketches
|
||||
without changing to much code.
|
||||
Functions not supported by this library will return nothing at all and in case a return value is expected
|
||||
the function will return 0.
|
||||
50
firmware_adxl345_spi/lib/LiquidCrystal_I2C/keywords.txt
Normal file
50
firmware_adxl345_spi/lib/LiquidCrystal_I2C/keywords.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
###########################################
|
||||
# Syntax Coloring Map For LiquidCrystal_I2C
|
||||
###########################################
|
||||
|
||||
###########################################
|
||||
# Datatypes (KEYWORD1)
|
||||
###########################################
|
||||
LiquidCrystal_I2C KEYWORD1
|
||||
|
||||
###########################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
###########################################
|
||||
init KEYWORD2
|
||||
begin KEYWORD2
|
||||
clear KEYWORD2
|
||||
home KEYWORD2
|
||||
noDisplay KEYWORD2
|
||||
display KEYWORD2
|
||||
noBlink KEYWORD2
|
||||
blink KEYWORD2
|
||||
noCursor KEYWORD2
|
||||
cursor KEYWORD2
|
||||
scrollDisplayLeft KEYWORD2
|
||||
scrollDisplayRight KEYWORD2
|
||||
leftToRight KEYWORD2
|
||||
rightToLeft KEYWORD2
|
||||
shiftIncrement KEYWORD2
|
||||
shiftDecrement KEYWORD2
|
||||
noBacklight KEYWORD2
|
||||
backlight KEYWORD2
|
||||
autoscroll KEYWORD2
|
||||
noAutoscroll KEYWORD2
|
||||
createChar KEYWORD2
|
||||
setCursor KEYWORD2
|
||||
print KEYWORD2
|
||||
blink_on KEYWORD2
|
||||
blink_off KEYWORD2
|
||||
cursor_on KEYWORD2
|
||||
cursor_off KEYWORD2
|
||||
setBacklight KEYWORD2
|
||||
load_custom_character KEYWORD2
|
||||
printstr KEYWORD2
|
||||
init_bargraph KEYWORD2
|
||||
draw_horizontal_graph KEYWORD2
|
||||
graphHorizontalChars KEYWORD2
|
||||
graphVerticalChars KEYWORD2
|
||||
###########################################
|
||||
# Constants (LITERAL1)
|
||||
###########################################
|
||||
LIQUIDCRYSTAL_I2C_VERSION LITERAL1
|
||||
@@ -0,0 +1,9 @@
|
||||
name=LiquidCrystal_I2C
|
||||
version=2.6.1
|
||||
author=Libor Gabaj <libor.gabaj@gmail.com>
|
||||
maintainer=Libor Gabaj <libor.gabaj@gmail.com>
|
||||
sentence=Library for parallel HD44780 compatible LCDs interfaced via a Chinese PCF8574 I2C serial extender.
|
||||
paragraph=Library for parallel HD44780 compatible LCDs interfaced via a Chinese PCF8574 I2C serial extender. It adds overloaded clear() function for clearing particular segment of an input row. Library also implements extended graph functions with help of custom characters and adds overloaded graph functions for expressing graph value in percentage or ration instead of pixels.
|
||||
category=Display
|
||||
url=https://github.com/mrkaleArduinoLib/LiquidCrystal_I2C.git
|
||||
architectures=avr
|
||||
@@ -0,0 +1,444 @@
|
||||
#include "LiquidCrystal_I2C.h"
|
||||
|
||||
// When the display powers up, it is configured as follows:
|
||||
//
|
||||
// 1. Display clear
|
||||
// 2. Function set:
|
||||
// DL = 1; 8-bit interface data
|
||||
// N = 0; 1-line display
|
||||
// F = 0; 5x8 dot character font
|
||||
// 3. Display on/off control:
|
||||
// D = 0; Display off
|
||||
// C = 0; Cursor off
|
||||
// B = 0; Blinking off
|
||||
// 4. Entry mode set:
|
||||
// I/D = 1; Increment by 1
|
||||
// S = 0; No shift
|
||||
//
|
||||
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
|
||||
// can't assume that its in that state when a sketch starts (and the
|
||||
// LiquidCrystal constructor is called).
|
||||
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t addr, uint8_t cols, uint8_t rows)
|
||||
{
|
||||
_Addr = addr;
|
||||
_cols = cols;
|
||||
_rows = rows;
|
||||
_backlightval = LCD_NOBACKLIGHT;
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::init(){
|
||||
init_priv();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::init_priv()
|
||||
{
|
||||
Wire.begin();
|
||||
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
|
||||
begin(_cols, _rows);
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t charsize) {
|
||||
if (lines > 1) {
|
||||
_displayfunction |= LCD_2LINE;
|
||||
}
|
||||
_numlines = lines;
|
||||
|
||||
// for some 1 line displays you can select a 10 pixel high font
|
||||
if ((charsize != 0) && (lines == 1)) {
|
||||
_displayfunction |= LCD_5x10DOTS;
|
||||
}
|
||||
|
||||
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
|
||||
// according to datasheet, we need at least 40ms after power rises above 2.7V
|
||||
// before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
|
||||
delayMicroseconds(50000);
|
||||
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
|
||||
delay(1000);
|
||||
|
||||
// put the LCD into 4 bit mode
|
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// figure 24, pg 46
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x30);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x30);
|
||||
delayMicroseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x30);
|
||||
delayMicroseconds(150);
|
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x20);
|
||||
|
||||
|
||||
// set # lines, font size, etc.
|
||||
command(LCD_FUNCTIONSET | _displayfunction);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
|
||||
display();
|
||||
|
||||
// clear it off
|
||||
clear();
|
||||
|
||||
// Initialize to default text direction (for roman languages)
|
||||
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
|
||||
|
||||
// set the entry mode
|
||||
command(LCD_ENTRYMODESET | _displaymode);
|
||||
|
||||
home();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********** high level commands, for the user! */
|
||||
void LiquidCrystal_I2C::clear(){
|
||||
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
delayMicroseconds(2000); // this command takes a long time!
|
||||
}
|
||||
|
||||
// Clear particular segment of a row
|
||||
void LiquidCrystal_I2C::clear(uint8_t rowStart, uint8_t colStart, uint8_t colCnt) {
|
||||
// Maintain input parameters
|
||||
rowStart = constrain(rowStart, 0, _rows - 1);
|
||||
colStart = constrain(colStart, 0, _cols - 1);
|
||||
colCnt = constrain(colCnt, 0, _cols - colStart);
|
||||
// Clear segment
|
||||
setCursor(colStart, rowStart);
|
||||
for (uint8_t i = 0; i < colCnt; i++) write(' ');
|
||||
// Go to segment start
|
||||
setCursor(colStart, rowStart);
|
||||
}
|
||||
|
||||
|
||||
void LiquidCrystal_I2C::home(){
|
||||
command(LCD_RETURNHOME); // set cursor position to zero
|
||||
delayMicroseconds(2000); // this command takes a long time!
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row){
|
||||
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
|
||||
if ( row > _numlines ) {
|
||||
row = _numlines-1; // we count rows starting w/0
|
||||
}
|
||||
command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
|
||||
}
|
||||
|
||||
// Turn the display on/off (quickly)
|
||||
void LiquidCrystal_I2C::noDisplay() {
|
||||
_displaycontrol &= ~LCD_DISPLAYON;
|
||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||
}
|
||||
void LiquidCrystal_I2C::display() {
|
||||
_displaycontrol |= LCD_DISPLAYON;
|
||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||
}
|
||||
|
||||
// Turns the underline cursor on/off
|
||||
void LiquidCrystal_I2C::noCursor() {
|
||||
_displaycontrol &= ~LCD_CURSORON;
|
||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||
}
|
||||
void LiquidCrystal_I2C::cursor() {
|
||||
_displaycontrol |= LCD_CURSORON;
|
||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||
}
|
||||
|
||||
// Turn on and off the blinking cursor
|
||||
void LiquidCrystal_I2C::noBlink() {
|
||||
_displaycontrol &= ~LCD_BLINKON;
|
||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||
}
|
||||
void LiquidCrystal_I2C::blink() {
|
||||
_displaycontrol |= LCD_BLINKON;
|
||||
command(LCD_DISPLAYCONTROL | _displaycontrol);
|
||||
}
|
||||
|
||||
// These commands scroll the display without changing the RAM
|
||||
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
|
||||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
|
||||
}
|
||||
void LiquidCrystal_I2C::scrollDisplayRight(void) {
|
||||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
|
||||
}
|
||||
|
||||
// This is for text that flows Left to Right
|
||||
void LiquidCrystal_I2C::leftToRight(void) {
|
||||
_displaymode |= LCD_ENTRYLEFT;
|
||||
command(LCD_ENTRYMODESET | _displaymode);
|
||||
}
|
||||
|
||||
// This is for text that flows Right to Left
|
||||
void LiquidCrystal_I2C::rightToLeft(void) {
|
||||
_displaymode &= ~LCD_ENTRYLEFT;
|
||||
command(LCD_ENTRYMODESET | _displaymode);
|
||||
}
|
||||
|
||||
// This will 'right justify' text from the cursor
|
||||
void LiquidCrystal_I2C::autoscroll(void) {
|
||||
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
|
||||
command(LCD_ENTRYMODESET | _displaymode);
|
||||
}
|
||||
|
||||
// This will 'left justify' text from the cursor
|
||||
void LiquidCrystal_I2C::noAutoscroll(void) {
|
||||
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
|
||||
command(LCD_ENTRYMODESET | _displaymode);
|
||||
}
|
||||
|
||||
// Allows us to fill the first 8 CGRAM locations
|
||||
// with custom characters
|
||||
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++) {
|
||||
write(charmap[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the (optional) backlight off/on
|
||||
void LiquidCrystal_I2C::noBacklight(void) {
|
||||
_backlightval=LCD_NOBACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::backlight(void) {
|
||||
_backlightval=LCD_BACKLIGHT;
|
||||
expanderWrite(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********** mid level commands, for sending data/cmds */
|
||||
|
||||
inline void LiquidCrystal_I2C::command(uint8_t value) {
|
||||
send(value, 0);
|
||||
}
|
||||
|
||||
inline size_t LiquidCrystal_I2C::write(uint8_t value) {
|
||||
send(value, Rs);
|
||||
return 1; // Number of processed bytes
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************ low level data pushing commands **********/
|
||||
|
||||
// write either command or data
|
||||
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
|
||||
uint8_t highnib = value & 0xF0;
|
||||
uint8_t lownib = value << 4;
|
||||
write4bits((highnib)|mode);
|
||||
write4bits((lownib)|mode);
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::write4bits(uint8_t value) {
|
||||
expanderWrite(value);
|
||||
pulseEnable(value);
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::expanderWrite(uint8_t _data){
|
||||
Wire.beginTransmission(_Addr);
|
||||
Wire.write((int)(_data) | _backlightval);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::pulseEnable(uint8_t _data){
|
||||
expanderWrite(_data | En); // En high
|
||||
delayMicroseconds(1); // enable pulse must be >450ns
|
||||
|
||||
expanderWrite(_data & ~En); // En low
|
||||
delayMicroseconds(50); // commands need > 37us to settle
|
||||
}
|
||||
|
||||
// Create custom characters for horizontal graphs
|
||||
uint8_t LiquidCrystal_I2C::graphHorizontalChars(uint8_t rowPattern) {
|
||||
uint8_t cc[LCD_CHARACTER_VERTICAL_DOTS];
|
||||
for (uint8_t idxCol = 0; idxCol < LCD_CHARACTER_HORIZONTAL_DOTS; idxCol++) {
|
||||
for (uint8_t idxRow = 0; idxRow < LCD_CHARACTER_VERTICAL_DOTS; idxRow++) {
|
||||
cc[idxRow] = rowPattern << (LCD_CHARACTER_HORIZONTAL_DOTS - 1 - idxCol);
|
||||
}
|
||||
createChar(idxCol, cc);
|
||||
}
|
||||
return LCD_CHARACTER_HORIZONTAL_DOTS;
|
||||
}
|
||||
|
||||
// Create custom characters for vertical graphs
|
||||
uint8_t LiquidCrystal_I2C::graphVerticalChars(uint8_t rowPattern) {
|
||||
uint8_t cc[LCD_CHARACTER_VERTICAL_DOTS];
|
||||
for (uint8_t idxChr = 0; idxChr < LCD_CHARACTER_VERTICAL_DOTS; idxChr++) {
|
||||
for (uint8_t idxRow = 0; idxRow < LCD_CHARACTER_VERTICAL_DOTS; idxRow++) {
|
||||
cc[LCD_CHARACTER_VERTICAL_DOTS - idxRow - 1] = idxRow > idxChr ? B00000 : rowPattern;
|
||||
}
|
||||
createChar(idxChr, cc);
|
||||
}
|
||||
return LCD_CHARACTER_VERTICAL_DOTS;
|
||||
}
|
||||
|
||||
// Initializes custom characters for input graph type
|
||||
uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype) {
|
||||
// Initialize row state vector
|
||||
for(byte i = 0; i < _rows; i++) {
|
||||
_graphstate[i] = 255;
|
||||
}
|
||||
switch (graphtype) {
|
||||
case LCDI2C_VERTICAL_BAR_GRAPH:
|
||||
graphVerticalChars(B11111);
|
||||
// Initialize column state vector
|
||||
for(byte i = _rows; i < _cols; i++) {
|
||||
_graphstate[i] = 255;
|
||||
}
|
||||
break;
|
||||
case LCDI2C_HORIZONTAL_BAR_GRAPH:
|
||||
graphHorizontalChars(B11111);
|
||||
break;
|
||||
case LCDI2C_HORIZONTAL_LINE_GRAPH:
|
||||
graphHorizontalChars(B00001);
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
_graphtype = graphtype;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Display horizontal graph from desired cursor position with input value
|
||||
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end) {
|
||||
// Maintain input parameters
|
||||
row = constrain(row, 0, _rows - 1);
|
||||
column = constrain(column, 0, _cols - 1);
|
||||
len = constrain(len, 0, _cols - column);
|
||||
pixel_col_end = constrain(pixel_col_end, 0, (len * LCD_CHARACTER_HORIZONTAL_DOTS) - 1);
|
||||
_graphstate[row] = constrain(_graphstate[row], column, column + len - 1);
|
||||
// Display graph
|
||||
switch (_graphtype) {
|
||||
case LCDI2C_HORIZONTAL_BAR_GRAPH:
|
||||
setCursor(column, row);
|
||||
// Display full characters
|
||||
for (uint8_t i = 0; i < pixel_col_end / LCD_CHARACTER_HORIZONTAL_DOTS; i++) {
|
||||
write(LCD_CHARACTER_HORIZONTAL_DOTS - 1);
|
||||
column++;
|
||||
}
|
||||
// Display last character
|
||||
write(pixel_col_end % LCD_CHARACTER_HORIZONTAL_DOTS);
|
||||
// Clear remaining chars in segment
|
||||
for (uint8_t i = column; i < _graphstate[row]; i++) write(' ');
|
||||
// Last drawn column as graph state
|
||||
_graphstate[row] = column;
|
||||
break;
|
||||
case LCDI2C_HORIZONTAL_LINE_GRAPH:
|
||||
// Drawn column as graph state
|
||||
column += pixel_col_end / LCD_CHARACTER_HORIZONTAL_DOTS;
|
||||
// Clear previous drawn character if differs from new one
|
||||
if (_graphstate[row] != column) {
|
||||
setCursor(_graphstate[row], row);
|
||||
write(' ');
|
||||
_graphstate[row] = column;
|
||||
}
|
||||
// Display graph character
|
||||
setCursor(column, row);
|
||||
write(pixel_col_end % LCD_CHARACTER_HORIZONTAL_DOTS);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Display horizontal graph from desired cursor position with input value
|
||||
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end) {
|
||||
// Maintain input parameters
|
||||
row = constrain(row, 0, _rows - 1);
|
||||
column = constrain(column, 0, _cols - 1);
|
||||
len = constrain(len, 0, row + 1);
|
||||
pixel_row_end = constrain(pixel_row_end, 0, (len * LCD_CHARACTER_VERTICAL_DOTS) - 1);
|
||||
_graphstate[column] = constrain(_graphstate[column], row - len + 1, row);
|
||||
// Display graph
|
||||
switch (_graphtype) {
|
||||
case LCDI2C_VERTICAL_BAR_GRAPH:
|
||||
// Display full characters
|
||||
for (uint8_t i = 0; i < pixel_row_end / LCD_CHARACTER_VERTICAL_DOTS; i++) {
|
||||
setCursor(column, row--);
|
||||
write(LCD_CHARACTER_VERTICAL_DOTS - 1);
|
||||
}
|
||||
// Display the highest character
|
||||
setCursor(column, row);
|
||||
write(pixel_row_end % LCD_CHARACTER_VERTICAL_DOTS);
|
||||
// Clear remaining top chars in column
|
||||
for (uint8_t i = _graphstate[column]; i < row; i++) {
|
||||
setCursor(column, i);
|
||||
write(' ');
|
||||
}
|
||||
_graphstate[column] = row; // Last drawn row as its state
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Overloaded methods
|
||||
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint16_t percentage) {
|
||||
percentage = (percentage * len * LCD_CHARACTER_HORIZONTAL_DOTS / 100) - 1;
|
||||
draw_horizontal_graph(row, column, len, (uint8_t) percentage);
|
||||
}
|
||||
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, float ratio) {
|
||||
ratio = (ratio * len * LCD_CHARACTER_HORIZONTAL_DOTS) - 1;
|
||||
draw_horizontal_graph(row, column, len, (uint8_t) ratio);
|
||||
}
|
||||
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint16_t percentage) {
|
||||
percentage = (percentage * len * LCD_CHARACTER_VERTICAL_DOTS / 100) - 1;
|
||||
draw_vertical_graph(row, column, len, (uint8_t) percentage);
|
||||
}
|
||||
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, float ratio) {
|
||||
ratio = (ratio * len * LCD_CHARACTER_VERTICAL_DOTS) - 1;
|
||||
draw_vertical_graph(row, column, len, (uint8_t) ratio);
|
||||
}
|
||||
|
||||
// Alias functions
|
||||
|
||||
void LiquidCrystal_I2C::on(){
|
||||
display();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::off(){
|
||||
noDisplay();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::cursor_on(){
|
||||
cursor();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::cursor_off(){
|
||||
noCursor();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::blink_on(){
|
||||
blink();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::blink_off(){
|
||||
noBlink();
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows){
|
||||
createChar(char_num, rows);
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::setBacklight(uint8_t new_val){
|
||||
if(new_val){
|
||||
backlight(); // turn backlight on
|
||||
}else{
|
||||
noBacklight(); // turn backlight off
|
||||
}
|
||||
}
|
||||
|
||||
void LiquidCrystal_I2C::printstr(const char c[]){
|
||||
//This function is not identical to the function used for "real" I2C displays
|
||||
//it's here so the user sketch doesn't have to be changed
|
||||
print(c);
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
NAME:
|
||||
LiquidCrystal_I2C
|
||||
|
||||
DESCRIPTION:
|
||||
Library for parallel HD44780 compatible LCDs interfaced via a Chinese
|
||||
PCF8574 I2C serial extender.
|
||||
- Library implements LCD API 1.0 to the extend the appropriate LCDs
|
||||
support functionality expected by the API.
|
||||
- Library adds overloaded clear() function for clearing particular
|
||||
segment of an input row.
|
||||
- Library implements extended graph functions with help of custom
|
||||
characters, so that do not use your custom characters concurrently
|
||||
with graph function. Your custom characters will be overwritten by
|
||||
graph initialization.
|
||||
- Library adds overloaded graph functions for expression graph value
|
||||
in percentage instead of pixels.
|
||||
|
||||
LICENSE:
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the MIT License (MIT).
|
||||
|
||||
CREDENTIALS:
|
||||
Author: Libor Gabaj
|
||||
GitHub: https://github.com/mrkaleArduinoLib/LiquidCrystal_I2C.git
|
||||
|
||||
CREDITS:
|
||||
Mario H. atmega@xs4all.nl - LiquidCrystal_I2C V2.0
|
||||
Murray R. Van Luyn. vanluynm@iinet.net.au - Mods for Chinese I2C converter board
|
||||
*/
|
||||
#ifndef LIQUIDCRYSTAL_I2C_H
|
||||
#define LIQUIDCRYSTAL_I2C_H
|
||||
#define LIQUIDCRYSTAL_I2C_VERSION "LiquidCrystal_I2C 2.6.1"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <inttypes.h>
|
||||
#include <Wire.h>
|
||||
|
||||
// commands
|
||||
#define LCD_CLEARDISPLAY 0x01
|
||||
#define LCD_RETURNHOME 0x02
|
||||
#define LCD_ENTRYMODESET 0x04
|
||||
#define LCD_DISPLAYCONTROL 0x08
|
||||
#define LCD_CURSORSHIFT 0x10
|
||||
#define LCD_FUNCTIONSET 0x20
|
||||
#define LCD_SETCGRAMADDR 0x40
|
||||
#define LCD_SETDDRAMADDR 0x80
|
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00
|
||||
#define LCD_ENTRYLEFT 0x02
|
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01
|
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00
|
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04
|
||||
#define LCD_DISPLAYOFF 0x00
|
||||
#define LCD_CURSORON 0x02
|
||||
#define LCD_CURSOROFF 0x00
|
||||
#define LCD_BLINKON 0x01
|
||||
#define LCD_BLINKOFF 0x00
|
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08
|
||||
#define LCD_CURSORMOVE 0x00
|
||||
#define LCD_MOVERIGHT 0x04
|
||||
#define LCD_MOVELEFT 0x00
|
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10
|
||||
#define LCD_4BITMODE 0x00
|
||||
#define LCD_2LINE 0x08
|
||||
#define LCD_1LINE 0x00
|
||||
#define LCD_5x10DOTS 0x04
|
||||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
// flags for backlight control
|
||||
//#define LCD_BACKLIGHT B00001000
|
||||
//#define LCD_NOBACKLIGHT B00000000
|
||||
// LK ESP32
|
||||
#define LCD_BACKLIGHT 0x08
|
||||
#define LCD_NOBACKLIGHT 0x00
|
||||
|
||||
// values for graphtype in calls to init_bargraph and character geometry
|
||||
#define LCDI2C_VERTICAL_BAR_GRAPH 1
|
||||
#define LCDI2C_HORIZONTAL_BAR_GRAPH 2
|
||||
#define LCDI2C_HORIZONTAL_LINE_GRAPH 3
|
||||
#define LCD_CHARACTER_HORIZONTAL_DOTS 5
|
||||
#define LCD_CHARACTER_VERTICAL_DOTS 8
|
||||
|
||||
#define En B00000100 // Enable bit
|
||||
#define Rw B00000010 // Read/Write bit
|
||||
#define Rs B00000001 // Register select bit
|
||||
|
||||
class LiquidCrystal_I2C : public Print {
|
||||
public:
|
||||
LiquidCrystal_I2C(uint8_t addr, uint8_t cols, uint8_t rows);
|
||||
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
|
||||
void init();
|
||||
/*
|
||||
Clear particular segment of a row
|
||||
|
||||
DESCRIPTION:
|
||||
Overloaded original function clear().
|
||||
* Thanks to default parameters, for clearing the entire row
|
||||
use just clear(rowStart).
|
||||
* The functions sets the cursor to start column and row after clearing.
|
||||
|
||||
PARAMETERS:
|
||||
rowStart - row number to be cleared counting from 0.
|
||||
Limited to the last row.
|
||||
colStart - column number of the cleared segment counting from 0.
|
||||
Defaulted to the very begining of the row.
|
||||
Limited to the last character.
|
||||
colCnt - number of cleared characters.
|
||||
Defaulted to 255.
|
||||
Limited to remaining characters on the row.
|
||||
|
||||
RETURN: none
|
||||
*/
|
||||
void clear();
|
||||
void clear(uint8_t rowStart, uint8_t colStart = 0, uint8_t colCnt = 255);
|
||||
void home();
|
||||
void noDisplay();
|
||||
void display();
|
||||
void noBlink();
|
||||
void blink();
|
||||
void noCursor();
|
||||
void cursor();
|
||||
void scrollDisplayLeft();
|
||||
void scrollDisplayRight();
|
||||
void leftToRight();
|
||||
void rightToLeft();
|
||||
void noBacklight();
|
||||
void backlight();
|
||||
void noAutoscroll();
|
||||
void autoscroll();
|
||||
void createChar(uint8_t location, uint8_t charmap[]);
|
||||
void setCursor(uint8_t col, uint8_t row);
|
||||
virtual size_t write(uint8_t value);
|
||||
void command(uint8_t value);
|
||||
|
||||
/*
|
||||
Initialize particular bar graph
|
||||
|
||||
DESCRIPTION:
|
||||
Creates a set of custom characters for displaying bar graphs.
|
||||
Some number of first current custom characters will be overwritten
|
||||
according to the type of graph.
|
||||
|
||||
PARAMETERS:
|
||||
uint8_t graphtype - type of graph
|
||||
LCDI2C_VERTICAL_BAR_GRAPH - rewrites all 8 custom characters
|
||||
LCDI2C_HORIZONTAL_BAR_GRAPH - rewrites first 5 custom characters
|
||||
LCDI2C_HORIZONTAL_LINE_GRAPH - rewrites first 5 custom characters
|
||||
|
||||
RETURN: error code
|
||||
0 - at success
|
||||
1 - at failure, e.g., graph type not recognized
|
||||
*/
|
||||
uint8_t init_bargraph(uint8_t graphtype);
|
||||
|
||||
/*
|
||||
Display horizontal graph from desired cursor position with input value
|
||||
|
||||
DESCRIPTION:
|
||||
Displays horizontal bar or running pipe starting at input cursor position
|
||||
composed of custom characters.
|
||||
* For graph is reserved "len" characters long segment on the "row" starting
|
||||
on "column".
|
||||
* Current value of the bar graph is displayed as "pixel_col_end" pipes
|
||||
in the graph segment.
|
||||
* Current value of the line graph is displayed as pipe on "pixel_col_end"
|
||||
dot position in the graph segment.
|
||||
* Zero value of the graph is displayed as the very left pipe in the
|
||||
graph segment, so that the graph always displays something.
|
||||
|
||||
PARAMETERS:
|
||||
uint8_t row - row position of graph segment counting from 0
|
||||
Limited to physical rows.
|
||||
uint8_t column - column position of graph segment counting from 0
|
||||
Limited to physical columns.
|
||||
uint8_t len - length of graph segment in characters
|
||||
Limited to remaining physical columns from col position.
|
||||
uint8_t pixel_col_end - value of graph in pipes counting from 0
|
||||
Limited to physical horizontal dots of graph segment.
|
||||
|
||||
RETURN: none
|
||||
*/
|
||||
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
|
||||
|
||||
/*
|
||||
Display vertical graph from desired cursor position with input value
|
||||
|
||||
DESCRIPTION:
|
||||
Displays vertical bar starting at "row", "column" position composed
|
||||
of custom characters.
|
||||
For bar is reserved "len" rows long segment on the "column" starting on
|
||||
"row".
|
||||
Current value of the bar graph is displayed as "pixel_row_end" dashes
|
||||
from bottom to top of the graph segment.
|
||||
|
||||
PARAMETERS:
|
||||
uint8_t row - row positon of the bottom of a graph segment
|
||||
counting from 0
|
||||
Limited to physical rows.
|
||||
uint8_t column - column position of graph segment counting from 0
|
||||
Limited to physical columns.
|
||||
uint8_t len - length of graph segment in rows
|
||||
Limited to remaining physical rows from row position.
|
||||
uint8_t pixel_row_end - value of graph in dashes counting from 0
|
||||
Limited to physical vertical dots of graph segment.
|
||||
|
||||
RETURN: none
|
||||
*/
|
||||
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end);
|
||||
|
||||
/*
|
||||
Overloaded methods with type difference of graph value
|
||||
|
||||
PARAMETERS:
|
||||
uint16_t percentage - percentage of graph segment as graph value
|
||||
Although expected range is 0 to 100, uint8_t has been reserved
|
||||
by official API already.
|
||||
float ratio - fraction of graph segment as graph value
|
||||
Expected range is 0.0 to 1.0
|
||||
*/
|
||||
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint16_t percentage);
|
||||
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, float ratio);
|
||||
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint16_t percentage);
|
||||
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, float ratio);
|
||||
|
||||
////compatibility API function aliases
|
||||
void on(); // alias for display()
|
||||
void off(); // alias for noDisplay()
|
||||
void blink_on(); // alias for blink()
|
||||
void blink_off(); // alias for noBlink()
|
||||
void cursor_on(); // alias for cursor()
|
||||
void cursor_off(); // alias for noCursor()
|
||||
void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
|
||||
void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar()
|
||||
void printstr(const char[]);
|
||||
|
||||
/* Unsupported API functions (not implemented in this library)
|
||||
uint8_t status();
|
||||
void setContrast(uint8_t new_val);
|
||||
uint8_t keypad();
|
||||
void setDelay(int, int);
|
||||
*/
|
||||
|
||||
private:
|
||||
void init_priv();
|
||||
void send(uint8_t, uint8_t);
|
||||
void write4bits(uint8_t);
|
||||
void expanderWrite(uint8_t);
|
||||
void pulseEnable(uint8_t);
|
||||
|
||||
/*
|
||||
Create custom characters for horizontal graphs
|
||||
|
||||
DESCRIPTION:
|
||||
Creates the set of custom characters for displaying horizontal graphs.
|
||||
The first 5 current custom characters will be overwritten.
|
||||
Particular custom characters are filled by bit shifting fullCharRowPattern
|
||||
from the right to the left.
|
||||
|
||||
PARAMETERS:
|
||||
uint8_t rowPattern - row pattern of the full character
|
||||
|
||||
RETURN: uint8_t - number of created custom characters
|
||||
*/
|
||||
uint8_t graphHorizontalChars(uint8_t rowPattern);
|
||||
|
||||
/*
|
||||
Create custom characters for vertical graphs
|
||||
|
||||
DESCRIPTION:
|
||||
Creates the set of custom characters for displaying vertical graphs.
|
||||
All 8 current custom characters will be overwritten.
|
||||
Particular custom characters are filled with rowPattern from the very
|
||||
bottom pixel line.
|
||||
|
||||
PARAMETERS:
|
||||
uint8_t rowPattern - row pattern of the pixel line
|
||||
|
||||
RETURN: uint8_t - number of created custom characters
|
||||
*/
|
||||
uint8_t graphVerticalChars(uint8_t rowPattern);
|
||||
|
||||
// Private attributes
|
||||
uint8_t _Addr;
|
||||
uint8_t _displayfunction;
|
||||
uint8_t _displaycontrol;
|
||||
uint8_t _displaymode;
|
||||
uint8_t _numlines;
|
||||
uint8_t _cols;
|
||||
uint8_t _rows;
|
||||
uint8_t _backlightval;
|
||||
uint8_t _graphtype; // Internal code for graph type
|
||||
uint8_t _graphstate[20]; // Internal last graph column/row state
|
||||
};
|
||||
|
||||
#endif
|
||||
4
firmware_adxl345_spi/lib/README
Normal file
4
firmware_adxl345_spi/lib/README
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
# Biblioteki
|
||||
|
||||
Ten folder zawiera biblioteki wykorzystane w projekcie.
|
||||
46
firmware_adxl345_spi/lib/RTClib/.github/ISSUE_TEMPLATE.md
vendored
Normal file
46
firmware_adxl345_spi/lib/RTClib/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||
improve the speed of resolution please review the following guidelines and
|
||||
common troubleshooting steps below before creating the issue:
|
||||
|
||||
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||
something isn't working as expected. In many cases the problem is a common issue
|
||||
that you will more quickly receive help from the forum community. GitHub issues
|
||||
are meant for known defects in the code. If you don't know if there is a defect
|
||||
in the code then start with troubleshooting on the forum first.
|
||||
|
||||
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||
check all of the steps and commands to run have been followed. Consult the
|
||||
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||
|
||||
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||
|
||||
- For uploading sketches or communicating with the board make sure you're using
|
||||
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||
very hard to tell the difference between a data and charge cable! Try using the
|
||||
cable with other devices or swapping to another cable to confirm it is not
|
||||
the problem.
|
||||
|
||||
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||
your board and plug in an external power supply. In many cases just
|
||||
plugging a board into your computer is not enough to power it and other
|
||||
peripherals.
|
||||
|
||||
- **Double check all soldering joints and connections.** Flakey connections
|
||||
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||
|
||||
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||
guarantee a clone board will have the same functionality and work as expected
|
||||
with this code and don't support them.
|
||||
|
||||
If you're sure this issue is a defect in the code and checked the steps above
|
||||
please fill in the following fields to provide enough troubleshooting information.
|
||||
You may delete the guideline and text above to just leave the following details:
|
||||
|
||||
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||
|
||||
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||
VERSION HERE**
|
||||
|
||||
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
||||
26
firmware_adxl345_spi/lib/RTClib/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
26
firmware_adxl345_spi/lib/RTClib/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||
Before you open the request please review the following guidelines and tips to
|
||||
help it be more easily integrated:
|
||||
|
||||
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||
of the code were modified.** This will help us understand any risks of integrating
|
||||
the code.
|
||||
|
||||
- **Describe any known limitations with your change.** For example if the change
|
||||
doesn't apply to a supported platform of the library please mention it.
|
||||
|
||||
- **Please run any tests or examples that can exercise your modified code.** We
|
||||
strive to not break users of the code and running tests/examples helps with this
|
||||
process.
|
||||
|
||||
Thank you again for contributing! We will try to test and integrate the change
|
||||
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||
can't immediately respond to every request. There is no need to bump or check in
|
||||
on a pull request (it will clutter the discussion of the request).
|
||||
|
||||
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||
priorities of the pull request. Don't fret, the open source community thrives on
|
||||
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||
|
||||
After reviewing the guidelines above you can delete this text from the pull request.
|
||||
32
firmware_adxl345_spi/lib/RTClib/.github/workflows/githubci.yml
vendored
Normal file
32
firmware_adxl345_spi/lib/RTClib/.github/workflows/githubci.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Arduino Library CI
|
||||
|
||||
on: [pull_request, push, repository_dispatch]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: adafruit/ci-arduino
|
||||
path: ci
|
||||
|
||||
- name: pre-install
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py main_platforms
|
||||
|
||||
- name: clang
|
||||
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
|
||||
|
||||
- name: doxygen
|
||||
env:
|
||||
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
|
||||
PRETTYNAME : "RTClib"
|
||||
run: bash ci/doxy_gen_and_deploy.sh src
|
||||
4
firmware_adxl345_spi/lib/RTClib/.gitignore
vendored
Normal file
4
firmware_adxl345_spi/lib/RTClib/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*~
|
||||
html
|
||||
Doxyfile*
|
||||
doxygen_sqlite3.db
|
||||
1
firmware_adxl345_spi/lib/RTClib/.piopm
Normal file
1
firmware_adxl345_spi/lib/RTClib/.piopm
Normal file
@@ -0,0 +1 @@
|
||||
{"type": "library", "name": "RTClib", "version": "2.1.4", "spec": {"owner": "adafruit", "id": 83, "name": "RTClib", "requirements": null, "uri": null}}
|
||||
77
firmware_adxl345_spi/lib/RTClib/README.md
Normal file
77
firmware_adxl345_spi/lib/RTClib/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# RTClib [](https://github.com/adafruit/RTClib/actions)[](http://adafruit.github.io/RTClib/html/index.html)
|
||||
|
||||
This is a fork of JeeLab's fantastic real time clock library for Arduino.
|
||||
|
||||
Works great with Adafruit RTC breakouts:
|
||||
|
||||
- [DS3231 Precision RTC](https://www.adafruit.com/product/3013) (breakout) and [Stemma QT version](https://www.adafruit.com/product/5188)
|
||||
- [PCF8523 RTC](https://www.adafruit.com/product/3295)
|
||||
- [DS1307 RTC](https://www.adafruit.com/product/3296)
|
||||
|
||||
Please note that dayOfTheWeek() ranges from 0 to 6 inclusive with 0 being 'Sunday'.
|
||||
|
||||
<!-- START COMPATIBILITY TABLE -->
|
||||
|
||||
## Compatibility
|
||||
|
||||
MCU | Tested Works | Doesn't Work | Not Tested | Notes
|
||||
------------------ | :----------: | :----------: | :---------: | -----
|
||||
Atmega328 @ 16MHz | X | | |
|
||||
Atmega328 @ 12MHz | X | | |
|
||||
Atmega32u4 @ 16MHz | X | | | Use SDA/SCL on pins D3 & D2
|
||||
Atmega32u4 @ 8MHz | X | | | Use SDA/SCL on pins D3 & D2
|
||||
ESP8266 | X | | | SDA/SCL default to pins 4 & 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL)
|
||||
Atmega2560 @ 16MHz | X | | | Use SDA/SCL on Pins 20 & 21
|
||||
ATSAM3X8E | X | | | Use SDA1 and SCL1
|
||||
ATSAM21D | X | | |
|
||||
ATtiny85 @ 16MHz | X | | |
|
||||
ATtiny85 @ 8MHz | X | | |
|
||||
Intel Curie @ 32MHz | | | X |
|
||||
STM32F2 | | | X |
|
||||
|
||||
* ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini
|
||||
* ATmega328 @ 12MHz : Adafruit Pro Trinket 3V
|
||||
* ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0
|
||||
* ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro
|
||||
* ESP8266 : Adafruit Huzzah
|
||||
* ATmega2560 @ 16MHz : Arduino Mega
|
||||
* ATSAM3X8E : Arduino Due
|
||||
* ATSAM21D : Arduino Zero, M0 Pro
|
||||
* ATtiny85 @ 16MHz : Adafruit Trinket 5V
|
||||
* ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V
|
||||
|
||||
<!-- END COMPATIBILITY TABLE -->
|
||||
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
|
||||
|
||||
# Dependencies
|
||||
* [Adafruit BusIO](https://github.com/adafruit/Adafruit_BusIO)
|
||||
|
||||
# Contributing
|
||||
|
||||
Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/RTClib/blob/master/code-of-conduct.md)
|
||||
before contributing to help this project stay welcoming.
|
||||
|
||||
## Documentation and doxygen
|
||||
For the detailed API documentation, see https://adafruit.github.io/RTClib/html/index.html
|
||||
Documentation is produced by doxygen. Contributions should include documentation for any new code added.
|
||||
|
||||
Some examples of how to use doxygen can be found in these guide pages:
|
||||
|
||||
https://learn.adafruit.com/the-well-automated-arduino-library/doxygen
|
||||
|
||||
https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips
|
||||
|
||||
## Code formatting and clang-format
|
||||
The code should be formatted according to the [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html), which is the default of the clang-format tool. The easiest way to ensure conformance is to [install clang-format](https://llvm.org/builds/) and run
|
||||
|
||||
```shell
|
||||
clang-format -i <source_file>
|
||||
```
|
||||
|
||||
See [Formatting with clang-format](https://learn.adafruit.com/the-well-automated-arduino-library/formatting-with-clang-format) for details.
|
||||
|
||||
Written by JeeLabs
|
||||
MIT license, check license.txt for more information
|
||||
All text above must be included in any redistribution
|
||||
|
||||
To install, use the Arduino Library Manager and search for "RTClib" and install the library.
|
||||
127
firmware_adxl345_spi/lib/RTClib/code-of-conduct.md
Normal file
127
firmware_adxl345_spi/lib/RTClib/code-of-conduct.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Adafruit Community Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and leaders pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level or type of
|
||||
experience, education, socio-economic status, nationality, personal appearance,
|
||||
race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
We are committed to providing a friendly, safe and welcoming environment for
|
||||
all.
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Be kind and courteous to others
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Collaborating with other community members
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and sexual attention or advances
|
||||
* The use of inappropriate images, including in a community member's avatar
|
||||
* The use of inappropriate language, including in a community member's nickname
|
||||
* Any spamming, flaming, baiting or other attention-stealing behavior
|
||||
* Excessive or unwelcome helping; answering outside the scope of the question
|
||||
asked
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate
|
||||
|
||||
The goal of the standards and moderation guidelines outlined here is to build
|
||||
and maintain a respectful community. We ask that you don’t just aim to be
|
||||
"technically unimpeachable", but rather try to be your best self.
|
||||
|
||||
We value many things beyond technical expertise, including collaboration and
|
||||
supporting others within our community. Providing a positive experience for
|
||||
other community members can have a much more significant impact than simply
|
||||
providing the correct answer.
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project leaders are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project leaders have the right and responsibility to remove, edit, or
|
||||
reject messages, comments, commits, code, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any community member for other behaviors that they deem
|
||||
inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Moderation
|
||||
|
||||
Instances of behaviors that violate the Adafruit Community Code of Conduct
|
||||
may be reported by any member of the community. Community members are
|
||||
encouraged to report these situations, including situations they witness
|
||||
involving other community members.
|
||||
|
||||
You may report in the following ways:
|
||||
|
||||
In any situation, you may send an email to <support@adafruit.com>.
|
||||
|
||||
On the Adafruit Discord, you may send an open message from any channel
|
||||
to all Community Helpers by tagging @community helpers. You may also send an
|
||||
open message from any channel, or a direct message to @kattni#1507,
|
||||
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
|
||||
@Andon#8175.
|
||||
|
||||
Email and direct message reports will be kept confidential.
|
||||
|
||||
In situations on Discord where the issue is particularly egregious, possibly
|
||||
illegal, requires immediate action, or violates the Discord terms of service,
|
||||
you should also report the message directly to Discord.
|
||||
|
||||
These are the steps for upholding our community’s standards of conduct.
|
||||
|
||||
1. Any member of the community may report any situation that violates the
|
||||
Adafruit Community Code of Conduct. All reports will be reviewed and
|
||||
investigated.
|
||||
2. If the behavior is an egregious violation, the community member who
|
||||
committed the violation may be banned immediately, without warning.
|
||||
3. Otherwise, moderators will first respond to such behavior with a warning.
|
||||
4. Moderators follow a soft "three strikes" policy - the community member may
|
||||
be given another chance, if they are receptive to the warning and change their
|
||||
behavior.
|
||||
5. If the community member is unreceptive or unreasonable when warned by a
|
||||
moderator, or the warning goes unheeded, they may be banned for a first or
|
||||
second offense. Repeated offenses will result in the community member being
|
||||
banned.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct and the enforcement policies listed above apply to all
|
||||
Adafruit Community venues. This includes but is not limited to any community
|
||||
spaces (both public and private), the entire Adafruit Discord server, and
|
||||
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
|
||||
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
|
||||
interaction at a conference.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. As a community
|
||||
member, you are representing our community, and are expected to behave
|
||||
accordingly.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 1.4, available at
|
||||
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
|
||||
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
|
||||
|
||||
For other projects adopting the Adafruit Community Code of
|
||||
Conduct, please contact the maintainers of those projects for enforcement.
|
||||
If you wish to use this code of conduct for your own project, consider
|
||||
explicitly mentioning your moderation policy or making a copy with your
|
||||
own moderation policy so as to avoid confusion.
|
||||
@@ -0,0 +1,122 @@
|
||||
/* Example implementation of an alarm using DS3231
|
||||
*
|
||||
* VCC and GND of RTC should be connected to some power source
|
||||
* SDA, SCL of RTC should be connected to SDA, SCL of arduino
|
||||
* SQW should be connected to CLOCK_INTERRUPT_PIN
|
||||
* CLOCK_INTERRUPT_PIN needs to work with interrupts
|
||||
*/
|
||||
|
||||
#include <RTClib.h>
|
||||
// #include <Wire.h>
|
||||
|
||||
RTC_DS3231 rtc;
|
||||
|
||||
// the pin that is connected to SQW
|
||||
#define CLOCK_INTERRUPT_PIN 2
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initializing the rtc
|
||||
if(!rtc.begin()) {
|
||||
Serial.println("Couldn't find RTC!");
|
||||
Serial.flush();
|
||||
while (1) delay(10);
|
||||
}
|
||||
|
||||
if(rtc.lostPower()) {
|
||||
// this will adjust to the date and time at compilation
|
||||
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
|
||||
}
|
||||
|
||||
//we don't need the 32K Pin, so disable it
|
||||
rtc.disable32K();
|
||||
|
||||
// Making it so, that the alarm will trigger an interrupt
|
||||
pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING);
|
||||
|
||||
// set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far)
|
||||
// if not done, this easily leads to problems, as both register aren't reset on reboot/recompile
|
||||
rtc.clearAlarm(1);
|
||||
rtc.clearAlarm(2);
|
||||
|
||||
// stop oscillating signals at SQW Pin
|
||||
// otherwise setAlarm1 will fail
|
||||
rtc.writeSqwPinMode(DS3231_OFF);
|
||||
|
||||
// turn off alarm 2 (in case it isn't off already)
|
||||
// again, this isn't done at reboot, so a previously set alarm could easily go overlooked
|
||||
rtc.disableAlarm(2);
|
||||
|
||||
// schedule an alarm 10 seconds in the future
|
||||
if(!rtc.setAlarm1(
|
||||
rtc.now() + TimeSpan(10),
|
||||
DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options
|
||||
)) {
|
||||
Serial.println("Error, alarm wasn't set!");
|
||||
}else {
|
||||
Serial.println("Alarm will happen in 10 seconds!");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// print current time
|
||||
char date[10] = "hh:mm:ss";
|
||||
rtc.now().toString(date);
|
||||
Serial.print(date);
|
||||
|
||||
// the stored alarm value + mode
|
||||
DateTime alarm1 = rtc.getAlarm1();
|
||||
Ds3231Alarm1Mode alarm1mode = rtc.getAlarm1Mode();
|
||||
char alarm1Date[12] = "DD hh:mm:ss";
|
||||
alarm1.toString(alarm1Date);
|
||||
Serial.print(" [Alarm1: ");
|
||||
Serial.print(alarm1Date);
|
||||
Serial.print(", Mode: ");
|
||||
switch (alarm1mode) {
|
||||
case DS3231_A1_PerSecond: Serial.print("PerSecond"); break;
|
||||
case DS3231_A1_Second: Serial.print("Second"); break;
|
||||
case DS3231_A1_Minute: Serial.print("Minute"); break;
|
||||
case DS3231_A1_Hour: Serial.print("Hour"); break;
|
||||
case DS3231_A1_Date: Serial.print("Date"); break;
|
||||
case DS3231_A1_Day: Serial.print("Day"); break;
|
||||
}
|
||||
|
||||
// the value at SQW-Pin (because of pullup 1 means no alarm)
|
||||
Serial.print("] SQW: ");
|
||||
Serial.print(digitalRead(CLOCK_INTERRUPT_PIN));
|
||||
|
||||
// whether a alarm fired
|
||||
Serial.print(" Fired: ");
|
||||
Serial.print(rtc.alarmFired(1));
|
||||
|
||||
// Serial.print(" Alarm2: ");
|
||||
// Serial.println(rtc.alarmFired(2));
|
||||
// control register values (see https://datasheets.maximintegrated.com/en/ds/DS3231.pdf page 13)
|
||||
// Serial.print(" Control: 0b");
|
||||
// Serial.println(read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), BIN);
|
||||
|
||||
// resetting SQW and alarm 1 flag
|
||||
// using setAlarm1, the next alarm could now be configurated
|
||||
if (rtc.alarmFired(1)) {
|
||||
rtc.clearAlarm(1);
|
||||
Serial.print(" - Alarm cleared");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void onAlarm() {
|
||||
Serial.println("Alarm occured!");
|
||||
}
|
||||
|
||||
/*static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write((byte)reg);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(addr, (byte)1);
|
||||
return Wire.read();
|
||||
}*/
|
||||
@@ -0,0 +1,120 @@
|
||||
/* Using DS3231 (or other supported RTC) with a custom TwoWire instance
|
||||
*
|
||||
* If using a microcontroller which supports additional i2c ports,
|
||||
* such as the SAMD21's SERCOMX, a user can define a custom i2c bus
|
||||
* to use with an RTC.
|
||||
* This example builds the custom i2c bus using SERCOM0 and leverages the "wiring_private.h" APIs
|
||||
*
|
||||
* Connecting the device:
|
||||
* VCC and GND of RTC should be connected to some power source
|
||||
* SDA, SCL of RTC should be connected to the custom SDA and SCL pins.
|
||||
* In this particular example we are using a Nano 33 IoT and routing
|
||||
* the custom Wire instance over pins 6 (SDA) and 5 (SCL)
|
||||
*
|
||||
* This example will work with Arduino Zero, any Arduino MKR board based on SAMD21, Nano 33 IoT
|
||||
* and any board by Adafruit, Sparkfun, Seeed Studio based on the same microcontroller
|
||||
*
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include "wiring_private.h"
|
||||
#include <RTClib.h>
|
||||
|
||||
/* Defining the custom TwoWire instance for SAMD21 */
|
||||
TwoWire myWire(&sercom0, 6, 5); // Create the new wire instance assigning it to pin 0 and 1
|
||||
extern "C"{
|
||||
void SERCOM0_Handler(void);
|
||||
|
||||
void SERCOM0_Handler(void) {
|
||||
|
||||
myWire.onService();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Creating a new DS3231 object */
|
||||
RTC_DS3231 myRTC;
|
||||
|
||||
String daysNames[] = {
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday"
|
||||
};
|
||||
String monthsNames[] = {
|
||||
"-",
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(57600);
|
||||
Serial.println("start");
|
||||
|
||||
unsigned long setupStartTime = millis();
|
||||
/*** Waiting for Serial to be ready or timeout ***/
|
||||
while(!Serial && millis() - setupStartTime < 3000);
|
||||
|
||||
/*
|
||||
* Initialising pins 6 and 5 to be routed to the SERCOM0 pads 0 and 1 in order
|
||||
* to be used as SDA and SCL. Without this step the periphearl won't be patched through
|
||||
*/
|
||||
pinPeripheral(6, PIO_SERCOM_ALT); // PAD[0] //Assign SDA function to pin 0
|
||||
pinPeripheral(5, PIO_SERCOM_ALT); // PAD[1] //Assign SCL function to pin 1
|
||||
|
||||
/* We now pass our custom TwoWire object to the RTC instance */
|
||||
myRTC.begin(&myWire);
|
||||
|
||||
/*
|
||||
* From this moment on every operation on the RTC will work as expected
|
||||
* But the i2c bus being used will be the one we manually created using SERCOM0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Creating a Date object with
|
||||
* YEAR, MONTH, DAY (2021, January, 1)
|
||||
* HOUR, MINUTE, SECONDS (0, 0, 0)
|
||||
* Midnight of January 1st, 2021
|
||||
*/
|
||||
DateTime newDT = DateTime(2021, 1, 1, 0, 0, 0);
|
||||
|
||||
/* Pushing that date/time to the RTC */
|
||||
myRTC.adjust(newDT);
|
||||
Serial.println("setup done");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
/* creating a temporary date/time object to store the data coming from the RTC */
|
||||
DateTime dt = myRTC.now();
|
||||
|
||||
/* printing that data to the Serial port in a meaningful format */
|
||||
Serial.println("************");
|
||||
Serial.print(daysNames[dt.dayOfTheWeek()]);
|
||||
Serial.print(" ");
|
||||
Serial.print(monthsNames[dt.month()]);
|
||||
Serial.print(" ");
|
||||
Serial.print(dt.day());
|
||||
Serial.print(", ");
|
||||
Serial.println(dt.year());
|
||||
Serial.print(dt.hour());
|
||||
Serial.print(":");
|
||||
Serial.print(dt.minute());
|
||||
Serial.print(":");
|
||||
Serial.println(dt.second());
|
||||
/* Delays are bad, but let's not flood the Serial for this silly example */
|
||||
delay(500);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user