Dave Spinden
Published © MIT

Mini But Mighty, MiniZed Alarm Clock

Adding a display to the MiniZed Motor Control live build equals an alarm clock that will be sure to start your day off on a good note.

IntermediateShowcase (no instructions)4 hours11
Mini But Mighty, MiniZed Alarm Clock

Things used in this project

Hardware components

MiniZed
Avnet MiniZed
×1
Pmod HB3
Digilent Pmod HB3
×1
Pmod OLEDrgb
Digilent Pmod OLEDrgb
×1
DC motor (generic)
×1
Bell or Similar to hit with the motor
×1

Software apps and online services

Vivado Design Suite
Xilinx Vivado Design Suite

Story

Read more

Schematics

Vivado Block Diagram

Added oled Pmod library from Digilent

Code

helloworld.c

C/C++
Moddifed Adam Taylor code to change the timer from pwm to clock counter. Added screen and clock/alarm setup.
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xil_exception.h"
#include "xttcps.h"
#include "xscugic.h"
#include "xparameters.h"
#include "PmodOLEDrgb.h"

#define GPIO_DEVICE_ID  	XPAR_XGPIOPS_0_DEVICE_ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_0_DEVICE_ID
#define	TICK_TIMER_FREQ_HZ	1  //should be 1 for real clock function, 100 to test functions
#define TTC_TICK_DEVICE_ID	XPAR_XTTCPS_0_DEVICE_ID
#define TTC_TICK_INTR_ID	XPAR_XTTCPS_0_INTR
static void TickHandler(void *CallBackRef);
int SetupTicker(XTtcPs *TtcPsInst,u16 DeviceID,u16 TtcTickIntrID,XScuGic *InterruptController);
static int SetupInterruptSystem(u16 IntcDeviceID,XScuGic *IntcInstancePtr);
int SetupTimer(u16 DeviceID,XTtcPs *TtcPsInst);
void set_pwm(u32 cycle);
void display_menu();
void update_oled();
typedef struct {
u32 OutputHz;	/* Output frequency */
XInterval Interval;	/* Interval value */
u8 Prescaler;	/* Prescaler value */
u16 Options;	/* Option settings */
} TmrCntrSetup;

XGpioPs Gpio;
XGpioPs_Config *ConfigPtr;
XTtcPs_Config *TtcConfig;
XTtcPs ttcTimer;
TmrCntrSetup *TimerSetup;
XScuGic InterruptController;  	/* Interrupt controller instance */
XTtcPs TtcPsInst;
u32 MatchValue;
static TmrCntrSetup SettingsTable={TICK_TIMER_FREQ_HZ, 0, 0, 0};

PmodOLEDrgb oledrgb;
int time_hour_int=12;
char time_hour_char[2];
int time_min_int=59;
char time_min_char[2];
int time_sec_int=0;
int AMzeroPMone=0;

int Alarm_hour_int=1;
int Alarm_min_int=0;
int AlarmAMzeroPMone=0;
char Alarm_hour_char[2];
char Alarm_min_char[2];

int main()
{
u8 DutyCycle;
char key_input;

init_platform();
printf("www.adiuvoengineering.com\n\r");
printf("mods by David Spinden\n\r");
printf("Alarm Clock Example\n\r");
OLEDrgb_begin(&oledrgb, XPAR_PMODOLEDRGB_0_AXI_LITE_GPIO_BASEADDR,XPAR_PMODOLEDRGB_0_AXI_LITE_SPI_BASEADDR);

display_menu();
update_oled();

TmrCntrSetup SettingsTable= {TICK_TIMER_FREQ_HZ, 0, 0, 0};
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
XGpioPs_SetDirectionPin(&Gpio, 54, 1);
XGpioPs_SetOutputEnablePin(&Gpio, 54, 1);
//XGpioPs_WritePin(&Gpio, 54, 0x1); //wait until alarm goes off

SetupInterruptSystem(INTC_DEVICE_ID, &InterruptController);
SetupTicker(&ttcTimer,TTC_TICK_DEVICE_ID,TTC_TICK_INTR_ID,&InterruptController);



while (1) {
	;
  }



cleanup_platform();
return 0;
}
void display_menu()
{
char hour_input[2];
char min_input[2];
char AMPMselect;
char Alarm_hour_input[2];
char Alarm_min_input[2];
char AlarmAMPMselect;

//Clear the screen
printf("\033[2J");
//Display the main menu
printf("*******************************************\n");
printf("****      www.adiuvoengineering.com    ****\n");
printf("****      Alarm Clock with Motors      ****\n");
printf("*******************************************\n");
printf("\n");
printf("   Set the Time   \n");
printf("------------------------------------------\n");
printf("\n");
printf("Enter Hour (1-12):\n");
//read(2, (char*)&hour_input, 2);
scanf("%s", hour_input);
//printf("Echo %c\n\r",hour_input);
time_hour_int = atoi(hour_input);
printf("\n");
printf("Enter Minute (0-59):\n");
//read(2, (char*)&min_input, 2);
scanf("%s", min_input);
//printf("Echo %c\n\r",min_input);
time_min_int = atoi(min_input);
printf("\n");
printf("Enter a for AM, p for PM:\n");
read(1, (char*)&AMPMselect, 1);
//printf("Echo %c\n\r",AMPMselect);
if (AMPMselect !='a')
{
	AMzeroPMone=1;
}
printf("\n");


printf("   Set the Alarm   \n");
printf("------------------------------------------\n");
printf("\n");
printf("Enter Alarm Hour (1-12):\n");
scanf("%s", Alarm_hour_input);
//printf("Echo %c\n\r",Alarm_hour_input);
Alarm_hour_int = atoi(Alarm_hour_input);
printf("\n");
printf("Enter Alarm Minute (0-59):\n");
scanf("%s", Alarm_min_input);
//printf("Echo %c\n\r",Alarm_min_input);
Alarm_min_int = atoi(Alarm_min_input);
printf("\n");
printf("Enter 'a' for AM, 'p' for PM:\n");
read(1, (char*)&AlarmAMPMselect, 1);
//printf("Echo %c\n\r",AlarmAMPMselect);
if (AlarmAMPMselect !='a')
{
	AlarmAMzeroPMone=1;
}
printf("\n");

}
void set_pwm(u32 cycle)
{
u32 MatchValue;
MatchValue = (TimerSetup->Interval * cycle) / 100;
XTtcPs_SetMatchValue(&ttcTimer, 0, MatchValue);
}
int SetupTicker(XTtcPs *TtcPsInst,u16 DeviceID,u16 TtcTickIntrID,XScuGic *InterruptController)
{
int Status;
TmrCntrSetup *TimerSetup;
XTtcPs *TtcPsTick;
TimerSetup = &SettingsTable;
TimerSetup->Options |= (XTTCPS_OPTION_INTERVAL_MODE |
XTTCPS_OPTION_MATCH_MODE | XTTCPS_OPTION_WAVE_POLARITY);
Status = SetupTimer(DeviceID,TtcPsInst);
if(Status != XST_SUCCESS) {
return Status;
}
TtcPsTick = TtcPsInst;
Status = XScuGic_Connect(InterruptController, TtcTickIntrID,
(Xil_InterruptHandler)TickHandler, (void *)TtcPsTick);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XScuGic_Enable(InterruptController, TtcTickIntrID);
XTtcPs_EnableInterrupts(TtcPsTick, XTTCPS_IXR_INTERVAL_MASK);
XTtcPs_Start(TtcPsTick);
return Status;
}
static int SetupInterruptSystem(u16 IntcDeviceID,XScuGic *IntcInstancePtr)
{
int Status;
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(IntcDeviceID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
IntcInstancePtr);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
int SetupTimer(u16 DeviceID,XTtcPs *TtcPsInst)
{
int Status;
XTtcPs_Config *Config;
XTtcPs *Timer;
TmrCntrSetup *TimerSetup;
TimerSetup = &SettingsTable;
Timer = TtcPsInst;
Config = XTtcPs_LookupConfig(DeviceID);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XTtcPs_SetOptions(Timer, TimerSetup->Options);
XTtcPs_CalcIntervalFromFreq(Timer, TimerSetup->OutputHz,
&(TimerSetup->Interval), &(TimerSetup->Prescaler));
XTtcPs_SetInterval(Timer, TimerSetup->Interval);
XTtcPs_SetPrescaler(Timer, TimerSetup->Prescaler);
return XST_SUCCESS;
}
static void TickHandler(void *CallBackRef)
{
u32 StatusEvent;
/*
* Read the interrupt status, then write it back to clear the interrupt.
*/
StatusEvent = XTtcPs_GetInterruptStatus((XTtcPs *)CallBackRef);
XTtcPs_ClearInterruptStatus((XTtcPs *)CallBackRef, StatusEvent);
//printf("timer\n\r");
/*update the flag if interrupt has been occurred*/
//UpdateFlag = TRUE;
if (time_sec_int==59)
{
	time_sec_int=0;
	if (time_min_int<59)
	{
		time_min_int++;
	}
	else
	{
		time_min_int=0;
		if (time_hour_int==13)
		{
			time_hour_int=1;
		}
		else
		{
			time_hour_int++;
		}
	}
	update_oled(); //update once a min
	if (time_hour_int==11 && time_min_int==59) //update AM/PM on next cycle
	{
		if (AMzeroPMone==0)
		{
			AMzeroPMone=1;
		}
		else
		{
			AMzeroPMone=0;
		}
	}
}
else
{
	time_sec_int++;
}

if (time_hour_int==Alarm_hour_int && time_min_int==Alarm_min_int)  //sound alarm for a min
{
	printf("Alarm\n");
	XGpioPs_WritePin(&Gpio, 54, 0x1); //motor on
}
else
{
	XGpioPs_WritePin(&Gpio, 54, 0x0);  //motor off
}
}

void update_oled()
{
	itoa(time_hour_int,time_hour_char,10);
	switch(time_min_int)
	{
	case (0):
		strcpy(time_min_char,"00");
		break;
	case(1):
		strcpy(time_min_char,"01");
		break;
	case(2):
		strcpy(time_min_char,"02");
		break;
	case(3):
		strcpy(time_min_char,"03");
		break;
	case(4):
		strcpy(time_min_char,"04");
		break;
	case(5):
		strcpy(time_min_char,"05");
		break;
	case(6):
		strcpy(time_min_char,"06");
		break;
	case(7):
		strcpy(time_min_char,"07");
		break;
	case(8):
		strcpy(time_min_char,"08");
		break;
	case(9):
		strcpy(time_min_char,"09");
		break;
	default:
		itoa(time_min_int,time_min_char,10); //already two digits
		break;
	}
	itoa(Alarm_hour_int,Alarm_hour_char,10);
		switch(Alarm_min_int)
		{
		case (0):
			strcpy(Alarm_min_char,"00");
			break;
		case(1):
			strcpy(Alarm_min_char,"01");
			break;
		case(2):
			strcpy(Alarm_min_char,"02");
			break;
		case(3):
			strcpy(Alarm_min_char,"03");
			break;
		case(4):
			strcpy(Alarm_min_char,"04");
			break;
		case(5):
			strcpy(Alarm_min_char,"05");
			break;
		case(6):
			strcpy(Alarm_min_char,"06");
			break;
		case(7):
			strcpy(Alarm_min_char,"07");
			break;
		case(8):
			strcpy(Alarm_min_char,"08");
			break;
		case(9):
			strcpy(Alarm_min_char,"09");
			break;
		default:
			itoa(Alarm_min_int,Alarm_min_char,10); //already two digits
			break;
		}





	OLEDrgb_SetCursor(&oledrgb, 5, 2);
	   OLEDrgb_PutString(&oledrgb, "Time"); // Default color (green)
	   OLEDrgb_SetCursor(&oledrgb, 4, 3);
	   OLEDrgb_SetFontColor(&oledrgb, OLEDrgb_BuildRGB(0, 0, 255)); // Blue font
	   OLEDrgb_PutString(&oledrgb, time_hour_char);
	   OLEDrgb_SetCursor(&oledrgb, 6, 3);
	   OLEDrgb_PutString(&oledrgb, ":");
	   OLEDrgb_SetCursor(&oledrgb, 7, 3);
	   OLEDrgb_PutString(&oledrgb, time_min_char);
	   OLEDrgb_SetCursor(&oledrgb, 9, 3);
	   if (AMzeroPMone==0)
	   {
		   OLEDrgb_PutString(&oledrgb, "AM");
	   }
	   else
	   {
		   OLEDrgb_PutString(&oledrgb, "PM");
	   }

	   OLEDrgb_SetFontColor(&oledrgb, OLEDrgb_BuildRGB(200, 12, 44));
	   OLEDrgb_SetCursor(&oledrgb, 4, 5);
	   OLEDrgb_PutString(&oledrgb, "Alarm");
	   OLEDrgb_SetCursor(&oledrgb, 4, 6);
	   OLEDrgb_PutString(&oledrgb, Alarm_hour_char);
	   	   OLEDrgb_SetCursor(&oledrgb, 6, 6);
	   	   OLEDrgb_PutString(&oledrgb, ":");
	   	   OLEDrgb_SetCursor(&oledrgb, 7, 6);
	   	   OLEDrgb_PutString(&oledrgb, Alarm_min_char);
	   	   OLEDrgb_SetCursor(&oledrgb, 9, 6);
	   	   if (AlarmAMzeroPMone==0)
	   	   {
	   		   OLEDrgb_PutString(&oledrgb, "AM");
	   	   }
	   	   else
	   	   {
	   		   OLEDrgb_PutString(&oledrgb, "PM");
	   	   }

}

io.xdc

Tcl
The contraints for the vivado project
set_property PACKAGE_PIN M15 [get_ports {TTC0_WAVE0_OUT_0     }];  
set_property PACKAGE_PIN L15 [get_ports {GPIO_O_0     }];  
set_property IOSTANDARD LVCMOS33 [get_ports TTC0_WAVE0_OUT_0];
set_property IOSTANDARD LVCMOS33 [get_ports GPIO_O_0];


# ----------------------------------------------------------------------------
# PL Pmod #2 using Samtec Connectors
# ---------------------------------------------------------------------------- 
# Bank 34
set_property PACKAGE_PIN P14 [get_ports {pmod_out_pin1_o_0    }];  # "P14.PMOD2_D0_N"
set_property PACKAGE_PIN P13 [get_ports {pmod_out_pin2_o_0     }];  # "P13.PMOD2_D0_P"
set_property PACKAGE_PIN N12 [get_ports {pmod_out_pin3_o_0    }];  # "N12.PMOD2_D1_N"
set_property PACKAGE_PIN N11 [get_ports {pmod_out_pin4_o_0    }];  # "N11.PMOD2_D1_P"
set_property PACKAGE_PIN R15 [get_ports {pmod_out_pin7_o_0    }];  # "R15.PMOD2_D2_N"
set_property PACKAGE_PIN P15 [get_ports {pmod_out_pin8_o_0    }];  # "P15.PMOD2_D2_P"
set_property PACKAGE_PIN R13 [get_ports {pmod_out_pin9_o_0     }];  # "R13.PMOD2_D3_N"
set_property PACKAGE_PIN R12 [get_ports {pmod_out_pin10_o_0     }];  # "R12.PMOD2_D3_P"
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin1_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin2_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin3_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin4_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin7_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin8_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin9_o_0];
set_property IOSTANDARD LVCMOS33 [get_ports pmod_out_pin10_o_0];

Credits

Dave Spinden

Dave Spinden

1 project • 0 followers

Comments

Add projectSign up / Login