hw/util/buzzer: Tone generator with the PWM peripheral (#2538)

- hw/drivers/buzzer: Tone generator with the PWM peripheral
- Also adding apps/buzzer
diff --git a/apps/buzzer/pkg.yml b/apps/buzzer/pkg.yml
new file mode 100644
index 0000000..0d6c693
--- /dev/null
+++ b/apps/buzzer/pkg.yml
@@ -0,0 +1,36 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+pkg.name: apps/buzzer
+pkg.type: app
+pkg.description: Example app which generates beeps using a buzzer on PWM pin.
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - buzzer
+    - pwm
+    - tone
+
+pkg.deps:
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/sys/console/stub"
+    - "@apache-mynewt-core/sys/log/stub"
+    - "@apache-mynewt-core/hw/util/buzzer"
+
diff --git a/apps/buzzer/src/main.c b/apps/buzzer/src/main.c
new file mode 100755
index 0000000..a4a6a6c
--- /dev/null
+++ b/apps/buzzer/src/main.c
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include <assert.h>
+
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+
+#include "buzzer/buzzer.h"
+
+int count = 0;
+
+int
+main(int argc, char **argv)
+{
+    sysinit();
+
+    while (1) {
+
+        /* quarter of second */
+        os_time_delay(OS_TICKS_PER_SEC / 4);
+
+        /* each quarter of second */
+        switch (count++ % 4) {
+
+        case 0:
+            /* activate buzzer tone at 2 KHz frequency */
+            buzzer_tone_on(2000);
+            break;
+
+        case 1:
+            /* disable buzzer */
+            buzzer_tone_off();
+            break;
+
+        default:
+            /* empty */
+            break;
+        }
+    }
+
+    assert(0);
+}
+
diff --git a/apps/buzzer/syscfg.yml b/apps/buzzer/syscfg.yml
new file mode 100644
index 0000000..39728a7
--- /dev/null
+++ b/apps/buzzer/syscfg.yml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+syscfg.vals:
+
+    # PWM for buzzer
+    PWM_0: 1
+
+    # pin where the buzzer is connected to
+    BUZZER_PIN: 26
+
diff --git a/hw/util/buzzer/README.md b/hw/util/buzzer/README.md
new file mode 100644
index 0000000..0a6b82b
--- /dev/null
+++ b/hw/util/buzzer/README.md
@@ -0,0 +1,62 @@
+# Tone generator with the PWM peripheral
+
+This package implements methods to use a PWM peripheral as a tone generator
+ready to connect a passive buzzer to a MCU pin. It generates a square wave
+of the specified frequency and 50% duty cycle.
+
+It depends on the PWM abstract driver provided by [Apache
+Mynewt](https://github.com/apache/mynewt-core). Review if [the PWM driver
+interface](https://github.com/apache/mynewt-core/tree/master/hw/drivers/pwm)
+is implemented for your platform.
+
+## Synopsis
+
+Usage:
+
+```
+/* enable buzzer tone at 2 KHz frequency */
+buzzer_tone_on(2000);
+
+/* disable tone generation */
+buzzer_tone_off();
+
+```
+
+Configuration:
+
+```
+syscfg.vals:
+
+    # required:
+    BUZZER_PIN: 18
+
+    # optional (default):
+    BUZZER_PWM: '"pwm0"'
+
+    # activate PWM device (if your BSP does not it)
+    PWM_0: 1
+```
+
+## Setup
+
+Add the dependency to your package:
+
+```
+pkg.deps:
+    - "@apache-mynewt-core/hw/util/buzzer"
+```
+
+## License
+
+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.
+
diff --git a/hw/util/buzzer/include/buzzer/buzzer.h b/hw/util/buzzer/include/buzzer/buzzer.h
new file mode 100644
index 0000000..8e2be1b
--- /dev/null
+++ b/hw/util/buzzer/include/buzzer/buzzer.h
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef __BUZZER_H__
+#define __BUZZER_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void buzzer_driver_init();
+void buzzer_tone_on(uint32_t freq);
+void buzzer_tone_off();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BUZZER_H__ */
diff --git a/hw/util/buzzer/pkg.yml b/hw/util/buzzer/pkg.yml
new file mode 100644
index 0000000..b5e090d
--- /dev/null
+++ b/hw/util/buzzer/pkg.yml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+pkg.name: "hw/util/buzzer"
+pkg.description: "Tone generator with the PWM peripheral"
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/drivers/pwm"
+
+pkg.init:
+    buzzer_driver_init: 'MYNEWT_VAL(BUZZER_SYSINIT_STAGE)'
+
diff --git a/hw/util/buzzer/src/buzzer.c b/hw/util/buzzer/src/buzzer.c
new file mode 100644
index 0000000..e20460e
--- /dev/null
+++ b/hw/util/buzzer/src/buzzer.c
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "buzzer/buzzer.h"
+
+#include <os/mynewt.h>
+#include <pwm/pwm.h>
+
+#define BUZZER_PIN MYNEWT_VAL(BUZZER_PIN)
+#define BUZZER_PWM MYNEWT_VAL(BUZZER_PWM)
+#define BUZZER_PWM_CHAN 0
+
+#if BUZZER_PIN >= 0
+struct pwm_dev *_pwm_dev;
+#endif
+
+/***
+ * Initialize the PWM device to be used as a square wave generator. This is
+ * automatically invoked by the Mynewt initialization system.
+ */
+void
+buzzer_driver_init()
+{
+#if BUZZER_PIN >= 0
+    struct pwm_dev_cfg dev_conf = {
+        .n_cycles = 0,
+        .int_prio = -1,
+        .cycle_handler = NULL,
+        .seq_end_handler = NULL,
+        .cycle_data = NULL,
+        .seq_end_data = NULL,
+        .data = NULL
+    };
+
+    struct pwm_chan_cfg chan_conf = {
+        .pin = BUZZER_PIN,
+        .inverted = false,
+        .data = NULL,
+    };
+
+    int rc;
+
+    /* PWM device */
+    _pwm_dev = (struct pwm_dev *)os_dev_open(BUZZER_PWM, 0, NULL);
+    assert(_pwm_dev != NULL);
+
+    /* PWM configuration */
+    rc = pwm_configure_device(_pwm_dev, &dev_conf);
+    assert(rc == 0);
+
+    /* set channel */
+    rc = pwm_configure_channel(_pwm_dev, BUZZER_PWM_CHAN, &chan_conf);
+    assert(rc == 0);
+
+    /* set tone off */
+    pwm_set_duty_cycle(_pwm_dev, BUZZER_PWM_CHAN, 0);
+    assert(rc == 0);
+
+    /* enable PMW device */
+    rc = pwm_enable(_pwm_dev);
+    assert(rc == 0);
+#endif
+}
+
+/***
+ * Activate the PWM to generate a square wave of a specified frequency.
+ *
+ * @param freq Frequency of the tone in Hz.
+ */
+void
+buzzer_tone_on(uint32_t freq)
+{
+#if BUZZER_PIN >= 0
+    if (freq == 0) {
+        /* stop PWM */
+        pwm_set_duty_cycle(_pwm_dev, BUZZER_PWM_CHAN, 0);
+    } else {
+        /* set frequency */
+        pwm_set_frequency(_pwm_dev, freq);
+
+        /* set duty at 50% */
+        pwm_set_duty_cycle(_pwm_dev, BUZZER_PWM_CHAN, pwm_get_top_value(_pwm_dev) / 2);
+    }
+#endif
+}
+
+/***
+ * Stop the generation of the square wave triggered by buzzer_tone_on().
+ */
+inline void
+buzzer_tone_off()
+{
+#if BUZZER_PIN >= 0
+    buzzer_tone_on(0);
+#endif
+}
diff --git a/hw/util/buzzer/syscfg.yml b/hw/util/buzzer/syscfg.yml
new file mode 100644
index 0000000..6562237
--- /dev/null
+++ b/hw/util/buzzer/syscfg.yml
@@ -0,0 +1,36 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+syscfg.defs:
+
+    BUZZER_SYSINIT_STAGE:
+        description: >
+            Sysinit stage for buzzer functionality.
+        value: 95
+
+    BUZZER_PIN:
+        description: >
+            Pin number where the buzzer is connected to. Use -1 if buzzer is
+            disabled (default).
+        value: -1
+
+    BUZZER_PWM:
+        description: >
+            PWM device to use to generate the square signal. See Mynewt PWM
+            driver to further info. Default is "pwm0"
+        value: '"pwm0"'