From d6b6d5dc8711d1fe609ff4173b9121f2594f5d9a Mon Sep 17 00:00:00 2001 From: Winford Date: Fri, 28 Apr 2023 13:45:09 -0700 Subject: [PATCH] Add LEDC example for Elixir This is a rebar3 configured version of the `Ledc_x4` example from `AtomVM/examples/elixir/esp32`. Signed-off-by: Winford --- elixir/LEDC_Example/.gitignore | 32 ++++++ elixir/LEDC_Example/README.md | 20 ++++ elixir/LEDC_Example/lib/LEDC_Example.ex | 144 ++++++++++++++++++++++++ elixir/LEDC_Example/mix.exs | 27 +++++ 4 files changed, 223 insertions(+) create mode 100644 elixir/LEDC_Example/.gitignore create mode 100644 elixir/LEDC_Example/README.md create mode 100644 elixir/LEDC_Example/lib/LEDC_Example.ex create mode 100644 elixir/LEDC_Example/mix.exs diff --git a/elixir/LEDC_Example/.gitignore b/elixir/LEDC_Example/.gitignore new file mode 100644 index 0000000..1340604 --- /dev/null +++ b/elixir/LEDC_Example/.gitignore @@ -0,0 +1,32 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +ledc_example-*.tar + +# Temporary files, for example, from tests. +/tmp/ + +# Ignore compiled amv gilers. +*.avm + +# Ignore formatter files. +/.formatter.exs diff --git a/elixir/LEDC_Example/README.md b/elixir/LEDC_Example/README.md new file mode 100644 index 0000000..056ce36 --- /dev/null +++ b/elixir/LEDC_Example/README.md @@ -0,0 +1,20 @@ +# `LEDC_Example` Application + +Welcome to the `LEDC_Example` AtomVM application. + +The `LEDC_Example` AtomVM application illustrates use of the AtomVM `LEDC` interface. + +LEDs are wired to GPIO pins 4, 5, 18, and 19 and should use a resistor (minimum 100 Ohm up to 1K, 220 Ohm is a good choice). Change the number +for the GPIO pins in the example if necessary. See the Blinky example for wiring if you are unsure. + +For more information about programming on the AtomVM platform, see the [AtomVM Programmers Guide](https://doc.atomvm.net/programmers-guide.html). + +## Supported Platforms + +| Platform | Supported | +|----------|-----------| +| `esp32` | ✅ | +| `stm32` | ❌ | +| `generic_unix` | ❌ | + +For general information about building and executing Erlang AtomVM example programs, see the Erlang example program [README](../README.md). diff --git a/elixir/LEDC_Example/lib/LEDC_Example.ex b/elixir/LEDC_Example/lib/LEDC_Example.ex new file mode 100644 index 0000000..9988f4d --- /dev/null +++ b/elixir/LEDC_Example/lib/LEDC_Example.ex @@ -0,0 +1,144 @@ +# +# This file is part of AtomVM. +# +# Copyright 2022 Winford (Uncle Grumpy) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +# + +defmodule LedcExample do + @moduledoc """ + Ledc_example for Elixir. + """ + + @test_duty 4000 + @test_fade_time 3000 + + @high_speed_timer 0 + @low_speed_timer 1 + + # Change to match GPIO pins of your LEDs + @led_1 18 + @led_2 19 + @led_3 4 + @led_4 5 + + def start do + ledc_hs_timer = [ + {:duty_resolution, 13}, + {:freq_hz, 5000}, + {:speed_mode, LEDC.high_speed_mode}, + {:timer_num, @high_speed_timer} + ] + + :ok = LEDC.timer_config(ledc_hs_timer) + + ledc_ls_timer = [ + {:duty_resolution, 13}, + {:freq_hz, 5000}, + {:speed_mode, LEDC.low_speed_mode}, + {:timer_num, @low_speed_timer} + ] + + :ok = LEDC.timer_config(ledc_ls_timer) + + ledc_channel = [ + [ + {:channel, 0}, + {:duty, 0}, + {:gpio_num, @led_1}, + {:speed_mode, LEDC.high_speed_mode}, + {:hpoint, 0}, + {:timer_sel, @high_speed_timer} + ], + [ + {:channel, 1}, + {:duty, 0}, + {:gpio_num, @led_2}, + {:speed_mode, LEDC.high_speed_mode}, + {:hpoint, 0}, + {:timer_sel, @high_speed_timer} + ], + [ + {:channel, 2}, + {:duty, 0}, + {:gpio_num, @led_3}, + {:speed_mode, LEDC.low_speed_mode}, + {:hpoint, 0}, + {:timer_sel, @low_speed_timer} + ], + [ + {:channel, 3}, + {:duty, 0}, + {:gpio_num, @led_4}, + {:speed_mode, LEDC.low_speed_mode}, + {:hpoint, 0}, + {:timer_sel, @low_speed_timer} + ] + ] + + Enum.each(ledc_channel, fn channel_config -> :ok = LEDC.channel_config(channel_config) end) + :ok = LEDC.fade_func_install(0) + loop(ledc_channel) + end + + def loop(ledc_channel) do + :io.format('1. LEDC fade up to duty = ~p~n', [@test_duty]) + Enum.each(ledc_channel, fn channel_config -> do_stage_1(channel_config) end) + Process.sleep(@test_fade_time) + + :io.format('2. LEDC fade down to duty = 0~n') + Enum.each(ledc_channel, fn channel_config -> do_stage_2(channel_config) end) + Process.sleep(@test_fade_time) + + :io.format('3. LEDC set duty = ~p without fade~n', [@test_duty]) + Enum.each(ledc_channel, fn channel_config -> do_stage_3(channel_config) end) + Process.sleep(@test_fade_time) + + :io.format('4. LEDC set duty = 0 without fade~n') + Enum.each(ledc_channel, fn channel_config -> do_stage_4(channel_config) end) + Process.sleep(@test_fade_time) + + loop(ledc_channel) + end + + defp do_stage_1(channel_config) do + speed_mode = :proplists.get_value(:speed_mode, channel_config) + channel = :proplists.get_value(:channel, channel_config) + :ok = LEDC.set_fade_with_time(speed_mode, channel, @test_duty, @test_fade_time) + :ok = LEDC.fade_start(speed_mode, channel, LEDC.fade_no_wait) + end + + defp do_stage_2(channel_config) do + speed_mode = :proplists.get_value(:speed_mode, channel_config) + channel = :proplists.get_value(:channel, channel_config) + :ok = LEDC.set_fade_with_time(speed_mode, channel, 0, @test_fade_time) + :ok = LEDC.fade_start(speed_mode, channel, LEDC.fade_no_wait) + end + + defp do_stage_3(channel_config) do + speed_mode = :proplists.get_value(:speed_mode, channel_config) + channel = :proplists.get_value(:channel, channel_config) + :ok = LEDC.set_duty(speed_mode, channel, @test_duty) + :ok = LEDC.update_duty(speed_mode, channel) + end + + defp do_stage_4(channel_config) do + speed_mode = :proplists.get_value(:speed_mode, channel_config) + channel = :proplists.get_value(:channel, channel_config) + :ok = LEDC.set_duty(speed_mode, channel, 0) + :ok = LEDC.update_duty(speed_mode, channel) + end +end diff --git a/elixir/LEDC_Example/mix.exs b/elixir/LEDC_Example/mix.exs new file mode 100644 index 0000000..856ac81 --- /dev/null +++ b/elixir/LEDC_Example/mix.exs @@ -0,0 +1,27 @@ +defmodule LedcExample.MixProject do + use Mix.Project + + def project do + [ + app: :LEDC_Example, + version: "0.1.0", + elixir: "~> 1.13", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:exatomvm, git: "https://github.com/atomvm/ExAtomVM/"} + ] + end +end