//
// ShockTicker.asm (a MackAsm file)
//

//
// The SATA section maps out all the variables in memory.
// There initial values are burned into the the EEPROM and
// reload at boot time.
//

//
// Constants
//
MAX_CHANNELS:		const	10		// We can handle up to 10 channels.
CHAN_NAME_BUF_SIZE: const	110		// (10 char + 1 null) * 10 names
CHAN_MSG_BUF_SIZE:	const	1000	// Up to 1k of message data

//
// System Calls
//
//
// Register Incoming Network Packet Interpt Handler.
// When the sever sends a packet to us, data is placed in memory an interupt
// handler is called (if one is registered).  The handler gets:
//   TOS   Command code that was sent to the sever
//   TOS-1 Buff address that was written to.
//   TOS-2 The number of bytes written to the buffer
//   TOS-3 Return address
// Example:
//  push	myIntHandler		// Address of the subroutine
//  syscall	REGISTER_INT_IN
// 
REGISTER_INT_IN:	const	1		// Register Incoming Network Packet Interupt Handler

//
// Register the Time of Day clock.  Use this routine to tell the kernel where
// your cock is.  It is increment a 4-byte int by 1 every millisecond.
// Example:
//  push	utcTime
//  syscall REGISTER_TIME_ADDR
//
REGISTER_TIME_ADDR:	const	2		// Register the real-time clock.

//
// Send Packet to severt.
// Tell this kernal routine what kind of data you want from the server and where to put it,
// and this will send it off to the server.  When the data comes back and is place in the
// buffer, the Incoming Network Packet Interpt Handler is called.
// Example:
//  push	len						
//  push	bufAddr
//  push	CMD_SEND_CHAN_MSGS
//  syscall TRANSMIT_PACKET
TRANSMIT_PACKET:	const	3		// push len, push buf, push cmd, syscall TRANSMIT_PACKET
CMD_SEND_TIME:			const	0	//   Send 8-bytes. 4-bytes UTC millis since 1970 + 4-bytes TZ in millis
CMD_SEND_CHAN_NAMES:	const	1	//   Send channel names command
CMD_SEND_CHAN_MSGS:		const	2	//   Send channel messages command

//
// Data
//
START DATA
utcTime:		data.l	0	// UTC milliseconds since 1970     (4 of 8 bytes)
timeZone:		data.l	0	// UTC-Local time in milliseconds. (last 4 bytes of the time packet)

mode:			data.b	0	// Mode - current "state" of the display
OFF:			const		1
ONE_CHANNEL:	const		2  // "channel" stays fixed
ALL_CHANNELS:	const		3  // "channel" keeps incrementing

curChannel:		data	0	// Current displayed channel.
chanNames:		array 	0[MAX_CHANNELS]	// An array of pointers to channel names	
chanMsgs:		array 	0[MAX_CHANNELS]	// An array of pointers to channel messages

hScrollSpeed:	data	100		// millis between scroll

// Vars used by IntHandler and NextMsg
msgCmd			data	0		// The the server was responding to.
msgPtr			data	0
msgCount		data	0
msgEndOfBuf		data	0		// Points one past the buffer

// Messages
HELLO:			data.s	"HELLO\0"

// Error messages
DONTPANIC:		data.s	"Do\0x80t Panic\0" // char 0x80="n'"

//
// All the data past this point is written to by the server.
//
channelNameStart:
numOfChans:		data	0
chanNameBuf:	array.b	0[CHAN_NAME_BUF_SIZE]	// A list of null terminaled strings
chanMsgBuf:		array.b	0[CHAN_MSG_BUF_SIZE] 


// 
START EEPROM DATA
ee_hScrollSpeed:	data	10


//
// Execution starts here.
//
START CODE
Restart:
	// Reload parameters from the EEPROM
	load	ee_hScrollSpeed
	store	hScrollSpeed

	// Register Interup Handler.
	push	IntHandler
	syscall	REGISTER_INT_IN

	// Set the Clock. 
	push	8						// ARG2 - Buf size
	push	utcTime					// ARG1 - Buff address
	push	CMD_SEND_TIME			// ARG0 - Command
	stycall	TRANSMIT_PACKET			// Send off a request for the time.  This might take a while.

	push	utcTime					// ARG0 - Push the address of our clock
	syscall	REGISTER_TIME_ADDR		// Now utcTime will auti inc by 1 once every millisecond.

	// Ask the server to send the channel names.
GetChanNames:
	push	CHAN_NAME_BUF_SIZE		// ARG2 - Max data size
	push	chanNameBuf				// ARG1 - Buffer address
	push	SEND_CHAN_NAMES			// ARG0 - Command to get channel names
	syscall	SEND_PACKET

	// Ask the server to send the channel data.
GetChanMsgs:
	push	CHAN_MSG_BUF_SIZE		// ARG2 - Max data size
	push	chanMsgBuf				// ARG1 - Buffer address
	push	SEND_CHAN_MSGS			// ARG0 - Command to get channel names
	syscall	SEND_PACKET
	

MainLoop:
	// Display next change.
	syscall

	b	MainLoop:					// Bottom of the mail loop.
//
// The "Incoming Network Packet Interpt Handler"
//   TOS   Command code that was sent to the sever
//   TOS-1 Buff address that was written to.
//   TOS-2 The number of bytes written to the buffer
//   TOS-3 Return address
IntHandler:
	store	msgCmd
	dup								// Make a copy of the buf address
	store	msgPtr
	add								// add the start address to the size
	store	msgEndOfPtr
									// Stack has only the return addres on it now.
	load	msgCmd
	push	CMD_SEND_TIME
	b.=		Done
	load	msgCmd	
	b.<>	CMD_SEND_CHAN_NAMES, TryMsgCommand
	// Hanlde new names;
	store	0, msgCount
msgLook:
	load	msgPtr
	load.b							// load *msgPtr
	push	0	
	b.<>	msgGetNExt
	// Done. Save count and restart.
	load	msgCount
	store	numOfChans
	clear							// Empty the stack
	b	GetChanMsgs
msgGetNext
	load	msgPtr
	push	chanNames
	lshift	msgCount, 1				// msgCount * sizeof(int)
	add								// push &(chanName[msgCount])
	store							// hanName[msgCount] = msgPtr
TryMsgCommand:
	load	msgCmd
	b.<>	CMD_SEND_CHAN_MSGS, Done
	// Handle new message data
Done:
	return							// Return to what we were doing.

// Utility routine used by IntHandler.
//   msgPtr - points the message to skip
//   msgEndOfBuf - point one past the end of the buffer.
//   TOS - Return address
NextMsg:
	return
	