migrate to local environment #39

Merged
james merged 17 commits from chore/migrate-to-local into main 2023-11-24 20:15:54 +13:00
22 changed files with 523 additions and 425 deletions

5
.check.exs Normal file
View file

@ -0,0 +1,5 @@
[
tools: [
{:sobelow, false}
]
]

View file

@ -1,164 +0,0 @@
# This file contains the configuration for Credo and you are probably reading
# this after creating it with `mix credo.gen.config`.
#
# If you find anything wrong or unclear in this file, please report an
# issue on GitHub: https://github.com/rrrene/credo/issues
#
%{
#
# You can have as many configs as you like in the `configs:` field.
configs: [
%{
#
# Run any exec using `mix credo -C <name>`. If no exec name is given
# "default" is used.
#
name: "default",
#
# These are the files included in the analysis:
files: %{
#
# You can give explicit globs or simply directories.
# In the latter case `**/*.{ex,exs}` will be used.
#
included: ["lib/", "src/", "test/", "web/", "apps/"],
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"]
},
#
# Load and configure plugins here:
#
plugins: [],
#
# If you create your own checks, you must specify the source files for
# them here, so they can be loaded by Credo before running the analysis.
#
requires: [],
#
# If you want to enforce a style guide and need a more traditional linting
# experience, you can change `strict` to `true` below:
#
strict: false,
#
# If you want to use uncolored output by default, you can change `color`
# to `false` below:
#
color: true,
#
# You can customize the parameters of any check by adding a second element
# to the tuple.
#
# To disable a check put `false` as second element:
#
# {Credo.Check.Design.DuplicatedCode, false}
#
checks: [
#
## Consistency Checks
#
{Credo.Check.Consistency.ExceptionNames, []},
{Credo.Check.Consistency.LineEndings, []},
{Credo.Check.Consistency.ParameterPatternMatching, []},
{Credo.Check.Consistency.SpaceAroundOperators, false},
{Credo.Check.Consistency.SpaceInParentheses, []},
{Credo.Check.Consistency.TabsOrSpaces, []},
#
## Design Checks
#
# You can customize the priority of any check
# Priority values are: `low, normal, high, higher`
#
{Credo.Check.Design.AliasUsage,
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
#
{Credo.Check.Design.TagTODO, [exit_status: 2]},
{Credo.Check.Design.TagFIXME, []},
#
## Readability Checks
#
{Credo.Check.Readability.AliasOrder, []},
{Credo.Check.Readability.FunctionNames, []},
{Credo.Check.Readability.LargeNumbers, []},
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
{Credo.Check.Readability.ModuleAttributeNames, []},
{Credo.Check.Readability.ModuleDoc, []},
{Credo.Check.Readability.ModuleNames, []},
{Credo.Check.Readability.ParenthesesInCondition, []},
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
{Credo.Check.Readability.PredicateFunctionNames, []},
{Credo.Check.Readability.PreferImplicitTry, []},
{Credo.Check.Readability.RedundantBlankLines, []},
{Credo.Check.Readability.Semicolons, []},
{Credo.Check.Readability.SpaceAfterCommas, []},
{Credo.Check.Readability.StringSigils, []},
{Credo.Check.Readability.TrailingBlankLine, []},
{Credo.Check.Readability.TrailingWhiteSpace, []},
# TODO: enable by default in Credo 1.1
{Credo.Check.Readability.UnnecessaryAliasExpansion, false},
{Credo.Check.Readability.VariableNames, []},
#
## Refactoring Opportunities
#
{Credo.Check.Refactor.CondStatements, []},
{Credo.Check.Refactor.CyclomaticComplexity, []},
{Credo.Check.Refactor.FunctionArity, []},
{Credo.Check.Refactor.LongQuoteBlocks, []},
{Credo.Check.Refactor.MapInto, []},
{Credo.Check.Refactor.MatchInCondition, []},
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
{Credo.Check.Refactor.Nesting, []},
{Credo.Check.Refactor.UnlessWithElse, []},
{Credo.Check.Refactor.WithClauses, []},
#
## Warnings
#
{Credo.Check.Warning.BoolOperationOnSameValues, []},
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
{Credo.Check.Warning.IExPry, []},
{Credo.Check.Warning.IoInspect, []},
{Credo.Check.Warning.LazyLogging, []},
{Credo.Check.Warning.OperationOnSameValues, []},
{Credo.Check.Warning.OperationWithConstantResult, []},
{Credo.Check.Warning.RaiseInsideRescue, []},
{Credo.Check.Warning.UnusedEnumOperation, []},
{Credo.Check.Warning.UnusedFileOperation, []},
{Credo.Check.Warning.UnusedKeywordOperation, []},
{Credo.Check.Warning.UnusedListOperation, []},
{Credo.Check.Warning.UnusedPathOperation, []},
{Credo.Check.Warning.UnusedRegexOperation, []},
{Credo.Check.Warning.UnusedStringOperation, []},
{Credo.Check.Warning.UnusedTupleOperation, []},
#
# Controversial and experimental checks (opt-in, just replace `false` with `[]`)
#
{Credo.Check.Consistency.MultiAliasImportRequireUse, false},
{Credo.Check.Consistency.UnusedVariableNames, false},
{Credo.Check.Design.DuplicatedCode, false},
{Credo.Check.Readability.AliasAs, false},
{Credo.Check.Readability.MultiAlias, false},
{Credo.Check.Readability.Specs, false},
{Credo.Check.Readability.SinglePipe, false},
{Credo.Check.Refactor.ABCSize, false},
{Credo.Check.Refactor.AppendSingleItem, false},
{Credo.Check.Refactor.DoubleBooleanNegation, false},
{Credo.Check.Refactor.ModuleDependencies, false},
{Credo.Check.Refactor.PipeChainStart, false},
{Credo.Check.Refactor.VariableRebinding, false},
{Credo.Check.Warning.MapGetUnsafePass, false},
{Credo.Check.Warning.UnsafeToAtom, false}
#
# Custom checks can be created using `mix credo.gen.check`.
#
]
}
]
}

15
.doctor.exs Normal file
View file

@ -0,0 +1,15 @@
%Doctor.Config{
ignore_modules: [Wafer.Registers],
ignore_paths: [],
min_module_doc_coverage: 40,
min_module_spec_coverage: 0,
min_overall_doc_coverage: 50,
min_overall_moduledoc_coverage: 100,
min_overall_spec_coverage: 0,
exception_moduledoc_required: true,
raise: false,
reporter: Doctor.Reporters.Full,
struct_type_spec_required: true,
umbrella: false,
failed: false
}

389
.drone.yml Normal file
View file

@ -0,0 +1,389 @@
kind: pipeline
type: docker
name: build
platform:
os: linux
arch: arm64
steps:
- name: restore ASDF cache
image: meltwater/drone-cache
pull: "always"
environment:
AWS_ACCESS_KEY_ID:
from_secret: ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: SECRET_ACCESS_KEY
AWS_PLUGIN_PATH_STYLE: true
settings:
restore: true
endpoint:
from_secret: S3_ENDPOINT
bucket:
from_secret: CACHE_BUCKET
region: us-east-1
path-style: true
cache_key: 'asdf-{{ os }}-{{ arch }}-{{ checksum ".tool-versions" }}'
mount:
- .asdf
- name: restore build cache
image: meltwater/drone-cache
environment:
AWS_ACCESS_KEY_ID:
from_secret: ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: SECRET_ACCESS_KEY
AWS_PLUGIN_PATH_STYLE: true
settings:
restore: true
endpoint:
from_secret: S3_ENDPOINT
bucket:
from_secret: CACHE_BUCKET
region: us-east-1
path-style: true
cache_key: 'elixir-{{ checksum "mix.lock" }}-{{ checksum ".tool-versions" }}'
mount:
- deps
- _build
- .hex
- .mix
- .rebar3
- name: install dependencies
image: code.harton.nz/james/asdf_container:latest
pull: "always"
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
ASDF_DIR: /root/.asdf
depends_on:
- restore ASDF cache
- restore build cache
commands:
- asdf_install
- rm -rf .asdf/downloads
- . $ASDF_DIR/asdf.sh
- mix local.hex --if-missing --force
- mix local.rebar --if-missing --force
- mix deps.get
- mix deps.compile
- mix dialyzer --plt
- name: store ASDF cache
image: meltwater/drone-cache
environment:
AWS_ACCESS_KEY_ID:
from_secret: ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: SECRET_ACCESS_KEY
AWS_PLUGIN_PATH_STYLE: true
depends_on:
- install dependencies
settings:
rebuild: true
override: false
endpoint:
from_secret: S3_ENDPOINT
bucket:
from_secret: CACHE_BUCKET
region: us-east-1
path-style: true
cache_key: 'asdf-{{ os }}-{{ arch }}-{{ checksum ".tool-versions" }}'
mount:
- .asdf
- name: store build cache
image: meltwater/drone-cache
environment:
AWS_ACCESS_KEY_ID:
from_secret: ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: SECRET_ACCESS_KEY
AWS_PLUGIN_PATH_STYLE: true
depends_on:
- install dependencies
settings:
rebuild: true
override: false
endpoint:
from_secret: S3_ENDPOINT
bucket:
from_secret: CACHE_BUCKET
region: us-east-1
path-style: true
cache_key: 'elixir-{{ checksum "mix.lock" }}-{{ checksum ".tool-versions" }}'
mount:
- deps
- _build
- .hex
- .mix
- .rebar3
- name: mix compile
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- install dependencies
commands:
- asdf mix compile --warnings-as-errors
- name: mix test
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- asdf mix test
- name: mix test.sense_hat
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
SENSE_HAT_PRESENT: true
privileged: true
depends_on:
- mix compile
commands:
- asdf mix test
- name: mix credo
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- asdf mix credo --strict
- name: mix hex.audit
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- asdf mix hex.audit
- name: mix format
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- asdf mix format --check-formatted
- name: mix deps.unlock
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- asdf mix deps.unlock --check-unused
- name: mix doctor
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- asdf mix doctor --full
- name: mix git_ops.check_message
image: code.harton.nz/james/asdf_container:latest
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
depends_on:
- mix compile
commands:
- git log -1 --format=%s > .last_commit_message
- asdf mix git_ops.check_message .last_commit_message
- name: mix git_ops.release
image: code.harton.nz/james/asdf_container:latest
when:
branch:
- main
event:
exclude:
- pull_request
depends_on:
- mix test
- mix credo
- mix hex.audit
- mix format
- mix test.sense_hat
- mix deps.unlock
- mix doctor
- mix git_ops.check_message
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
ASDF_DIR: /root/.asdf
DRONE_TOKEN:
from_secret: DRONE_TOKEN
commands:
- git fetch --tags
- . $ASDF_DIR/asdf.sh
- mix git_ops.project_info --format=shell > before.env
- mix git_ops.release --yes --no-major || true
- mix git_ops.project_info --format=shell > after.env
- . ./before.env
- export OLD_APP_VERSION=$${APP_VERSION}
- . ./after.env
- export NEW_APP_VERSION=$${APP_VERSION}
- if [ "v$${OLD_APP_VERSION}" != "v$${NEW_APP_VERSION}" ]; then
- export GIT_URL=$(echo $DRONE_GIT_HTTP_URL | sed -e "s/:\\/\\//:\\/\\/$DRONE_REPO_OWNER:$DRONE_TOKEN@/")
- git push $${GIT_URL} "HEAD:${DRONE_COMMIT_REF}" "refs/tags/v$${NEW_APP_VERSION}"
- fi
- name: build artifacts
image: code.harton.nz/james/asdf_container:latest
when:
event:
- tag
refs:
include:
- refs/tags/v*
depends_on:
- mix test
- mix credo
- mix hex.audit
- mix format
- mix test.sense_hat
- mix deps.unlock
- mix doctor
- mix git_ops.check_message
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
ASDF_DIR: /root/.asdf
commands:
- . $ASDF_DIR/asdf.sh
- mix git_ops.project_info --format=shell > app.env
- . ./app.env
- mkdir artifacts
- mix hex.build -o "artifacts/$${APP_NAME}-$${APP_VERSION}-pkg.tar"
- gzip "artifacts/$${APP_NAME}-$${APP_VERSION}-pkg.tar"
- mix docs
- tar zcvf "artifacts/$${APP_NAME}-$${APP_VERSION}-docs.tar.gz" doc/
- git tag -l --format='%(contents:subject)' v$${APP_VERSION} > tag_subject
- git tag -l --format='%(contents:body)' v$${APP_VERSION} > tag_body
- name: gitea release
image: plugins/gitea-release
when:
event:
- tag
refs:
include:
- refs/tags/v*
depends_on:
- build artifacts
settings:
api_key:
from_secret: DRONE_TOKEN
base_url: https://code.harton.nz
files: artifacts/*.tar.gz
checksum: sha256
title: tag_subject
note: tag_body
- name: docs release
when:
event:
- tag
refs:
include:
- refs/tags/v*
image: minio/mc
environment:
S3_ENDPOINT:
from_secret: S3_ENDPOINT
ACCESS_KEY:
from_secret: ACCESS_KEY_ID
SECRET_KEY:
from_secret: SECRET_ACCESS_KEY
depends_on:
- build artifacts
commands:
- mc alias set store $${S3_ENDPOINT} $${ACCESS_KEY} $${SECRET_KEY}
- mc mb -p store/docs.harton.nz
- mc anonymous set download store/docs.harton.nz
- mc mirror --overwrite doc/ store/docs.harton.nz/$${DRONE_REPO}/$${DRONE_TAG}
- mc mirror --overwrite doc/ store/docs.harton.nz/$${DRONE_REPO}
- name: hex release
image: code.harton.nz/james/asdf_container:latest
when:
event:
- tag
refs:
include:
- refs/tags/v*
depends_on:
- build artifacts
environment:
MIX_ENV: test
HEX_HOME: /drone/src/.hex
MIX_HOME: /drone/src/.mix
REBAR_BASE_DIR: /drone/src/.rebar3
ASDF_DATA_DIR: /drone/src/.asdf
ASDF_DIR: /root/.asdf
HEX_API_KEY:
from_secret: HEX_API_KEY
commands:
- . $ASDF_DIR/asdf.sh
- mix hex.publish --yes

View file

@ -1,177 +0,0 @@
image: elixir:latest
stages:
- build
- test
- release
variables:
MIX_ENV: "test"
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/"
HEX_HOME: "$CI_PROJECT_DIR/.hex"
MIX_HOME: "$CI_PROJECT_DIR/.mix"
build:
image: elixir:latest
stage: build
cache:
key: "$CI_JOB_NAME"
paths:
- deps
- _build
- .hex
- .mix
script:
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
- mix deps.compile
- mix git_ops.project_info -f dotenv > project_info.env
artifacts:
paths:
- _build/
- deps/
- .hex
- .mix
reports:
dotenv: project_info.env
test:
image: elixir:latest
dependencies:
- build
stage: test
script:
- mix test
build_and_test_i2c_1_x:
image: elixir:latest
stage: test
cache:
key: "$CI_JOB_NAME"
paths:
- deps
- _build
- .hex
- .mix
script:
- mix local.hex --force
- mix local.rebar --force
- CI_I2C_1_X=true mix deps.get
- mix deps.compile
- mix test
artifacts:
paths:
- _build/
- deps/
- .hex
- .mix
integrate:
image: elixir:latest
stage: test
tags:
- sense-hat
script:
- mix local.hex --force
- mix local.rebar --force
- rm -rf deps _build
- mix deps.get
- mix deps.compile
- SENSE_HAT_PRESENT=true mix test
credo:
image: elixir:latest
dependencies:
- build
stage: test
script:
- mix credo
audit:
image: elixir:latest
dependencies:
- build
stage: test
script:
- mix hex.audit
format:
image: elixir:latest
dependencies:
- build
stage: test
script:
- mix format --check-formatted
pages:
image: elixir:latest
dependencies:
- build
stage: release
script:
- mix docs -o public
artifacts:
paths:
- public
only:
- main
git_ops:
image: elixir:latest
dependencies:
- build
stage: release
only:
refs:
- main
except:
variables:
- $CI_COMMIT_MESSAGE =~ /chore\:\ release version/
script:
- |
export OLD_APP_VERSION=$APP_VERSION
mkdir -p artifacts
git config --global user.name "Gitlab Runner for ${GITLAB_USER_NAME}"
git config --global user.email "${GITLAB_USER_EMAIL}"
mix git_ops.release --yes || true
mix git_ops.project_info -f shell > artifacts/env
source artifacts/env
if [ "v${OLD_APP_VERSION}" != "v${APP_VERSION}" ]; then
mix hex.build -o "artifacts/${APP_NAME}-${APP_VERSION}.tar"
gzip "artifacts/${APP_NAME}-${APP_VERSION}.tar"
mix docs && tar zcvf "artifacts/${APP_NAME}-${APP_VERSION}-docs.tar.gz" doc/
curl --header "JOB_TOKEN: ${CI_JOB_TOKEN}" --upload-file "artifacts/${APP_NAME}-${APP_VERSION}.tar.gz" "${PACKAGE_REGISTRY_URL}/${APP_NAME}/${APP_VERSION}/${APP_NAME}-${APP_VERSION}.tar.gz"
curl --header "JOB_TOKEN: ${CI_JOB_TOKEN}" --upload-file "artifacts/${APP_NAME}-${APP_VERSION}-docs.tar.gz" "${PACKAGE_REGISTRY_URL}/${APP_NAME}/${APP_VERSION}/${APP_NAME}-${APP_VERSION}-docs.tar.gz"
git push "https://project_${CI_PROJECT_ID}_bot:${RELEASE_TOKEN}@gitlab.com/${CI_PROJECT_PATH}.git" "HEAD:${CI_COMMIT_REF_NAME}" "refs/tags/v${APP_VERSION}"
fi
artifacts:
paths:
- artifacts/*
release-gitlab:
image: registry.gitlab.com/gitlab-org/release-cli:latest
dependencies:
- build
stage: release
only:
- tags
- /^v\d+\.\d+\.\d+(-\w+)?$/
script:
- release-cli create \
--name "Release ${APP_NAME} ${APP_VERSION}" \
--description "./CHANGELOG.md" \
--tag-name "v${APP_VERSION}" \
--assets-link "{\"name\":\"${APP_NAME}-${APP_VERSION}.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/${APP_NAME}/${APP_VERSION}/${APP_NAME}-${APP_VERSION}.tar.gz\"}" \
--assets-link "{\"name\":\"${APP_NAME}-${APP_VERSION}-docs.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/${APP_NAME}/${APP_VERSION}/${APP_NAME}-${APP_VERSION}-docs.tar.gz\"}"
release-hex:
image: elixir:latest
dependencies:
- build
stage: release
only:
- tags
- /^v\d+\.\d+\.\d+(-\w+)?$/
script:
- mix hex.publish --yes

2
.tool-versions Normal file
View file

@ -0,0 +1,2 @@
erlang 26.1.2
elixir 1.15.7

View file

@ -1,6 +1,6 @@
# Wafer
[![pipeline status](https://gitlab.com/jimsy/wafer/badges/main/pipeline.svg)](https://gitlab.com/jimsy/wafer/commits/main)
[![Build Status](https://drone.harton.nz/api/badges/james/wafer/status.svg?ref=refs/heads/main)](https://drone.harton.nz/james/wafer)
[![Hex.pm](https://img.shields.io/hexpm/v/wafer.svg)](https://hex.pm/packages/wafer)
[![Hippocratic License HL3-FULL](https://img.shields.io/static/v1?label=Hippocratic%20License&message=HL3-FULL&labelColor=5e2751&color=bc8c3d)](https://firstdonoharm.dev/version/3/0/full.html)
@ -10,9 +10,10 @@ Wafer provides Elixir protocols for interacting with device registers and dealin
Wafer implements the [GPIO](https://hexdocs.pm/wafer/Wafer.GPIOProto.html) and [Chip](https://hexdocs.pm/wafer/Wafer.Chip.html) protocols for [ElixirALE](https://hex.pm/packages/elixir_ale)'s GPIO and I2C drivers, [Circuits.GPIO](https://hex.pm/packages/circuits_gpio) and [Circuits.I2C](https://hex.pm/packages/circuits_i2c). Implementing it for SPI should also be trivial, I just don't have any SPI devices to test with at the moment.
Documentation for the main branch can always be found [here](https://jimsy.gitlab.io/wafer/).
Documentation for the main branch can always be found [here](https://docs.harton.nz/james/wafer/).
Some examples of how to use this project:
- [Augie](https://gitlab.com/jimsy/augie), a hexapod robot.
- [PCA9641](https://gitlab.com/jimsy/pca9641), an example of how easy it is to write a driver with Wafer.
@ -135,6 +136,10 @@ Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_do
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/wafer](https://hexdocs.pm/wafer).
## Gitlab Mirror
This repository is mirrored [on Gitlab](https://gitlab.com/jimsy/wafer) from it's primary location [on my Forgejo instance](https://code.harton.nz/james/smokestack). Feel free to raise issues and open PRs on Gitlab.
## License
This software is licensed under the terms of the

View file

@ -5,6 +5,7 @@ defmodule Wafer.Application do
use Application
@doc false
def start(_type, _args) do
children = [
{Registry, [keys: :duplicate, name: Wafer.InterruptRegistry]},

View file

@ -57,11 +57,11 @@ defimpl Wafer.GPIO, for: Wafer.Driver.Circuits.GPIO do
import Wafer.Guards
def read(%{ref: ref}) when is_reference(ref) do
case(Wrapper.read(ref)) do
case Wrapper.read(ref) do
value when is_pin_value(value) -> {:ok, value}
{:error, reason} -> {:error, reason}
other -> {:error, "Invalid response from driver: #{inspect(other)}"}
end
rescue
error -> {:error, error}
end
def write(%{ref: ref} = conn, value) when is_reference(ref) and is_pin_value(value) do
@ -80,11 +80,11 @@ defimpl Wafer.GPIO, for: Wafer.Driver.Circuits.GPIO do
def enable_interrupt(conn, pin_condition, metadata \\ nil)
when is_pin_condition(pin_condition) do
with :ok <- Dispatcher.enable(conn, pin_condition, metadata), do: {:ok, conn}
Dispatcher.enable(conn, pin_condition, metadata)
end
def disable_interrupt(conn, pin_condition) when is_pin_condition(pin_condition) do
with :ok <- Dispatcher.disable(conn, pin_condition), do: {:ok, conn}
Dispatcher.disable(conn, pin_condition)
end
def pull_mode(%{ref: ref} = conn, mode) when is_reference(ref) and is_pin_pull_mode(mode) do

View file

@ -1,7 +1,7 @@
defmodule Wafer.Driver.Circuits.I2C do
defstruct ~w[address bus ref]a
defstruct ~w[address bus conn]a
@behaviour Wafer.Conn
alias Circuits.I2C.I2CDev
alias Circuits.I2C.Bus
alias Wafer.Driver.Circuits.I2C.Wrapper
alias Wafer.I2C
import Wafer.Guards
@ -12,7 +12,7 @@ defmodule Wafer.Driver.Circuits.I2C do
Implements the `Wafer.Conn` behaviour as well as the `Wafer.Chip` and `Wafer.I2C` protocols.
"""
@type t :: %__MODULE__{address: I2C.address(), bus: binary, ref: reference}
@type t :: %__MODULE__{address: I2C.address(), bus: binary, conn: Bus.t()}
@type options :: [option]
@type option :: {:bus_name, binary} | {:address, I2C.address()} | {:force, boolean}
@ -24,10 +24,10 @@ defmodule Wafer.Driver.Circuits.I2C do
def acquire(opts) when is_list(opts) do
with {:ok, bus} when is_binary(bus) <- Keyword.fetch(opts, :bus_name),
{:ok, address} when is_i2c_address(address) <- Keyword.fetch(opts, :address),
{:ok, ref} when is_reference(ref) or is_struct(ref, I2CDev) <- Wrapper.open(bus),
devices when is_list(devices) <- Wrapper.detect_devices(ref),
{:ok, conn} <- Wrapper.open(bus),
devices when is_list(devices) <- Wrapper.detect_devices(conn),
true <- Keyword.get(opts, :force, false) || Enum.member?(devices, address) do
{:ok, %__MODULE__{bus: bus, address: address, ref: ref}}
{:ok, %__MODULE__{bus: bus, address: address, conn: conn}}
else
false ->
{:error, "No device detected at address. Pass `force: true` to override."}
@ -49,24 +49,24 @@ defimpl Wafer.Release, for: Wafer.Driver.Circuits.I2C do
Release all resources associated with this device.
"""
@spec release(I2C.t()) :: :ok | {:error, reason :: any}
def release(%I2C{ref: ref} = _conn), do: Wrapper.close(ref)
def release(%I2C{conn: conn} = _conn), do: Wrapper.close(conn)
end
defimpl Wafer.Chip, for: Wafer.Driver.Circuits.I2C do
alias Wafer.Driver.Circuits.I2C.Wrapper
import Wafer.Guards
def read_register(%{ref: ref, address: address}, register_address, bytes)
def read_register(%{conn: conn, address: address}, register_address, bytes)
when is_i2c_address(address) and is_register_address(register_address) and
is_byte_size(bytes),
do: Wrapper.write_read(ref, address, <<register_address>>, bytes)
do: Wrapper.write_read(conn, address, <<register_address>>, bytes)
def read_register(_conn, _register_address, _bytes), do: {:error, "Invalid argument"}
def write_register(%{ref: ref, address: address} = conn, register_address, data)
def write_register(%{conn: inner, address: address} = conn, register_address, data)
when is_i2c_address(address) and is_register_address(register_address) and
is_binary(data) do
with :ok <- Wrapper.write(ref, address, <<register_address, data::binary>>), do: {:ok, conn}
with :ok <- Wrapper.write(inner, address, <<register_address, data::binary>>), do: {:ok, conn}
end
def write_register(_conn, _register_address, _data), do: {:error, "Invalid argument"}
@ -86,36 +86,35 @@ defimpl Wafer.I2C, for: Wafer.Driver.Circuits.I2C do
import Wafer.Guards
alias Wafer.Driver.Circuits.I2C.Wrapper
def read(%{ref: ref, address: address}, bytes, options \\ [])
def read(%{conn: conn, address: address}, bytes, options \\ [])
when is_i2c_address(address) and is_byte_size(bytes) and
is_list(options) do
case Wrapper.read(ref, address, bytes, options) do
case Wrapper.read(conn, address, bytes, options) do
{:ok, data} when is_binary(data) and byte_size(data) == bytes -> {:ok, data}
{:error, reason} -> {:error, reason}
other -> {:error, "Invalid response from driver: #{inspect(other)}"}
end
end
def write(%{ref: ref, address: address} = conn, data, options \\ [])
def write(%{conn: inner, address: address} = conn, data, options \\ [])
when is_i2c_address(address) and is_binary(data) and is_list(options) do
with :ok <- Wrapper.write(ref, address, data, options), do: {:ok, conn}
with :ok <- Wrapper.write(inner, address, data, options), do: {:ok, conn}
end
def write_read(%{ref: ref, address: address} = conn, data, bytes, options \\ [])
def write_read(%{conn: inner, address: address} = conn, data, bytes, options \\ [])
when is_i2c_address(address) and is_binary(data) and
is_byte_size(bytes) and is_list(options) do
case Wrapper.write_read(ref, address, data, bytes, options) do
case Wrapper.write_read(inner, address, data, bytes, options) do
{:ok, data} when is_binary(data) and byte_size(data) == bytes -> {:ok, data, conn}
{:error, reason} -> {:error, reason}
other -> {:error, "Invalid response from driver: #{inspect(other)}"}
end
end
def detect_devices(%{ref: ref}) when is_reference(ref) do
case Wrapper.detect_devices(ref) do
def detect_devices(%{conn: conn}) do
case Wrapper.detect_devices(conn) do
devices when is_list(devices) -> {:ok, devices}
{:error, reason} -> {:error, reason}
other -> {:error, "Invalid response from driver: #{inspect(other)}"}
end
end
end

View file

@ -115,7 +115,6 @@ defimpl Wafer.I2C, for: Wafer.Driver.ElixirALE.I2C do
case Wrapper.detect_devices(pid) do
devices when is_list(devices) -> {:ok, devices}
{:error, reason} -> {:error, reason}
other -> {:error, "Invalid response from driver: #{inspect(other)}"}
end
end
end

View file

@ -35,5 +35,5 @@ defmodule Wafer.Driver.ElixirALE.I2C.Wrapper do
defdelegate write_read(pid, write_data, read_count), to: ElixirALE.I2C
@compile {:no_warn_undefined, ElixirALE.I2C}
defdelegate write_read_device(pid, address, write_data, read_count), to: ElixirALE
defdelegate write_read_device(pid, address, write_data, read_count), to: ElixirALE.I2C
end

View file

@ -14,6 +14,9 @@ defmodule Wafer.Driver.Fake do
protocols.
"""
@type t :: %__MODULE__{opts: any}
@doc false
@impl Wafer.Conn
def acquire(opts) do
if emit_warning(),
@ -87,7 +90,7 @@ defimpl Wafer.I2C, for: Wafer.Driver.Fake do
{:ok, <<0::size(bits)>>, conn}
end
def detect_devices(_conn), do: []
def detect_devices(_conn), do: {:ok, []}
end
defimpl Wafer.SPI, for: Wafer.Driver.Fake do

View file

@ -63,7 +63,7 @@ defprotocol Wafer.I2C do
@doc """
Detect the devices adjacent to the connection's device on the same I2C bus.
"""
@spec detect_devices(Conn.t()) :: {:ok, [address]}
@spec detect_devices(Conn.t()) :: {:ok, [address]} | {:error, any}
def detect_devices(conn)
end

View file

@ -1,4 +1,3 @@
# credo:disable-for-this-file
defmodule Wafer.Registers do
@moduledoc """
This module provides helpful macros for specifying the registers used to
@ -16,6 +15,7 @@ defmodule Wafer.Registers do
@type access_mode :: :ro | :rw | :wo
@type bytes :: non_neg_integer
@doc false
defmacro __using__(_opts) do
quote do
import Wafer.Registers
@ -101,7 +101,7 @@ defmodule Wafer.Registers do
defmacro defregister(name, register_address, :ro, bytes)
when is_atom(name) and is_integer(register_address) and register_address >= 0 and
is_integer(bytes) and bytes >= 0 do
empty_bytes = 1..bytes |> Enum.map(fn _ -> 0 end) |> Enum.join(", ")
empty_bytes = 1..bytes |> Enum.map_join(", ", fn _ -> 0 end)
quote do
@doc """
@ -121,7 +121,7 @@ defmodule Wafer.Registers do
defmacro defregister(name, register_address, :wo, bytes)
when is_atom(name) and is_integer(register_address) and register_address >= 0 and
is_integer(bytes) and bytes >= 0 do
empty_bytes = 1..bytes |> Enum.map(fn _ -> 0 end) |> Enum.join(", ")
empty_bytes = 1..bytes |> Enum.map_join(", ", fn _ -> 0 end)
quote do
@doc """
@ -142,10 +142,11 @@ defmodule Wafer.Registers do
end
end
# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
defmacro defregister(name, register_address, :rw, bytes)
when is_atom(name) and is_integer(register_address) and register_address >= 0 and
is_integer(bytes) and bytes >= 0 do
empty_bytes = 1..bytes |> Enum.map(fn _ -> 0 end) |> Enum.join(", ")
empty_bytes = 1..bytes |> Enum.map_join(", ", fn _ -> 0 end)
bits = bytes * 8
quote do
@ -215,8 +216,7 @@ defmodule Wafer.Registers do
Chip.read_register(conn, unquote(register_address), unquote(bytes)),
new_data when is_binary(new_data) and byte_size(new_data) == unquote(bytes) <-
callback.(old_data),
{:ok, conn} <- Chip.write_register(conn, unquote(register_address), new_data),
do: {:ok, conn}
do: Chip.write_register(conn, unquote(register_address), new_data)
end
def unquote(:"update_#{name}")(_conn, _callback),

View file

@ -30,7 +30,7 @@ defprotocol Wafer.Release do
Release all resources associated with the connection. Usually in preparation
for shutdown.
"""
@spec release(Conn.t()) :: :ok
@spec release(Conn.t()) :: :ok | {:error, any}
def release(conn)
end

View file

@ -173,7 +173,7 @@ defmodule Wafer.Twiddles do
iex> find_ones(<<0x0A>>)
[1, 3]
"""
@spec find_ones(byte | single_byte_binary) :: non_neg_integer
@spec find_ones(byte | single_byte_binary) :: [non_neg_integer]
def find_ones(byte) when is_byte(byte) do
0..7
|> Enum.filter(&(get_bit(byte, &1) == 1))
@ -192,7 +192,7 @@ defmodule Wafer.Twiddles do
iex> find_zeroes(<<0xFA>>)
[0, 2]
"""
@spec find_zeroes(byte | single_byte_binary) :: non_neg_integer
@spec find_zeroes(byte | single_byte_binary) :: [non_neg_integer]
def find_zeroes(byte) when is_byte(byte) do
0..7
|> Enum.filter(&(get_bit(byte, &1) == 0))

34
mix.exs
View file

@ -18,7 +18,13 @@ defmodule Wafer.MixProject do
package: package(),
description: @description,
deps: deps(),
consolidate_protocols: Mix.env() != :test
consolidate_protocols: Mix.env() != :test,
source_url: "https://code.harton.nz/james/wafer",
homepage_url: "https://code.harton.nz/james/wafer",
docs: [
source_url_pattern: "https://code.harton.nz/james/wafer/src/branch/main/%{path}#L%{line}",
extras: ["README.md"]
]
]
end
@ -35,13 +41,17 @@ defmodule Wafer.MixProject do
maintainers: ["James Harton <james@harton.nz>"],
licenses: ["HL3-FULL"],
links: %{
"Source" => "https://gitlab.com/jimsy/wafer"
}
"Source" => "https://code.harton.nz/james/smokestack",
"Gitlab Mirror" => "https://gitlab.com/jimsy/wafer"
},
source_url: "https://code.harton.nz/james/smokestack"
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
devtest = [only: ~w[dev test]a, runtime: false]
[
{:circuits_gpio, "~> 1.0", optional: true},
if System.get_env("CI_I2C_1_X") == "true" do
@ -49,13 +59,19 @@ defmodule Wafer.MixProject do
else
{:circuits_i2c, "~> 2.0 or ~> 1.0", optional: true}
end,
{:circuits_spi, "~> 1.3", optional: true},
{:credo, "~> 1.6", only: ~w[dev test]a, runtime: false},
{:earmark, "~> 1.4", only: ~w[dev test]a},
{:circuits_spi, "~> 2.0 or ~> 1.3", optional: true},
{:elixir_ale, "~> 1.2", optional: true},
{:ex_doc, ">= 0.28.1", only: ~w[dev test]a},
{:git_ops, "~> 2.4", only: ~w[dev test]a, runtime: false},
{:mimic, "~> 1.5", only: :test}
# Dev/test
{:credo, "~> 1.6", devtest},
{:dialyxir, "~> 1.4", devtest},
{:doctor, "~> 0.21", devtest},
{:earmark, "~> 1.4", devtest},
{:ex_check, "~> 0.15", devtest},
{:ex_doc, ">= 0.0.0", devtest},
{:git_ops, "~> 2.4", devtest},
{:mimic, "~> 1.5", only: :test},
{:mix_audit, "~> 2.1", devtest}
]
end
end

View file

@ -1,21 +1,29 @@
%{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"circuits_gpio": {:hex, :circuits_gpio, "1.0.0", "b2a493b1822ec712bfba7068a016930f6db5e31713b9b84ed8bc307c7c323682", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "da64c1d9ba1329cd7ca7e63adcd68d73e2294d6b48eb66c9a1064f3db5c523f3"},
"circuits_i2c": {:hex, :circuits_i2c, "2.0.0", "8343b12879189f844835abeaf31a36c5626b8ace58413a582794fdfe60c2dc0e", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "06eccd33b36bcedf41730cac8da58e359967ea63a2cd899cea58c2a138634cc4"},
"circuits_spi": {:hex, :circuits_spi, "1.3.0", "d66d4c8818739416958cea1d846d66896ab7c28fa42695f1cae3c2c7a3e9e9ca", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "56e49b346fdd43185832a03d3de3751c2ce9928ee3ce4a31a364f6548fe2b74c"},
"credo": {:hex, :credo, "1.6.1", "7dc76dcdb764a4316c1596804c48eada9fff44bd4b733a91ccbf0c0f368be61e", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "698607fb5993720c7e93d2d8e76f2175bba024de964e160e2f7151ef3ab82ac5"},
"earmark": {:hex, :earmark, "1.4.19", "3854a17305c880cc46305af15fb1630568d23a709aba21aaa996ced082fc29d7", [:mix], [{:earmark_parser, ">= 1.4.18", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "d5a8c9f9e37159a8fdd3ea8437fb4e229eaf56d5129b9a011dc4780a4872079d"},
"earmark_parser": {:hex, :earmark_parser, "1.4.19", "de0d033d5ff9fc396a24eadc2fcf2afa3d120841eb3f1004d138cbf9273210e8", [:mix], [], "hexpm", "527ab6630b5c75c3a3960b75844c314ec305c76d9899bb30f71cb85952a9dc45"},
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"circuits_gpio": {:hex, :circuits_gpio, "1.1.0", "cda895fd0a12fdf50e27f6d61cc349587dff29755fca640b93233a661925d97a", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "11dab3c7b39cbe08588e9527c9fd98117be485f70b61641874abdda50340e991"},
"circuits_i2c": {:hex, :circuits_i2c, "2.0.1", "e9ab22f078b403cafd2c5006fff448f9a790f73c04e9135b7ac22f45f2e63c5c", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "a1567004389b49637fe34d9dd8bdf36c26a53c269e654753860b5c09532bc3c4"},
"circuits_spi": {:hex, :circuits_spi, "2.0.0", "9198c15c7ffce5bc353e13b7c82df3fe99d7332bd7c28fb9a62c60ce1e7567dc", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2eddec1fe6486a16f77f72eca91d50a806f9365033d96a517381b61d747612c2"},
"credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"},
"doctor": {:hex, :doctor, "0.21.0", "20ef89355c67778e206225fe74913e96141c4d001cb04efdeba1a2a9704f1ab5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "a227831daa79784eb24cdeedfa403c46a4cb7d0eab0e31232ec654314447e4e0"},
"earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"},
"earmark_parser": {:hex, :earmark_parser, "1.4.38", "b42252eddf63bda05554ba8be93a1262dc0920c721f1aaf989f5de0f73a2e367", [:mix], [], "hexpm", "2cd0907795aaef0c7e8442e376633c5b3bd6edc8dbbdc539b22f095501c1cdb6"},
"elixir_ale": {:hex, :elixir_ale, "1.2.1", "07ac2f17a0191b8bd3b0df6b526c7f699a3a4d690c9def573fcb5824eef24d98", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "bfb099137500a3b8c4a1750cf07f2d704897ef9feac3412064bf9edc7d74193c"},
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"},
"ex_doc": {:hex, :ex_doc, "0.28.1", "34fab7e7201c5a1f275f3b2f837125c940c512e8543d181bd4dd7acb19c8dba0", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "10e564dd59101a5edc4de7009a54baed015a246dee01f7200aab24e8f57fc044"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"},
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"},
"git_ops": {:hex, :git_ops, "2.4.5", "185a724dfde3745edd22f7571d59c47a835cf54ded67e9ccbc951920b7eec4c2", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e323a5b01ad53bc8c19c3a444be3e61ed7803ecd2e95530446ae9327d0143ecc"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.2", "dc72dfe17eb240552857465cc00cce390960d9a0c055c4ccd38b70629227e97c", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "fd23ae48d09b32eff49d4ced2b43c9f086d402ee4fd4fcb2d7fad97fa8823e75"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"mimic": {:hex, :mimic, "1.5.1", "085f7ebfeb5b579a13a167aec3c712d71fecfc6cb8b298c0dd3056f97ea2c2a0", [:mix], [], "hexpm", "33a50ef9ff38f8f24b2586d52e529981a3ba2b8d061c872084aff0e993bf4bd5"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.2", "b99ca56bbce410e9d5ee4f9155a212e942e224e259c7ebbf8f2c86ac21d4fa3c", [:mix], [], "hexpm", "98d51bd64d5f6a2a9c6bb7586ee8129e27dfaab1140b5a4753f24dac0ba27d2f"},
"git_ops": {:hex, :git_ops, "2.6.0", "e0791ee1cf5db03f2c61b7ebd70e2e95cba2bb9b9793011f26609f22c0900087", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "b98fca849b18aaf490f4ac7d1dd8c6c469b0cc3e6632562d366cab095e666ffe"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
"mimic": {:hex, :mimic, "1.7.4", "cd2772ffbc9edefe964bc668bfd4059487fa639a5b7f1cbdf4fd22946505aa4f", [:mix], [], "hexpm", "437c61041ecf8a7fae35763ce89859e4973bb0666e6ce76d75efc789204447c3"},
"mix_audit": {:hex, :mix_audit, "2.1.1", "653aa6d8f291fc4b017aa82bdb79a4017903902ebba57960ef199cbbc8c008a1", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.9", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "541990c3ab3a7bb8c4aaa2ce2732a4ae160ad6237e5dcd5ad1564f4f85354db1"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
"yaml_elixir": {:hex, :yaml_elixir, "2.9.0", "9a256da867b37b8d2c1ffd5d9de373a4fda77a32a45b452f1708508ba7bbcb53", [:mix], [{:yamerl, "~> 0.10", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "0cb0e7d4c56f5e99a6253ed1a670ed0e39c13fc45a6da054033928607ac08dfc"},
}

View file

@ -1,3 +0,0 @@
{
"extends": ["gitlab>jimsy/renovate"]
}

View file

@ -101,7 +101,7 @@ defmodule WaferDriverCircuits.GPIOTest do
|> expect(:enable, 1, fn conn1, pin_condition, _metadata ->
assert conn1 == conn
assert pin_condition == :rising
:ok
{:ok, conn1}
end)
assert {:ok, ^conn} = GPIO.enable_interrupt(conn, :rising)
@ -116,7 +116,7 @@ defmodule WaferDriverCircuits.GPIOTest do
|> expect(:disable, 1, fn conn1, pin_condition ->
assert conn1 == conn
assert pin_condition == :rising
:ok
{:ok, conn1}
end)
assert {:ok, ^conn} = GPIO.disable_interrupt(conn, :rising)

View file

@ -77,7 +77,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:close, 1, fn ref ->
assert ref == conn.ref
assert ref == conn.conn
:ok
end)
@ -91,7 +91,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:write_read, 1, fn ref, addr, data, bytes ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert data == <<0>>
assert bytes == 2
@ -108,7 +108,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:write, 1, fn ref, addr, data ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert data == <<1, 2, 3>>
:ok
@ -124,7 +124,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:write_read, 1, fn ref, addr, data, bytes ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert data == <<0>>
assert bytes == 2
@ -133,7 +133,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:write, 1, fn ref, addr, data ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert data == <<0, 1, 1>>
:ok
@ -149,7 +149,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:read, 1, fn ref, addr, bytes, opts ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert bytes == 2
assert opts == []
@ -166,7 +166,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:write, 1, fn ref, addr, data, opts ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert data == <<0, 0>>
assert opts == []
@ -183,7 +183,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:write_read, 1, fn ref, addr, data, bytes, opts ->
assert ref == conn.ref
assert ref == conn.conn
assert addr == conn.address
assert data == <<1>>
assert bytes == 2
@ -202,7 +202,7 @@ defmodule WaferCircuits.I2CTest do
Wrapper
|> expect(:detect_devices, 1, fn ref ->
assert conn.ref == ref
assert conn.conn == ref
[conn.address]
end)
@ -210,5 +210,5 @@ defmodule WaferCircuits.I2CTest do
end
end
defp conn, do: %Subject{ref: :erlang.make_ref(), bus: "i2c-1", address: 0x13}
defp conn, do: %Subject{conn: :erlang.make_ref(), bus: "i2c-1", address: 0x13}
end