diff --git a/units/template/install.sh b/units/template/install.sh new file mode 100755 index 0000000..7feac33 --- /dev/null +++ b/units/template/install.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +echo "Enter unit type identifier (empty to cancel):" +read x + +if [ -e $x ]; then + exit; +fi + +xl="${x,,}" +xu="${x^^}" + +for f in *.h; do mv -- "$f" "${f//tpl/$xl}"; done +for f in *.c; do mv -- "$f" "${f//tpl/$xl}"; done + +sed "s/tpl/$xl/" -i *.h +sed "s/TPL/$xu/" -i *.h +sed "s/tpl/$xl/" -i *.c +sed "s/TPL/$xu/" -i *.c + +echo "Unit $xu set up completed. Removing installer.." +rm '!README.TXT' +rm $0 diff --git a/units/touch/_touch_api.c b/units/touch/_touch_api.c new file mode 100644 index 0000000..5eec0e4 --- /dev/null +++ b/units/touch/_touch_api.c @@ -0,0 +1,11 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" +#include "unit_touch.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + diff --git a/units/touch/_touch_init.c b/units/touch/_touch_init.c new file mode 100644 index 0000000..74221dd --- /dev/null +++ b/units/touch/_touch_init.c @@ -0,0 +1,56 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + +/** Allocate data structure and set defaults */ +error_t UTOUCH_preInit(Unit *unit) +{ + struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv)); + if (priv == NULL) return E_OUT_OF_MEM; + + priv->cfg.charge_time = 2; + priv->cfg.drain_time = 2; + priv->cfg.spread_deviation = 0; + priv->cfg.ss_presc = 1; + priv->cfg.pg_presc = 32; + priv->cfg.sense_timeout = 7; + memset(priv->cfg.group_scaps, 0, 8); + memset(priv->cfg.group_channels, 0, 8); + + return E_SUCCESS; +} + +/** Finalize unit set-up */ +error_t UTOUCH_init(Unit *unit) +{ + bool suc = true; + struct priv *priv = unit->data; + + // + + return E_SUCCESS; +} + + +/** Tear down the unit */ +void UTOUCH_deInit(Unit *unit) +{ + struct priv *priv = unit->data; + + // de-init peripherals + if (unit->status == E_SUCCESS ) { + // + } + + // Release all resources, deinit pins + rsc_teardown(unit); + + // Free memory + free_ck(unit->data); +} diff --git a/units/touch/_touch_internal.h b/units/touch/_touch_internal.h new file mode 100644 index 0000000..e4c865d --- /dev/null +++ b/units/touch/_touch_internal.h @@ -0,0 +1,57 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#ifndef GEX_F072_TOUCH_INTERNAL_H +#define GEX_F072_TOUCH_INTERNAL_H + +#ifndef TOUCH_INTERNAL +#error bad include! +#endif + +#include "unit_base.h" + +/** Private data structure */ +struct priv { + // settings + struct { + uint8_t charge_time; // 1-16 -> 0..15 + uint8_t drain_time; // 1-16 -> 0..15 + uint8_t spread_deviation; // 1-128, 0=off ... 0-127, 0 sets 0 to SSE + uint8_t ss_presc; // 1-2 -> 0..1 + uint8_t pg_presc; // 1,2,4,8,16,32,64,128 -> 0..7 when writing to the periph + uint8_t sense_timeout; // 1-7 -> 0..6 hex when writing to the periph + // the schmitts must be disabled on all used channels, restored to 0xFFFF on deinit + uint8_t group_scaps[8]; + uint8_t group_channels[8]; + } cfg; + + // internal state +}; + +/** Allocate data structure and set defaults */ +error_t UTOUCH_preInit(Unit *unit); + +/** Load from a binary buffer stored in Flash */ +void UTOUCH_loadBinary(Unit *unit, PayloadParser *pp); + +/** Write to a binary buffer for storing in Flash */ +void UTOUCH_writeBinary(Unit *unit, PayloadBuilder *pb); + +// ------------------------------------------------------------------------ + +/** Parse a key-value pair from the INI file */ +error_t UTOUCH_loadIni(Unit *unit, const char *key, const char *value); + +/** Generate INI file section for the unit */ +void UTOUCH_writeIni(Unit *unit, IniWriter *iw); + +// ------------------------------------------------------------------------ + +/** Finalize unit set-up */ +error_t UTOUCH_init(Unit *unit); + +/** Tear down the unit */ +void UTOUCH_deInit(Unit *unit); + +#endif //GEX_F072_TOUCH_INTERNAL_H diff --git a/units/touch/_touch_settings.c b/units/touch/_touch_settings.c new file mode 100644 index 0000000..3aac527 --- /dev/null +++ b/units/touch/_touch_settings.c @@ -0,0 +1,205 @@ +// +// Created by MightyPork on 2018/02/03. +// + +#include "platform.h" +#include "unit_base.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + +// some channels are mapped to nonexistent ports, so just ignore them - clutters the config +#define HAVE_CH7 0 +#define HAVE_CH8 0 + +/** Load from a binary buffer stored in Flash */ +void UTOUCH_loadBinary(Unit *unit, PayloadParser *pp) +{ + struct priv *priv = unit->data; + + uint8_t version = pp_u8(pp); + (void)version; + + priv->cfg.charge_time = pp_u8(pp); + priv->cfg.drain_time = pp_u8(pp); + priv->cfg.spread_deviation = pp_u8(pp); + priv->cfg.ss_presc = pp_u8(pp); + priv->cfg.pg_presc = pp_u8(pp); + priv->cfg.sense_timeout = pp_u8(pp); + pp_buf(pp, priv->cfg.group_scaps, 8); + pp_buf(pp, priv->cfg.group_channels, 8); +} + +/** Write to a binary buffer for storing in Flash */ +void UTOUCH_writeBinary(Unit *unit, PayloadBuilder *pb) +{ + struct priv *priv = unit->data; + + pb_u8(pb, 0); // version + + pb_u8(pb, priv->cfg.charge_time); + pb_u8(pb, priv->cfg.drain_time); + pb_u8(pb, priv->cfg.spread_deviation); + pb_u8(pb, priv->cfg.ss_presc); + pb_u8(pb, priv->cfg.pg_presc); + pb_u8(pb, priv->cfg.sense_timeout); + pb_buf(pb, priv->cfg.group_scaps, 8); + pb_buf(pb, priv->cfg.group_channels, 8); +} + +// ------------------------------------------------------------------------ + +/** Parse a key-value pair from the INI file */ +error_t UTOUCH_loadIni(Unit *unit, const char *key, const char *value) +{ + bool suc = true; + struct priv *priv = unit->data; + + if (streq(key, "charge-time")) { + priv->cfg.charge_time = cfg_u8_parse(value, &suc); + } + else if (streq(key, "drain-time")) { + priv->cfg.drain_time = cfg_u8_parse(value, &suc); + } + else if (streq(key, "ss-deviation")) { + priv->cfg.spread_deviation = cfg_u8_parse(value, &suc); + } + else if (streq(key, "ss-clock-prediv")) { + priv->cfg.ss_presc = cfg_u8_parse(value, &suc); + } + else if (streq(key, "pg-clock-prediv")) { + priv->cfg.pg_presc = cfg_u8_parse(value, &suc); + } + else if (streq(key, "sense-timeout")) { + priv->cfg.sense_timeout = cfg_u8_parse(value, &suc); + } + + else if (streq(key, "g1_cap")) { + priv->cfg.group_scaps[0] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g2_cap")) { + priv->cfg.group_scaps[1] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g3_cap")) { + priv->cfg.group_scaps[2] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g4_cap")) { + priv->cfg.group_scaps[3] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g5_cap")) { + priv->cfg.group_scaps[4] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g6_cap")) { + priv->cfg.group_scaps[5] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#if HAVE_CH7 + else if (streq(key, "g7_cap")) { + priv->cfg.group_scaps[6] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif +#if HAVE_CH8 + else if (streq(key, "g8_cap")) { + priv->cfg.group_scaps[7] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif + + else if (streq(key, "g1_ch")) { + priv->cfg.group_channels[0] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g2_ch")) { + priv->cfg.group_channels[1] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g3_ch")) { + priv->cfg.group_channels[2] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g4_ch")) { + priv->cfg.group_channels[3] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g5_ch")) { + priv->cfg.group_channels[4] = (uint8_t) cfg_pinmask_parse(value, &suc); + } + else if (streq(key, "g6_ch")) { + priv->cfg.group_channels[5] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#if HAVE_CH7 + else if (streq(key, "g7_ch")) { + priv->cfg.group_channels[6] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif +#if HAVE_CH8 + else if (streq(key, "g8_ch")) { + priv->cfg.group_channels[7] = (uint8_t) cfg_pinmask_parse(value, &suc); + } +#endif + + else { + return E_BAD_KEY; + } + + if (!suc) return E_BAD_VALUE; + return E_SUCCESS; +} + +/** Generate INI file section for the unit */ +void UTOUCH_writeIni(Unit *unit, IniWriter *iw) +{ + struct priv *priv = unit->data; + + iw_comment(iw, "This unit utilizes the touch sensing controller."); + iw_comment(iw, "See the reference manual for details about its function."); + iw_cmt_newline(iw); + + iw_comment(iw, "Pulse generator clock prescaller (1,2,4,...,128)"); + iw_entry(iw, "pg-clock-prediv", "%d", (int)priv->cfg.ss_presc); + iw_comment(iw, "Sense pad charging time (1-16)"); + iw_entry(iw, "charge-time", "%d", (int)priv->cfg.charge_time); + iw_comment(iw, "Charge transfer time (1-16)"); + iw_entry(iw, "drain-time", "%d", (int)priv->cfg.drain_time); + iw_comment(iw, "Spread spectrum max deviation (0-128,0=off)"); + iw_entry(iw, "ss-deviation", "%d", (int)priv->cfg.spread_deviation); + iw_comment(iw, "Spreading clock prescaller (1,2)"); + iw_entry(iw, "ss-clock-prediv", "%d", (int)priv->cfg.ss_presc); + iw_comment(iw, "Measurement timeout (1-7)"); + iw_entry(iw, "sense-timeout", "%d", (int)priv->cfg.sense_timeout); + + iw_cmt_newline(iw); + iw_comment(iw, "Each used group must have 1 sampling capacitor and 1-3 channels."); + iw_comment(iw, "Channels are numbered 1,2,3,4"); + iw_cmt_newline(iw); + + iw_comment(iw, "Group 1: A0,A1,A2,A3"); + iw_entry(iw, "g1_cap", cfg_pinmask_encode(priv->cfg.group_scaps[0], unit_tmp512, true)); + iw_entry(iw, "g1_ch", cfg_pinmask_encode(priv->cfg.group_channels[0], unit_tmp512, true)); + + iw_comment(iw, "Group 2: A4,A5,A6,A7"); + iw_entry(iw, "g2_cap", cfg_pinmask_encode(priv->cfg.group_scaps[1], unit_tmp512, true)); + iw_entry(iw, "g2_ch", cfg_pinmask_encode(priv->cfg.group_channels[1], unit_tmp512, true)); + + iw_comment(iw, "Group 3: C5,B0,B1,B2"); + iw_entry(iw, "g3_cap", cfg_pinmask_encode(priv->cfg.group_scaps[2], unit_tmp512, true)); + iw_entry(iw, "g3_ch", cfg_pinmask_encode(priv->cfg.group_channels[2], unit_tmp512, true)); + + iw_comment(iw, "Group 4: A9,A10,A11,A12"); + iw_entry(iw, "g4_cap", cfg_pinmask_encode(priv->cfg.group_scaps[3], unit_tmp512, true)); + iw_entry(iw, "g4_ch", cfg_pinmask_encode(priv->cfg.group_channels[3], unit_tmp512, true)); + + iw_comment(iw, "Group 5: B3,B4,B6,B7"); + iw_entry(iw, "g5_cap", cfg_pinmask_encode(priv->cfg.group_scaps[4], unit_tmp512, true)); + iw_entry(iw, "g5_ch", cfg_pinmask_encode(priv->cfg.group_channels[4], unit_tmp512, true)); + + iw_comment(iw, "Group 6: B11,B12,B13,B14"); + iw_entry(iw, "g6_cap", cfg_pinmask_encode(priv->cfg.group_scaps[5], unit_tmp512, true)); + iw_entry(iw, "g6_ch", cfg_pinmask_encode(priv->cfg.group_channels[5], unit_tmp512, true)); + +#if HAVE_CH7 + iw_comment(iw, "E2,E3,E4,E5"); + iw_entry(iw, "g7_cap", cfg_pinmask_encode(priv->cfg.group_scaps[6], unit_tmp512, true)); + iw_entry(iw, "g7_ch", cfg_pinmask_encode(priv->cfg.group_channels[6], unit_tmp512, true)); +#endif +#if HAVE_CH8 + iw_comment(iw, "D12,D13,D14,D15"); + iw_entry(iw, "g8_cap", cfg_pinmask_encode(priv->cfg.group_scaps[7], unit_tmp512, true)); + iw_entry(iw, "g8_ch", cfg_pinmask_encode(priv->cfg.group_channels[7], unit_tmp512, true)); +#endif +} + diff --git a/units/touch/unit_touch.c b/units/touch/unit_touch.c new file mode 100644 index 0000000..59cd19c --- /dev/null +++ b/units/touch/unit_touch.c @@ -0,0 +1,56 @@ +// +// Created by MightyPork on 2017/11/25. +// + +#include "unit_base.h" +#include "unit_touch.h" + +#define TOUCH_INTERNAL +#include "_touch_internal.h" + +// ------------------------------------------------------------------------ + +enum TouchCmd_ { + // +}; + +/** Handle a request message */ +static error_t UTOUCH_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp) +{ + switch (command) { + default: + return E_UNKNOWN_COMMAND; + } +} + +// ------------------------------------------------------------------------ + +/** + * Handle update-tick (if configured in init) + * + * @param unit + */ +static void UTOUCH_updateTick(Unit *unit) +{ + // +} + +// ------------------------------------------------------------------------ + +/** Unit template */ +const UnitDriver UNIT_TOUCH = { + .name = "TOUCH", + .description = "Capacitive touch sensing", + // Settings + .preInit = UTOUCH_preInit, + .cfgLoadBinary = UTOUCH_loadBinary, + .cfgWriteBinary = UTOUCH_writeBinary, + .cfgLoadIni = UTOUCH_loadIni, + .cfgWriteIni = UTOUCH_writeIni, + // Init + .init = UTOUCH_init, + .deInit = UTOUCH_deInit, + // Function + .handleRequest = UTOUCH_handleRequest, + .updateTick = UTOUCH_updateTick, +}; diff --git a/units/touch/unit_touch.h b/units/touch/unit_touch.h new file mode 100644 index 0000000..dc3b2fa --- /dev/null +++ b/units/touch/unit_touch.h @@ -0,0 +1,16 @@ +// +// Created by MightyPork on 2017/11/25. +// +// Digital input unit; single or multiple pin read access on one port (A-F) +// + +#ifndef U_TOUCH_H +#define U_TOUCH_H + +#include "unit.h" + +extern const UnitDriver UNIT_TOUCH; + +// UU_ prototypes + +#endif //U_TOUCH_H