Skip to content
shell.c 5.85 KiB
Newer Older
/*
    This file is part of MutekH.

    MutekH is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation; version 2.1 of the
    License.

    MutekH is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this program.  If not, see
    <http://www.gnu.org/licenses/>.

    Copyright Julien Peeters <contact@julienpeeters.net> (c) 2016
*/

#include <device/device.h>
#include <device/driver.h>
#include <device/resources.h>

#include <device/class/gpio.h>
#include <device/class/iomux.h>
#include <device/class/uart.h>
#include <device/class/timer.h>

#include <mutek/shell.h>
#include <mutek/console.h>
#include <mutek/startup.h>
#include <mutek/printk.h>

#include <arch/stm32/pin.h>

#define FIRST STM32_PE8
#define LAST  STM32_PE15

static struct device_gpio_s  gpio;
static struct device_timer_s timer;

static dev_timer_delay_t     msec;

static uint8_t brain_gpio_init_mask[] = { 0x55, 0x55 };

void otoroshi_startup(void)
{
    printk("bmaaa: brain firmware started!\n");

    ensure(!device_get_accessor_by_path(&gpio.base, NULL, "/gpio", DRIVER_CLASS_GPIO));
    ensure(!device_get_accessor_by_path(&timer.base, NULL, "/timer4", DRIVER_CLASS_TIMER));

    ensure(!dev_timer_init_sec(&timer, &msec, 0, 1, 1000));

    DEVICE_OP(&gpio, set_output, FIRST, LAST, brain_gpio_init_mask, dev_gpio_mask0);
    DEVICE_OP(&gpio, set_mode, FIRST, LAST, dev_gpio_mask1, DEV_PIN_PUSHPULL);
    dev_timer_busy_wait_delay(&timer, msec * 100);
    DEVICE_OP(&gpio, set_output, FIRST, LAST, dev_gpio_mask0, dev_gpio_mask0);
}

enum shell_otoroshi_opts_e
{
  OTOROSHI_OPT_RELAY  = 0x1,
  OTOROSHI_OPT_STATE  = 0x2,
  OTOROSHI_OPT_CLOSED = 0x4,
  OTOROSHI_OPT_OPEN   = 0x8,
  OTOROSHI_OPT_PULSE  = 0x10,
  OTOROSHI_OPT_DELAY  = 0x20,
};

struct termui_optctx_otoroshi_opts
{
  uint8_t relay;
  bool_t  state;
  size_t  delay;
};

static TERMUI_CON_COMMAND_PROTOTYPE(shell_otoroshi_relay)
{
  struct termui_optctx_otoroshi_opts * c = ctx;

  struct device_timer_s timer;
  dev_timer_delay_t     msec;

  struct device_gpio_s gpio;

  error_t err = 0;

  err = device_get_accessor_by_path(&gpio.base, NULL, "/gpio", DRIVER_CLASS_GPIO);
  if (err)
    return err;

  err = device_get_accessor_by_path(&timer.base, NULL, "/timer*", DRIVER_CLASS_TIMER);
  if (err)
    goto gpio_cleanup;

  err = dev_timer_init_sec(&timer, &msec, 0, 1, 1000);
  if (err)
    goto timer_cleanup;

  DEVICE_OP(&gpio, set_output, STM32_PE8, STM32_PE15, dev_gpio_mask0, dev_gpio_mask0);
  DEVICE_OP(&gpio, set_mode, STM32_PE8, STM32_PE15, dev_gpio_mask1, DEV_PIN_PUSHPULL);

  if (used & OTOROSHI_OPT_PULSE)
    {
      uint8_t id = STM32_PE8 + c->relay * 2;

      static uint8_t door_open_mask[1] = { 0x2 };
      static uint8_t door_close_mask[1]  = { 0x1 };

      DEVICE_OP(&gpio, set_output, id, id + 1, door_open_mask, door_open_mask);
      dev_timer_wait_delay(&timer, msec * 100, 0);
      DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask0, dev_gpio_mask0);

      dev_timer_wait_delay(&timer, msec * c->delay, 0);

      DEVICE_OP(&gpio, set_output, id, id + 1, door_close_mask, door_close_mask);
      dev_timer_wait_delay(&timer, msec * 100, 0);
      DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask0, dev_gpio_mask0);
    }
  else
    {
      bool_t state = 0;

      if (used & OTOROSHI_OPT_STATE)
        state = c->state;
      else if (used & OTOROSHI_OPT_CLOSED)
        state = 0;
      else if (used & OTOROSHI_OPT_OPEN)
        state = 1;

      uint8_t id = STM32_PE8 + c->relay * 2 + state;
      DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask1, dev_gpio_mask1);
      dev_timer_wait_delay(&timer, msec * 100, 0);
      DEVICE_OP(&gpio, set_output, id, id, dev_gpio_mask0, dev_gpio_mask0);
    }

timer_cleanup:
  device_put_accessor(&timer.base);
gpio_cleanup:
  device_put_accessor(&gpio.base);
  return err;
}

static TERMUI_CON_OPT_DECL(otoroshi_opts) =
{
  TERMUI_CON_OPT_INTEGER_RANGE_ENTRY("-r", "--relay", OTOROSHI_OPT_RELAY,
    struct termui_optctx_otoroshi_opts, relay, 1, 0, 3,
    TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_RELAY, 0))

  TERMUI_CON_OPT_INTEGER_RANGE_ENTRY("-s", "--state", OTOROSHI_OPT_STATE,
    struct termui_optctx_otoroshi_opts, state, 1, 0, 1,
    TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_STATE, OTOROSHI_OPT_RELAY))

  TERMUI_CON_OPT_ENTRY("-c", "--closed", OTOROSHI_OPT_CLOSED,
    TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE,
                               OTOROSHI_OPT_RELAY))

  TERMUI_CON_OPT_ENTRY("-o", "--open", OTOROSHI_OPT_OPEN,
    TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE,
                               OTOROSHI_OPT_RELAY))

  TERMUI_CON_OPT_ENTRY("-p", "--pulse", OTOROSHI_OPT_PULSE,
    TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE | OTOROSHI_OPT_PULSE,
                               OTOROSHI_OPT_RELAY))

  TERMUI_CON_OPT_INTEGER_ENTRY("-d", "--delay", OTOROSHI_OPT_DELAY,
    struct termui_optctx_otoroshi_opts, delay, 1,
    TERMUI_CON_OPT_CONSTRAINTS(OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN | OTOROSHI_OPT_STATE | OTOROSHI_OPT_DELAY,
                               OTOROSHI_OPT_RELAY | OTOROSHI_OPT_PULSE))

  TERMUI_CON_LIST_END
};

static TERMUI_CON_GROUP_DECL(shell_otoroshi_subgroup) =
{
  TERMUI_CON_ENTRY(shell_otoroshi_relay, "relay",
    TERMUI_CON_OPTS_CTX(otoroshi_opts, OTOROSHI_OPT_RELAY,
        OTOROSHI_OPT_STATE | OTOROSHI_OPT_CLOSED | OTOROSHI_OPT_OPEN
      | OTOROSHI_OPT_PULSE | OTOROSHI_OPT_DELAY, NULL))

  TERMUI_CON_LIST_END
};

MUTEK_SHELL_ROOT_GROUP(shell_otoroshi_subgroup, "otoroshi");