commit 5cbe64eda6492526fe30f11aa7da18e2335fca13
parent cd7dc4b0f0aec8900531e299b49951cfae712c53
Author: Tellenbach Reto <tellr1@bfh.ch>
Date: Mon, 15 Jun 2026 19:31:15 +0200
[wip] UART: poll
Diffstat:
8 files changed, 216 insertions(+), 41 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -5,8 +5,9 @@ pkg_check_modules(GNUNET REQUIRED gnunetutil)
add_subdirectory(lib)
add_subdirectory(gpio)
+add_subdirectory(uart)
# Manage libs
target_link_libraries(taler-digitizer
- PRIVATE bank gpio gnunetutil
+ PRIVATE bank gpio uart gnunetutil
)
\ No newline at end of file
diff --git a/src/gpio/gpiod_wrapper.c b/src/gpio/gpiod_wrapper.c
@@ -17,6 +17,12 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/**
+ * @file gpiod_wrapper.c
+ * @brief controll gpio pins
+ * @author Reto Tellenbach
+ */
+
#include "gpiod_wrapper.h"
struct gpiod_chip *gpiod_chip_open_by_name(const char *name)
diff --git a/src/gpio/gpiod_wrapper.h b/src/gpio/gpiod_wrapper.h
@@ -17,6 +17,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/**
+ * @file gpiod_wrapper.h
+ * @brief controll gpio pins
+ * @author Reto Tellenbach
+ */
+
+
#ifndef GPIOD_WRAPPER_H
#define GPIOD_WRAPPER_H
diff --git a/src/taler-digitizer.c b/src/taler-digitizer.c
@@ -36,6 +36,7 @@
#include "lib/bank_api_post_accounts_withdrawals_confirm.h"
#include "digitizer_display.h"
#include "gpio/gpiod_wrapper.h"
+#include "uart/ca_uart.h"
/**
@@ -49,6 +50,9 @@
#define SCAN_QR_TIMEOUT_SECONDS 60
#define SCAN_QR_CHECK_STATUS_INTERVAL_MILISECONDS 200
+
+#define ACCEPT_CASH_TIMEOUT_SECONDS 60
+
#define DISPLAY_BLOCK_SIZE 1024
#define DISPLAY_COUNT 750
@@ -123,17 +127,17 @@ static enum GNUNET_GenericReturnValue cfg_ca_enable;
/**
* device path to coin acceptor interface
*/
-static char *cfg_ca_device;
+static char *cfg_ca_inhibit_device;
/**
* Pin to enable Accepting coins
*/
-static unsigned long long cfg_ca_en_pin;
+static unsigned long long cfg_ca_inhibit_pin;
/**
* Pin to recive inserted amount signal
*/
-static unsigned long long cfg_ca_rx_pin;
+static char *cfg_ca_sig_device;
/**
* Biggest value of one coin insertion
@@ -153,7 +157,7 @@ static enum GNUNET_GenericReturnValue cfg_ba_enable;
/**
* device path to bill acceptor interface
*/
-static char *cfg_ba_device;
+static char *cfg_ba_inhibit_device;
/**
* Biggest value of one bill insertion
@@ -205,7 +209,12 @@ static struct gpiod_line_settings *gpio_settings;
/**
* gpio request to enable coin acceping
*/
-static struct gpiod_line_request *rl_ca_enable;
+static struct gpiod_line_request *rl_ca_inhibit;
+
+/**
+ * uart handle for Coin Acceptor signals
+ */
+static int filestream_ca;
@@ -595,7 +604,8 @@ static void
shutdown_task (void *cls)
{
(void)cls;
- gpiod_line_request_release(rl_ca_enable);
+ gpiod_line_request_release(rl_ca_inhibit);
+ close(filestream_ca);
if (NULL != get_withdrawal_handle)
{
@@ -813,12 +823,12 @@ static void Init_state_task(void *cls)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
"bill-acceptor",
- "DEVICE",
- &cfg_ba_device))
+ "INHIBIT_DEVICE",
+ &cfg_ba_inhibit_device))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"bill-acceptor",
- "DEVICE");
+ "INHIBIT_DEVICE");
global_ret = EXIT_FAILURE;
return;
}
@@ -947,36 +957,36 @@ static void Init_state_task(void *cls)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
"coin-acceptor",
- "DEVICE",
- &cfg_ca_device))
+ "INHIBIT_DEVICE",
+ &cfg_ca_inhibit_device))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"coin-acceptor",
- "DEVICE");
+ "INHIBIT_DEVICE");
global_ret = EXIT_FAILURE;
return;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
"coin-acceptor",
- "ENABLE_PIN",
- &cfg_ca_en_pin))
+ "INHIBIT_PIN",
+ &cfg_ca_inhibit_pin))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"coin-acceptor",
- "ENABLE_PIN");
+ "INHIBIT_PIN");
global_ret = EXIT_FAILURE;
return;
}
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
+ GNUNET_CONFIGURATION_get_value_string (cfg,
"coin-acceptor",
- "UART_RX_PIN",
- &cfg_ca_rx_pin))
+ "SIGNAL_DEVICE",
+ &cfg_ca_sig_device))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"coin-acceptor",
- "UART_RX_PIN");
+ "SIGNAL_DEVICE");
global_ret = EXIT_FAILURE;
return;
}
@@ -991,24 +1001,25 @@ static void Init_state_task(void *cls)
global_ret = EXIT_FAILURE;
return;
}
- rl_ca_enable = gpiod_make_line_request(cfg_ca_device,
- cfg_ca_en_pin,
+ rl_ca_inhibit = gpiod_make_line_request(cfg_ca_inhibit_device,
+ cfg_ca_inhibit_pin,
gpio_settings);
- if (NULL == rl_ca_enable)
+ if (NULL == rl_ca_inhibit)
{
TALER_LOG_ERROR("GPIO Init failed");
- gpiod_line_request_release(rl_ca_enable);
+ gpiod_line_request_release(rl_ca_inhibit);
global_ret = EXIT_FAILURE;
return;
}
- if(0 != gpiod_line_request_set_value(rl_ca_enable,
- (unsigned int)cfg_ca_en_pin,
+ if(0 != gpiod_line_request_set_value(rl_ca_inhibit,
+ (unsigned int)cfg_ca_inhibit_pin,
GPIOD_LINE_VALUE_INACTIVE))
- {
- TALER_LOG_ERROR("failed to set GPIO active");
- global_ret = EXIT_FAILURE;
- return;
- }
+ {
+ TALER_LOG_ERROR("failed to set GPIO active");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ filestream_ca = ca_uart_init(cfg_ca_sig_device,10*ACCEPT_CASH_TIMEOUT_SECONDS);
}
state_ctx->min_insertion_amount =
@@ -1153,8 +1164,8 @@ static void CountMoney_state_task(void *cls)
TALER_LOG_DEBUG ("CountMoney: %s\n",balance_str);
GNUNET_free(balance_str);
(void)cls;
- if(0 != gpiod_line_request_set_value(rl_ca_enable,
- (unsigned int)cfg_ca_en_pin,
+ if(0 != gpiod_line_request_set_value(rl_ca_inhibit,
+ (unsigned int)cfg_ca_inhibit_pin,
GPIOD_LINE_VALUE_INACTIVE))
{
GNUNET_free(temp_amount);
@@ -1185,8 +1196,8 @@ static void CountMoney_state_task(void *cls)
}else
{
GNUNET_free(temp_amount);
- if(0 != gpiod_line_request_set_value(rl_ca_enable,
- (unsigned int)cfg_ca_en_pin,
+ if(0 != gpiod_line_request_set_value(rl_ca_inhibit,
+ (unsigned int)cfg_ca_inhibit_pin,
GPIOD_LINE_VALUE_ACTIVE))
{
TALER_LOG_ERROR("failed to set GPIO active");
@@ -1200,10 +1211,49 @@ static void CountMoney_state_task(void *cls)
static void AcceptCash_state_task(void *cls)
{
- (void)cls;
TALER_LOG_DEBUG("AcceptingCash state");
- state = DIGITIZER_STATE_CASHING_UP;
- GNUNET_SCHEDULER_add_now(state_controller_task,NULL);
+ (void)cls;
+ struct TALER_Amount inserted;
+ ssize_t n;
+ uint8_t buff[32]; //only on byte read per accept cycle, but check if more than one was read
+ n = read(filestream_ca,buff,sizeof(buff));
+ state = TALER_amount_is_zero(&state_ctx->digitizer_user_balance)?
+ DIGITIZER_STATE_CANCEL_WITHDRAWAL:DIGITIZER_STATE_CASHING_UP;
+ if(0 < n)
+ {
+ for(ssize_t i=0;i<n;i++)
+ {
+ if(i>0)
+ TALER_LOG_WARNING("Multiple Coins inserted!\n");
+ strcpy(inserted.currency,cfg_currency);
+ inserted.value = buff[i] / 10;
+ inserted.fraction = buff[i] % 10 * TALER_AMOUNT_FRAC_BASE;
+ if(0 > TALER_amount_add(&state_ctx->digitizer_user_balance,
+ &state_ctx->digitizer_user_balance,
+ &inserted))
+ {
+ TALER_LOG_ERROR("adding amount failed\n");
+ GNUNET_SCHEDULER_add_now(state_controller_task,NULL);
+ return;
+ }
+ }
+ state = DIGITIZER_STATE_COUNT_MONEY;
+ GNUNET_SCHEDULER_add_now(state_controller_task,NULL);
+ return;
+ }
+ else if(n == 0)
+ {
+ TALER_LOG_INFO("No Coin inserted in time\n");
+ GNUNET_SCHEDULER_add_now(state_controller_task,NULL);
+ return;
+ }
+ else
+ {
+ TALER_LOG_INFO("Signal Error UART Coin Acceptor\n");
+ GNUNET_SCHEDULER_add_now(state_controller_task,NULL);
+ return;
+ }
+ return;
}
/**
diff --git a/src/uart/CMakeLists.txt b/src/uart/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(uart ca_uart.c)
+\ No newline at end of file
diff --git a/src/uart/ca_uart.c b/src/uart/ca_uart.c
@@ -0,0 +1,77 @@
+/*
+ This file is part of TALER cash2ecash
+ Copyright (C) 2026 GNUnet e.V.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file uart_wrapper.c
+ * @brief read UART signals
+ * @author Reto Tellenbach
+ */
+
+#include <termios.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "ca_uart.h"
+
+int
+ca_uart_init(const char *dev,const unsigned char vtime)
+{
+ int uart_filestream;
+ uart_filestream = 0;
+ // Config UART0
+ uart_filestream = open(dev, O_RDONLY | O_NOCTTY);
+ // O_RDONLY: read only
+ // O_NOCTTY: The port never becomes the controlling terminal of the process
+ // O_NDELAY: Use non-blocking I/O
+ if (-1 == uart_filestream)
+ {
+ return -1;
+ }
+ struct termios options;
+ if(0 != tcgetattr(uart_filestream,
+ &options))
+ {
+ close(uart_filestream);
+ return -1;
+ }
+ if(0 != cfsetispeed(&options, B9600))
+ {
+ close(uart_filestream);
+ return -1;
+ }
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // RAW input
+ options.c_cflag |= PARENB; // Parity bit enabled
+ options.c_iflag |= (INPCK | ISTRIP); // check and strip paryty bit
+ options.c_cflag |= CS8; // Size: 8 Bits
+ options.c_cflag |= (CREAD | CLOCAL); // These will ensure that your program does not become the 'owner' of the port subject to sporatic job control and hangup signals, and also that the serial interface driver will read incoming data bytes.
+ options.c_iflag &= ~(IXON | IXOFF | IXANY); // disable software flow controll
+ options.c_cc[VTIME] = vtime;
+ options.c_cc[VMIN] = 0;
+
+ //Flush buffers and apply setti
+ if(0 != tcsetattr(uart_filestream, TCSANOW, &options))
+ {
+ close(uart_filestream);
+ return -1;
+ }
+
+ return uart_filestream;
+}
+
+
diff --git a/src/uart/ca_uart.h b/src/uart/ca_uart.h
@@ -0,0 +1,32 @@
+/*
+ This file is part of TALER cash2ecash
+ Copyright (C) 2026 GNUnet e.V.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef CA_UART_H
+#define CA_UART_H
+
+/**
+ * @brief init UART port for Coin Acceptor signal
+ * @param dev device file of uart
+ * @param vtime wait time for signal
+ * @return -1 on error
+ */
+int
+ca_uart_init(const char *dev,const unsigned char vtime);
+
+#endif
diff --git a/taler-digitizer.conf b/taler-digitizer.conf
@@ -25,9 +25,9 @@ FRAMEBUFFER_BACKLIGHT = /sys/class/backlight/10-0045/brightness
# ENABLE, MAX_DENOMINATION, MIN_DENOMINATION
[coin-acceptor]
ENABLE = YES
-DEVICE = /dev/gpiochip0
-ENABLE_PIN = 16
-UART_RX_PIN = 15
+INHIBIT_DEVICE = /dev/gpiochip0
+INHIBIT_PIN = 16
+SIGNAL_DEVICE = /dev/gpiochip0
MAX_DENOMINATION = 5
MIN_DENOMINATION = 0.1