FUNCTION "TIMEDIFF" : TIME
TITLE = Compute TIME0 minus TIME1
	VAR_INPUT
		TIME0	: TIME;
		TIME1	: TIME;
	END_VAR
BEGIN
	L	#TIME0
	L	#TIME1
	-D
	UD	DW#16#7FFFFFFF
	T	#RET_VAL
END_FUNCTION


FUNCTION "UPDATE_TIME" : VOID
BEGIN
	CALL	"TIME_TCK" (
		RET_VAL	:= "TIME",
	)
END_FUNCTION


ORGANIZATION_BLOCK OB 1
BEGIN
M001:	CALL	"UPDATE_TIME"

// Warmup time (pypy needs this)
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "BOOT_TIME",
		RET_VAL	:= "DIFF",
	)
	L	"DIFF"
	L	T#2s
	>=D
	S	"RUNNING"

	U	"RUNNING"
	FP	"RUNNING_EDGE"
	SPBN	M005
	CALL	"__CLKRST"
	CALL	"UPDATE_TIME"
	L	"TIME"
	T	"START_TIME"
	T	"STAMP_0.1s"
	T	"STAMP_0.2s"
	T	"STAMP_0.4s"
	T	"STAMP_0.5s"
	T	"STAMP_0.8s"
	T	"STAMP_1.0s"
	T	"STAMP_1.6s"
	T	"STAMP_2.0s"
	L	0
	T	"COUNT_0.1s"
	T	"COUNT_0.2s"
	T	"COUNT_0.4s"
	T	"COUNT_0.5s"
	T	"COUNT_0.8s"
	T	"COUNT_1.0s"
	T	"COUNT_1.6s"
	T	"COUNT_2.0s"
	CLR
	=	"CLOCK_0.1s_EDGE"
	=	"CLOCK_0.2s_EDGE"
	=	"CLOCK_0.4s_EDGE"
	=	"CLOCK_0.5s_EDGE"
	=	"CLOCK_0.8s_EDGE"
	=	"CLOCK_1.0s_EDGE"
	=	"CLOCK_1.6s_EDGE"
	=	"CLOCK_2.0s_EDGE"


// Check 0.1s trigger time
M005:	U	"CLOCK_0.1s"
	FN	"CLOCK_0.1s_EDGE"
	SPBN	M010
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_0.1s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M006
	__ASSERT>=	__ACCU 1,	T#10ms
	__ASSERT<=	__ACCU 1,	T#250ms
M006:	L		"TIME"
	T		"STAMP_0.1s"
	L		"COUNT_0.1s"
	+		1
	T		"COUNT_0.1s"


// Check 0.2s trigger time
M010:	U	"CLOCK_0.2s"
	FN	"CLOCK_0.2s_EDGE"
	SPBN	M020
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_0.2s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M011
	__ASSERT>=	__ACCU 1,	T#100ms
	__ASSERT<=	__ACCU 1,	T#350ms
M011:	L		"TIME"
	T		"STAMP_0.2s"
	L		"COUNT_0.2s"
	+		1
	T		"COUNT_0.2s"

// Check 0.4s trigger time
M020:	U	"CLOCK_0.4s"
	FN	"CLOCK_0.4s_EDGE"
	SPBN	M030
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_0.4s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M021
	__ASSERT>=	__ACCU 1,	T#300ms
	__ASSERT<=	__ACCU 1,	T#550ms
M021:	L		"TIME"
	T		"STAMP_0.4s"
	L		"COUNT_0.4s"
	+		1
	T		"COUNT_0.4s"

// Check 0.5s trigger time
M030:	U	"CLOCK_0.5s"
	FN	"CLOCK_0.5s_EDGE"
	SPBN	M040
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_0.5s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M031
	__ASSERT>=	__ACCU 1,	T#400ms
	__ASSERT<=	__ACCU 1,	T#650ms
M031:	L		"TIME"
	T		"STAMP_0.5s"
	L		"COUNT_0.5s"
	+		1
	T		"COUNT_0.5s"

// Check 0.8s trigger time
M040:	U	"CLOCK_0.8s"
	FN	"CLOCK_0.8s_EDGE"
	SPBN	M050
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_0.8s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M041
	__ASSERT>=	__ACCU 1,	T#700ms
	__ASSERT<=	__ACCU 1,	T#950ms
M041:	L		"TIME"
	T		"STAMP_0.8s"
	L		"COUNT_0.8s"
	+		1
	T		"COUNT_0.8s"

// Check 1.0s trigger time
M050:	U	"CLOCK_1.0s"
	FN	"CLOCK_1.0s_EDGE"
	SPBN	M060
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_1.0s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M051
	__ASSERT>=	__ACCU 1,	T#900ms
	__ASSERT<=	__ACCU 1,	T#1s150ms
M051:	L		"TIME"
	T		"STAMP_1.0s"
	L		"COUNT_1.0s"
	+		1
	T		"COUNT_1.0s"

// Check 1.6s trigger time
M060:	U	"CLOCK_1.6s"
	FN	"CLOCK_1.6s_EDGE"
	SPBN	M070
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_1.6s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M061
	__ASSERT>=	__ACCU 1,	T#1s500ms
	__ASSERT<=	__ACCU 1,	T#1s750ms
M061:	L		"TIME"
	T		"STAMP_1.6s"
	L		"COUNT_1.6s"
	+		1
	T		"COUNT_1.6s"

// Check 2.0s trigger time
M070:	U	"CLOCK_2.0s"
	FN	"CLOCK_2.0s_EDGE"
	SPBN	M080
	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "STAMP_2.0s",
		RET_VAL	:= "DIFF",
	)
	L		"DIFF"
	UN		"RUNNING"
	SPB		M071
	__ASSERT>=	__ACCU 1,	T#1s900ms
	__ASSERT<=	__ACCU 1,	T#2s150ms
M071:	L		"TIME"
	T		"STAMP_2.0s"
	L		"COUNT_2.0s"
	+		1
	T		"COUNT_2.0s"

// Stop test, if test time complete
M080:	CALL	"TIMEDIFF" (
		TIME0	:= "TIME",
		TIME1	:= "START_TIME",
		RET_VAL	:= "DIFF",
	)
	UN		"RUNNING"
	BEB
	L		"DIFF"
	L		T#4s50ms
	<D
	BEB // Not completed, yet

	// Completed. Check trigger counts.
	L		"COUNT_0.1s"
	__ASSERT>=	__ACCU 1,	39
	__ASSERT<=	__ACCU 1,	41
	L		"COUNT_0.2s"
	__ASSERT==	__ACCU 1,	20
	L		"COUNT_0.4s"
	__ASSERT==	__ACCU 1,	10
	L		"COUNT_0.5s"
	__ASSERT==	__ACCU 1,	8
	L		"COUNT_0.8s"
	__ASSERT==	__ACCU 1,	5
	L		"COUNT_1.0s"
	__ASSERT==	__ACCU 1,	4
	L		"COUNT_1.6s"
	__ASSERT==	__ACCU 1,	2
	L		"COUNT_2.0s"
	__ASSERT==	__ACCU 1,	2
	// Everything is ok. Abort the test.
	CALL	"STP" // Stop CPU

END_ORGANIZATION_BLOCK


ORGANIZATION_BLOCK OB 100
BEGIN
	CALL	"UPDATE_TIME"
	L	"TIME"
	T	"BOOT_TIME"
	CLR
	=	"RUNNING"
	=	"RUNNING_EDGE"
END_ORGANIZATION_BLOCK
