aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lufa/Projects/TempDataLogger/Lib/RTC.c
blob: a5291eaf3cc79a937c6d66523c213ed554f1f938 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
     Copyright (C) Dean Camera, 2017.

  dean [at] fourwalledcubicle [dot] com
           www.lufa-lib.org
*/

#include "RTC.h"

#if defined(DUMMY_RTC)

/** Current dummy RTC time and date */
static volatile TimeDate_t DummyRTC_Count;

void RTC_Init(void)
{
	DummyRTC_Count.Hour   = 0;
	DummyRTC_Count.Minute = 0;
	DummyRTC_Count.Second = 0;
	DummyRTC_Count.Day    = 1;
	DummyRTC_Count.Month  = 1;
	DummyRTC_Count.Year   = 00;
}

void RTC_Tick500ms(void)
{
	static bool HalfSecondElapsed = false;

	HalfSecondElapsed = !HalfSecondElapsed;
	if (HalfSecondElapsed == false)
	  return;

	if (++DummyRTC_Count.Second < 60)
	  return;

	DummyRTC_Count.Second = 0;

	if (++DummyRTC_Count.Minute < 60)
	  return;

	DummyRTC_Count.Minute = 0;

	if (++DummyRTC_Count.Hour < 24)
	  return;

	DummyRTC_Count.Hour = 0;

	static const char MonthLength[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	uint8_t DaysInMonth = MonthLength[DummyRTC_Count.Month - 1];

	/* Check if we need to account for a leap year */
	if ((DummyRTC_Count.Month == 2) &&
	    ((!(DummyRTC_Count.Year % 400)) || ((DummyRTC_Count.Year % 100) && !(DummyRTC_Count.Year % 4))))
	{
		DaysInMonth++;
	}

	if (++DummyRTC_Count.Day <= DaysInMonth)
	  return;

	DummyRTC_Count.Day = 1;

	if (++DummyRTC_Count.Month <= 12)
	  return;

	DummyRTC_Count.Month = 1;
	DummyRTC_Count.Year++;
}

bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate)
{
	GlobalInterruptDisable();
	DummyRTC_Count = *NewTimeDate;
	GlobalInterruptEnable();

	return true;
}

bool RTC_GetTimeDate(TimeDate_t* const TimeDate)
{
	GlobalInterruptDisable();
	*TimeDate = DummyRTC_Count;
	GlobalInterruptEnable();

	return true;
}

#else

void RTC_Init(void)
{
	/* Unused for a real external DS1307 RTC device */
}

void RTC_Tick500ms(void)
{
	/* Unused for a real external DS1307 RTC device */
}

bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate)
{
	DS1307_DateTimeRegs_t NewRegValues;
	const uint8_t         WriteAddress = 0;

	// Convert new time data to the DS1307's time register layout
	NewRegValues.Byte1.Fields.TenSec    = (NewTimeDate->Second / 10);
	NewRegValues.Byte1.Fields.Sec       = (NewTimeDate->Second % 10);
	NewRegValues.Byte1.Fields.CH        = false;
	NewRegValues.Byte2.Fields.TenMin    = (NewTimeDate->Minute / 10);
	NewRegValues.Byte2.Fields.Min       = (NewTimeDate->Minute % 10);
	NewRegValues.Byte3.Fields.TenHour   = (NewTimeDate->Hour / 10);
	NewRegValues.Byte3.Fields.Hour      = (NewTimeDate->Hour % 10);
	NewRegValues.Byte3.Fields.TwelveHourMode = false;

	// Convert new date data to the DS1307's date register layout
	NewRegValues.Byte4.Fields.DayOfWeek = 0;
	NewRegValues.Byte5.Fields.TenDay    = (NewTimeDate->Day / 10);
	NewRegValues.Byte5.Fields.Day       = (NewTimeDate->Day % 10);
	NewRegValues.Byte6.Fields.TenMonth  = (NewTimeDate->Month / 10);
	NewRegValues.Byte6.Fields.Month     = (NewTimeDate->Month % 10);
	NewRegValues.Byte7.Fields.TenYear   = (NewTimeDate->Year / 10);
	NewRegValues.Byte7.Fields.Year      = (NewTimeDate->Year % 10);

	// Write the new Time and Date into the DS1307
	if (TWI_WritePacket(DS1307_ADDRESS, 10, &WriteAddress, sizeof(WriteAddress),
	                   (uint8_t*)&NewRegValues, sizeof(DS1307_DateTimeRegs_t)) != TWI_ERROR_NoError)
	{
		return false;
	}

	return true;
}

bool RTC_GetTimeDate(TimeDate_t* const TimeDate)
{
	DS1307_DateTimeRegs_t CurrentRegValues;
	const uint8_t         ReadAddress = 0;

	// Read in the stored Time and Date from the DS1307
	if (TWI_ReadPacket(DS1307_ADDRESS, 10, &ReadAddress, sizeof(ReadAddress),
	                   (uint8_t*)&CurrentRegValues, sizeof(DS1307_DateTimeRegs_t)) != TWI_ERROR_NoError)
	{
		return false;
	}

	// Convert stored time value into decimal
	TimeDate->Second  = (CurrentRegValues.Byte1.Fields.TenSec  * 10) + CurrentRegValues.Byte1.Fields.Sec;
	TimeDate->Minute  = (CurrentRegValues.Byte2.Fields.TenMin  * 10) + CurrentRegValues.Byte2.Fields.Min;
	TimeDate->Hour    = (CurrentRegValues.Byte3.Fields.TenHour * 10) + CurrentRegValues.Byte3.Fields.Hour;

	// Convert stored date value into decimal
	TimeDate->Day    = (CurrentRegValues.Byte5.Fields.TenDay   * 10) + CurrentRegValues.Byte5.Fields.Day;
	TimeDate->Month  = (CurrentRegValues.Byte6.Fields.TenMonth * 10) + CurrentRegValues.Byte6.Fields.Month;
	TimeDate->Year   = (CurrentRegValues.Byte7.Fields.TenYear  * 10) + CurrentRegValues.Byte7.Fields.Year;

	return true;
}

#endif
">ports=1 ;; *:portrange) config_set "$section" ports "" config_set "$section" srcports "" config_set "$section" dstports "" value="$(echo "$value" | sed -e 's,-,:,g')" case "$proto" in ""|tcp|udp) append "$var" "-m ${proto:-tcp -p tcp} --sport $value --dport $value";; *) unset "$var"; return 0;; esac ports=1 ;; *:connbytes) value="$(echo "$value" | sed -e 's,-,:,g')" add_insmod ipt_connbytes append "$var" "-m connbytes --connbytes $value --connbytes-dir both --connbytes-mode bytes" ;; *:tos) add_insmod ipt_tos case "$value" in !*) append "$var" "-m tos ! --tos $value";; *) append "$var" "-m tos --tos $value" esac ;; *:dscp) add_insmod ipt_dscp dscp_option="--dscp" [ -z "${value%%[EBCA]*}" ] && dscp_option="--dscp-class" case "$value" in !*) append "$var" "-m dscp ! $dscp_option $value";; *) append "$var" "-m dscp $dscp_option $value" esac ;; *:direction) value="$(echo "$value" | sed -e 's,-,:,g')" if [ "$value" = "out" ]; then append "$var" "-o $device" elif [ "$value" = "in" ]; then append "$var" "-i $device" fi ;; 1:pktsize) value="$(echo "$value" | sed -e 's,-,:,g')" add_insmod ipt_length append "$var" "-m length --length $value" ;; 1:limit) add_insmod ipt_limit append "$var" "-m limit --limit $value" ;; 1:tcpflags) case "$proto" in tcp) append "$var" "-m tcp --tcp-flags ALL $value";; *) unset $var; return 0;; esac ;; 1:mark) config_get class "${value##!}" classnr [ -z "$class" ] && continue; case "$value" in !*) append "$var" "-m mark ! --mark $class";; *) append "$var" "-m mark --mark $class";; esac ;; 1:TOS) add_insmod ipt_TOS config_get TOS "$rule" 'TOS' suffix="-j TOS --set-tos "${TOS:-"Normal-Service"} ;; 1:DSCP) add_insmod ipt_DSCP config_get DSCP "$rule" 'DSCP' [ -z "${DSCP%%[EBCA]*}" ] && set_value="--set-dscp-class $DSCP" \ || set_value="--set-dscp $DSCP" suffix="-j DSCP $set_value" ;; esac done append "$var" "$suffix" case "$ports:$proto" in 1:) parse_matching_rule "$var" "$section" "$options" "$prefix" "$suffix" "udp";; esac } config_cb() { option_cb() { return 0 } # Section start case "$1" in interface) config_set "$2" "classgroup" "Default" config_set "$2" "upload" "128" ;; classify|default|reclassify) option_cb() { append options "$1" } ;; esac # Section end config_get TYPE "$CONFIG_SECTION" TYPE case "$TYPE" in interface) config_get_bool enabled "$CONFIG_SECTION" enabled 1 [ 1 -eq "$enabled" ] || return 0 config_get classgroup "$CONFIG_SECTION" classgroup config_set "$CONFIG_SECTION" imqdev "$C" C=$(($C+1)) append INTERFACES "$CONFIG_SECTION" config_set "$classgroup" enabled 1 config_get device "$CONFIG_SECTION" device [ -z "$device" ] && { device="$(find_ifname ${CONFIG_SECTION})" config_set "$CONFIG_SECTION" device "${device:-eth0}" } ;; classgroup) append CG "$CONFIG_SECTION";; classify|default|reclassify) case "$TYPE" in classify) var="ctrules";; *) var="rules";; esac config_get target "$CONFIG_SECTION" target config_set "$CONFIG_SECTION" options "$options" append "$var" "$CONFIG_SECTION" unset options ;; esac } enum_classes() { local c="0" config_get classes "$1" classes config_get default "$1" default for class in $classes; do c="$(($c + 1))" config_set "${class}" classnr $c case "$class" in $default) class_default=$c;; esac done class_default="${class_default:-$c}" } cls_var() { local varname="$1" local class="$2" local name="$3" local type="$4" local default="$5" local tmp tmp1 tmp2 config_get tmp1 "$class" "$name" config_get tmp2 "${class}_${type}" "$name" tmp="${tmp2:-$tmp1}" tmp="${tmp:-$tmp2}" export ${varname}="${tmp:-$default}" } tcrules() { dir=/usr/lib/qos [ -e $dir/tcrules.awk ] || dir=. echo "$cstr" | awk \ -v device="$dev" \ -v linespeed="$rate" \ -f $dir/tcrules.awk } start_interface() { local iface="$1" local num_imq="$2" config_get device "$iface" device config_get_bool enabled "$iface" enabled 1 [ -z "$device" -o 1 -ne "$enabled" ] && { return 1 } config_get upload "$iface" upload config_get halfduplex "$iface" halfduplex config_get download "$iface" download config_get classgroup "$iface" classgroup config_get_bool overhead "$iface" overhead 0 download="${download:-${halfduplex:+$upload}}" enum_classes "$classgroup" for dir in up${halfduplex} ${download:+down}; do case "$dir" in up) [ "$overhead" = 1 ] && upload=$(($upload * 98 / 100 - (15 * 128 / $upload))) dev="$device" rate="$upload" dl_mode="" prefix="cls" ;; down) add_insmod imq numdevs="$num_imq" config_get imqdev "$iface" imqdev [ "$overhead" = 1 ] && download=$(($download * 98 / 100 - (80 * 1024 / $download))) dev="imq$imqdev" rate="$download" dl_mode=1 prefix="d_cls" ;; *) continue;; esac cstr= for class in $classes; do cls_var pktsize "$class" packetsize $dir 1500 cls_var pktdelay "$class" packetdelay $dir 0 cls_var maxrate "$class" limitrate $dir 100 cls_var prio "$class" priority $dir 1 cls_var avgrate "$class" avgrate $dir 0 config_get classnr "$class" classnr append cstr "$classnr:$prio:$avgrate:$pktsize:$pktdelay:$maxrate" "$N" done append ${prefix}q "$(tcrules)" "$N" export dev_${dir}="ifconfig $dev up txqueuelen 5 >&- 2>&- tc qdisc del dev $dev root >&- 2>&- tc qdisc add dev $dev root handle 1: hfsc default ${class_default}0 tc class add dev $dev parent 1: classid 1:1 hfsc sc rate ${rate}kbit ul rate ${rate}kbit" done add_insmod cls_fw add_insmod sch_hfsc add_insmod sch_sfq add_insmod sch_red cat <<EOF ${INSMOD:+$INSMOD$N}${dev_up:+$dev_up $clsq }${imqdev:+$dev_down $d_clsq $d_clsl $d_clsf } EOF unset INSMOD clsq clsf clsl d_clsq d_clsl d_clsf dev_up dev_down } start_interfaces() { local C="$1" for iface in $INTERFACES; do start_interface "$iface" "$C" done } add_rules() { local var="$1" local rules="$2" local prefix="$3" for rule in $rules; do unset iptrule config_get target "$rule" target config_get target "$target" classnr config_get options "$rule" options ## If we want to override the TOS field, let's clear the DSCP field first. [ ! -z "$(echo $options | grep 'TOS')" ] && { s_options=${options%%TOS} add_insmod ipt_DSCP parse_matching_rule iptrule "$rule" "$s_options" "$prefix" "-j DSCP --set-dscp 0" append "$var" "$iptrule" "$N" unset iptrule } parse_matching_rule iptrule "$rule" "$options" "$prefix" "-j MARK --set-mark $target" append "$var" "$iptrule" "$N" done } start_cg() { local cg="$1" local iptrules local pktrules local sizerules local download enum_classes "$cg" add_rules iptrules "$ctrules" "iptables -t mangle -A ${cg}_ct" config_get classes "$cg" classes for class in $classes; do config_get mark "$class" classnr config_get maxsize "$class" maxsize [ -z "$maxsize" -o -z "$mark" ] || { add_insmod ipt_length append pktrules "iptables -t mangle -A ${cg} -m mark --mark $mark -m length --length $maxsize: -j MARK --set-mark 0" "$N" } done add_rules pktrules "$rules" "iptables -t mangle -A ${cg}" for iface in $INTERFACES; do config_get classgroup "$iface" classgroup config_get device "$iface" device config_get imqdev "$iface" imqdev config_get dl "$iface" download config_get halfduplex "$iface" halfduplex add_insmod ipt_IMQ append up "iptables -t mangle -A OUTPUT -o $device -j ${cg}" "$N" append up "iptables -t mangle -A FORWARD -o $device -j ${cg}" "$N" [ -z "$dl" ] || { [ -z "$halfduplex" ] || { append down "iptables -t mangle -A POSTROUTING -o $device -j IMQ --todev $imqdev" "$N" } append down "iptables -t mangle -A PREROUTING -i $device -j ${cg}" "$N" append down "iptables -t mangle -A POSTROUTING -o $device -j ${cg}" "$N" append down "iptables -t mangle -A PREROUTING -i $device -j IMQ --todev $imqdev" "$N" } done cat <<EOF $INSMOD iptables -t mangle -N ${cg} >&- 2>&- iptables -t mangle -N ${cg}_ct >&- 2>&- ${iptrules:+${iptrules}${N}iptables -t mangle -A ${cg}_ct -j CONNMARK --save-mark} iptables -t mangle -A ${cg} -j CONNMARK --restore-mark iptables -t mangle -A ${cg} -m mark --mark 0 -j ${cg}_ct $pktrules $up$N${down:+${down}$N} EOF unset INSMOD } start_firewall() { add_insmod ipt_multiport add_insmod ipt_CONNMARK cat <<EOF iptables -t mangle -F iptables -t mangle -X EOF for group in $CG; do start_cg $group done } C="0" INTERFACES="" [ -e ./qos.conf ] && { . ./qos.conf config_cb } || config_load qos C="0" for iface in $INTERFACES; do export C="$(($C + 1))" done case "$1" in all) start_interfaces "$C" start_firewall ;; interface) start_interface "$2" "$C" ;; interfaces) start_interfaces ;; firewall) start_firewall ;; esac