Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
David Týr
Published © GPL3+

Voice Over Sigfox Network?

A simple device featuring retro mechanical pulse dial and Sigfox connectivity.

IntermediateFull instructions provided5 hours1,614
Voice Over Sigfox Network?

Things used in this project

Hardware components

TD1208
×1
TD1208 breakout
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
×1
Resistor 1M ohm
Resistor 1M ohm
×1
Capacitor 10 nF
Capacitor 10 nF
×1
rotary pulse dial from old telephone
×1
Generic push button
×1
generic battery holder
×1

Software apps and online services

Losant Platform
Losant Platform
Sigfox
Sigfox

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

enclosure TOP

enclosure BOTTOM

Schematics

Schematics

Code

Main code

C/C++
Main code utilizes modified library LCD_HD44780_EFM32
/******************************************************************************
 * @file
 * @brief Dial - rotary dial with sigfox connectivitya
 * @author David Týr
 * @version 1.0.0
 ******************************************************************************
 
 ******************************************************************************/

#include <efm32.h>
#include <em_gpio.h>
#include <td_core.h>
#include <td_sigfox.h>
#include <td_gpio.h>
#include <td_measure.h>
#include <td_rtc.h>
#include <em_timer.h>
//#include <td_tools_led.h>
#include <td_tools_switch.h>


#include <td_uart.h>
#include <td_printf.h>
//#include <td_stream.h>

#include <LCD_HD44780_EFM32.h>



#define TD_GEOLOC_USE_CODE		0
#define TD_SCHEDULER_MAX_TIMER	5


/* This file declare all "dynamic" library data. It should be last included file
 * Standard size value can be override before including this file
 */



#define TD_GEOLOC_USE_CODE 0
#include <td_config.h>

/*******************************************************************************
 *************************   DEFINES   *****************************************
 ******************************************************************************/


#define PW_PORT			TIM2_PORT
#define PW_BIT			TIM2_BIT
#define Pulse_PORT	    SCL_PORT
#define Pulse_BIT		SCL_BIT
#define Pulse_MASK		SCL_MASK
#define PDONE_PORT		SDA_PORT
#define PDONE_BIT		SDA_BIT
#define PDONE_MASK		SDA_MASK
#define BUTTON_PORT		DAC0_PORT
#define BUTTON_BIT		DAC0_BIT
#define BUTTON_MASK		DAC0_MASK


/*******************************************************************************
 ******************************  CONSTANTS  ************************************
 ******************************************************************************/

/*******************************************************************************
 *************************   PRIVATE VARIABLES   *******************************
 ******************************************************************************/

/** Button event flag */
/** Timer ID */
uint8_t Timer_timeout = 0xFF;


uint8_t SW_pulse = 0;
uint8_t SW_button = 0;
uint8_t Pulse_count = 0;
uint32_t MyNum = 0;
uint32_t Phone = 0;
uint32_t Code = 0;
uint8_t Stage = 0; //0- off 1-PWD 2-dial 3-code
static bool Disp_ON = false;
static bool SendEvent = false;

static uint8_t frame[11];


uint32_t PWD = 123;
uint16_t Timeout = 30;


/*******************************************************************************
 *************************   PRIVATE FUNCTIONS   *******************************
 ******************************************************************************/



static int COMMIT(uint32_t arg, uint8_t repetition) {

	Pulse_count--;

	TD_SCHEDULER_Restart (Timer_timeout);

	char buffer[1];

	if (Pulse_count == 0) {
		Pulse_count = 0;
		//Pulse_start = true;
		//lcd_clrscr();
		MyNum = 0;
		Stage--;

		return 0;
	}

	if (Pulse_count > 10  ) {
			Pulse_count = 0;
			return 0;
		}

	if (Pulse_count == 10) {
		Pulse_count = 0;
	}

	sprintf(buffer, "%d", Pulse_count);


	if (Stage == 1) {
		lcd_puts("*");
	}
	else {
		lcd_puts(buffer);

	}

	MyNum = (MyNum * 10) +  Pulse_count;

	Pulse_count = 0 ;

	return 1;
}

static void PULSE(uint32_t mask)
{

		Pulse_count++;

		TD_RTC_Delay(100);
		GPIO_IntConfig(Pulse_PORT, Pulse_BIT, true, false, true);

	}

static void TURN_OFF(uint32_t arg, uint8_t repetition)
{
	Disp_ON = false;
	GPIO_PinOutClear(PW_PORT, PW_BIT);
	GPIO_PinOutClear(USR0_PORT, USR0_BIT);
	GPIO_PinOutClear(USR1_PORT, USR1_BIT);
	GPIO_PinOutClear(USR2_PORT, USR2_BIT);
	GPIO_PinOutClear(USR3_PORT, USR3_BIT);
	GPIO_PinOutClear(USR4_PORT, USR4_BIT);
	GPIO_PinOutClear(DB2_PORT, DB2_BIT);
	GPIO_PinOutClear(DB3_PORT, DB3_BIT);

}


/*******************************************************************************
 **************************   PUBLIC FUNCTIONS   *******************************
 ******************************************************************************/



/***************************************************************************//**
 * @brief
 *   User setup function.
 ******************************************************************************/
void TD_USER_Setup(void)
{

	  // Initialize printf() to work with the LEUART
	 //     init_printf(TD_UART_Init(9600, true, false),
	  //    		TD_UART_Putc,
	   //   		TD_UART_Start,
	    //  		TD_UART_Stop);
	     // tfp_printf("START\r\n");

	  	// If using DB2/DB3
	    GPIO_DbgSWDIOEnable(false);
	    GPIO_DbgSWDClkEnable(false);

		 TD_RTC_Delay(10000);


			// Define the button pin as an input with an internal pull-up resistor
				GPIO_PinModeSet(PW_PORT, PW_BIT, gpioModePushPull, 0);
				GPIO_DriveModeSet(PW_PORT, gpioDriveModeHigh);




		int type;
		IRQn_Type irq_parity;


	// Define the button pin as an input with an internal pull-up resistor
		GPIO_PinModeSet(Pulse_PORT, Pulse_BIT, gpioModeInputPull, 1);

		// Set up a user hook on button pin interrupt
		type = (Pulse_MASK & TD_GPIO_ODD_MASK) ?
		TD_GPIO_USER_ODD : TD_GPIO_USER_EVEN;
		TD_GPIO_SetCallback(type, PULSE, Pulse_MASK);

		// Enable falling edge and rise interrupts on button pin
		GPIO_IntConfig(Pulse_PORT, Pulse_BIT, true, false, true);

		// Clear and enable the corresponding interrupt in the CPU's Nested Vector
		// Interrupt Controller
		irq_parity =
					(Pulse_MASK & TD_GPIO_ODD_MASK) ? GPIO_ODD_IRQn : GPIO_EVEN_IRQn;
		NVIC_ClearPendingIRQ(irq_parity);
		NVIC_EnableIRQ(irq_parity);









		// Push button initialization
		SW_pulse = TD_TOOLS_SWITCH_Init(PDONE_PORT, PDONE_BIT, gpioModeInputPull, true, true, 10, 3, 10);
		SW_button = TD_TOOLS_SWITCH_Init(BUTTON_PORT, BUTTON_BIT, gpioModeInputPull, true, true, 1, 3, 10);

		// Interrupt handling
		TD_TOOLS_SWITCH_Start(SW_pulse);
		TD_TOOLS_SWITCH_Start(SW_button);







}

/***************************************************************************//**
 * @brief
 *   User loop function.
 ******************************************************************************/
void TD_USER_Loop(void)
{
	// buttons handling
					switch (TD_TOOLS_SWITCH_Process(SW_pulse)) {
						case TD_TOOLS_SWITCH_SHORT_RELEASED:
							 COMMIT(0,0);
							break;

					default:
						break;
					}

					switch (TD_TOOLS_SWITCH_Process(SW_button)) {
						case TD_TOOLS_SWITCH_SHORT_RELEASED:



							if (!Disp_ON) {
								TD_SCHEDULER_Restart (Timer_timeout);
								Timer_timeout = TD_SCHEDULER_Append(Timeout, 0 , 0, TD_SCHEDULER_ONE_SHOT, TURN_OFF, 1); //timeout start
								GPIO_PinOutSet(PW_PORT, PW_BIT);
								TD_RTC_Delay (5000);
								lcd_init(LCD_DISP_ON_CURSOR_BLINK);

								Stage = 0;
								MyNum = 0;
								Pulse_count = 0;

								Disp_ON = true;
							}


							switch (Stage) {

							case 1:
								if (MyNum == PWD) {
									lcd_clrscr();
									lcd_home();
									 lcd_command(0x0C);
									lcd_puts("OK");

									TD_RTC_Delay (T1S);
									lcd_command(0x0F);
									Stage = 2;
								}
								else {
									lcd_clrscr();
									lcd_home();
									lcd_puts("WRONG PIN!!");

									TD_RTC_Delay (T3S);
									 MyNum =0;
									Stage = 0;
								}
							break;

							case 3:
								Phone = MyNum;
								lcd_clrscr();
								lcd_home();
								lcd_command(0x0C);
								lcd_puts("OK");
								TD_RTC_Delay (T1S);
								lcd_command(0x0F);
								Stage = 4;

							break;


							case 5:
								Code = MyNum;
								lcd_clrscr();
								lcd_home();
								lcd_command(0x0C);
								lcd_puts("TRANSMITTING...");
								SendEvent = true;

							break;

							}

						break;

					default:
						break;
					}

	if (Disp_ON) {

		switch (Stage) {

		case 0:
			lcd_clrscr();
			lcd_home();
			lcd_puts("Enter your PIN");
			MyNum = 0;
			Stage = 1;
			lcd_gotoxy(0,1);
		break;


		case 2:
			lcd_clrscr();
			lcd_home();
			lcd_puts("Phone number?");
			lcd_gotoxy(0,1);
			MyNum = 0;
			Stage = 3;
		break;

		case 4:
			lcd_clrscr();
			lcd_home();
			lcd_puts("Action code?");
			lcd_gotoxy(0,1);
			MyNum = 0;
			Stage = 5;
		break;
		}
	}

	if (SendEvent) {


				// Send the single byte counter to the SIGFOX network
				unsigned int volt = TD_MEASURE_VoltageTemperatureExtended(false);



				frame[1] = ( volt >> 8 ) & 0xff;
				frame[2] = ( volt ) & 0xff;
				frame[3] = ( Phone >> 24 ) & 0xff;
				frame[4] = ( Phone >> 16 ) & 0xff;
				frame[5] = ( Phone >> 8 ) & 0xff;
				frame[6] = ( Phone ) & 0xff;
				frame[7] = ( Code >> 24 ) & 0xff;
				frame[8] = ( Code >> 16 ) & 0xff;
				frame[9] = ( Code >> 8 ) & 0xff;
				frame[10] = ( Code ) & 0xff;



				TD_SIGFOX_Send(frame, 11, 0);

				SendEvent = false;


				lcd_clrscr();
				lcd_home();
				lcd_command(0x0C);
				lcd_puts("DONE!!!");
				TD_RTC_Delay (T5S);
				TD_SCHEDULER_Remove (Timer_timeout);
				TURN_OFF (0,0);

			}

}

LCD_HD44780_EFM32.h

C/C++
LCD HD44780 library h-file
No preview (download only).

LCD_HD44780_EFM32.c

C/C++
LCD_HD44780 library
No preview (download only).

Credits

David Týr
0 projects • 4 followers
An open-minded technological enthusiast who would like to taste everything new. In his free time, he loves to make own DIY projects.

Comments