OK, Here goes...
Code:
// HASP_COM.H
// Serial Port Setup Addresses for COM2
#define COM2_BASE 0x3F8 // Base address for COM2 Port
#define COM2_BUFFERS COM2_BASE + 0 // Transmitter Holding Buffer (W) and Receiver Buffer (R) when DLAB=0 or Divisor Latch Low Byte (R/W) when DLAB=1
#define COM2_INTERRUPT COM2_BASE + 1 // Interrupt Enable (R/W) when DLAB=0 or Divisor Latch High Byte (R/W) when DLAB=1
#define COM2_FIFO_INT_ID COM2_BASE + 2 // Interrupt Identification (R) and FIFO Control (W)
#define COM2_LINE_CONTROL COM2_BASE + 3 // Line Control Register (R/W)
#define COM2_MODEM_CONTROL COM2_BASE + 4 // Modem Control Register (R/W)
#define COM2_LINE_STATUS COM2_BASE + 5 // Line Status Register (R)
#define COM2_MODEM_STATUS COM2_BASE + 6 // Modem Status Register (R)
#define COM2_INTVECT 0x0C // COM2's IRQ Base Address
#define COM2_BUFFER_SIZE 1025 // COM2's Buffer Size in Bytes
// HASP_Comm_Setup Return Values
#define HASP_COMM_PASS 0 // HASP/GPS Communication Setup Successful
#define HASP_COMM_FAIL 1 // HASP/GPS Communication Setup Failure
Code:
// hasp_com.c
#include <stdlib.h>
#include <time.h> // time() function used to get timestamps
#include <dos.h> // delay() function
#include "help_fun.h" // Helper Functions
#include "hasp_com.h"
int COM2_Buffer_Read_Position = 0; // Position Marker for Input Buffer's Read Position
int COM2_Buffer_Write_Position = 0; // Position Marker for Input Buffer's Write Position
char COM2_Buffer[COM2_BUFFER_SIZE]; // Buffer to hold all COM2 data
int COM2_Is_Accepting_Commands = FALSE; // Flag Indicating whether COM2 (HASP) is accepting manual commands
// Begin COM2 Interrupt Setup Functions
void interrupt (*old_COM2_Interrupt)();
void interrupt COM2_Interrupt() {
COM2_Buffer[COM2_Buffer_Write_Position] = inportb(COM2_BUFFERS);
if (COM2_Is_Accepting_Commands) {
Transmit_To_HASP(&(COM2_Buffer[COM2_Buffer_Write_Position]));
COM2_Buffer_Write_Position++;
if (COM2_Buffer_Write_Position == COM2_BUFFER_SIZE - 1) COM2_Buffer_Write_Position = 0;
}
outportb(0x20, 0x20);
}
// End COM2 Interrupt Setup Functions
/* HASP Communication Setup Function
Version 0.1
April 15, 2009
Return Values : HASP_COMM_PASS (0) - HASP Communication Setup Successful
HASP_COMM_FAIL (1) - HASP Communication Setup Successful
Parameters : None
Description : Sets up the communication with the HASP/GPS
*/
int HASP_Comm_Setup () {
int HASP_Comm_Setup_Result = HASP_COMM_PASS; // Holds the value returned by HASP_Comm_Setup
//***** NOTE : INITIAL VALUES FOR RESULTS ARE SET TO FAIL - OTHER FUNCTIONS USUALLY INITIALLY SUCCESS*****//
// Setup Communication Protocol
outportb(COM2_LINE_CONTROL, 0x00); // Set DLAB = 0
outportb(COM2_INTERRUPT, 0x00); // Turn off interrupts
old_COM2_Interrupt = getvect(COM2_INTVECT); // Save Old Interrupt
setvect(COM2_INTVECT, COM2_Interrupt); // Set New Interrupt
outportb(COM2_LINE_CONTROL, 0x80); // Set DLAB = 1
outportb(COM2_BUFFERS, 0x60); // Set Baud rate to 1200 - Divisor Latch Low Byte
outportb(COM2_INTERRUPT, 0x00); // Set Baud rate to 1200 - Divisor Latch High Byte
outportb(COM2_LINE_CONTROL, 0x03); // 8 Bits, No Parity, 1 Stop Bit
outportb(COM2_FIFO_INT_ID, 0xC7); // Enable FIFO and Clear FIFO Buffers
outportb(COM2_MODEM_CONTROL, 0x0B); // Turn on DTR, RTS, and OUT2
disable();
outportb(0x21, (inportb(0x21) & 0xF7)); // Set Programmable Interrupt Controller
enable();
outportb(COM2_INTERRUPT, 0x01); // Interrupt When data recieved
return HASP_Comm_Setup_Result;
}
/* HASP Communication Shutdown Function
Version 0.1
April 15, 2009
Return Values : None
Parameters : None
Description : Shuts down the communication with the HASP
*/
void HASP_Comm_Shutdown () {
// Reset Communication Protocol to original settings
outportb(COM2_LINE_CONTROL, 0x00); // Set DLAB = 0
outportb(COM2_INTERRUPT, 0x00); // Turn off interrupts
disable();
outportb(0x21, (inportb(0x21) | 0x08)); // Set Programmable Interrupt Controller
enable();
setvect(COM2_INTVECT, old_COM2_Interrupt); // Restore Old Interrupt Vector
}
/* Reset HASP Communication Buffer Function
Version 0.1
April 15, 2009
Return Values : None
Parameters : None
Description : Resets the HASP Communication Buffer (COM2) (sets all bytes to 0 and resets the read and write positions to 0)
*/
void Reset_HASP_Comm_Buffer () {
int x;
for (x = 0; x < COM2_BUFFER_SIZE; x++) {
COM2_Buffer[x] = 0x00;
}
COM2_Buffer_Read_Position = 0;
COM2_Buffer_Write_Position = 0;
}
/* Transmit to HASP Function
Version 0.1
April 17, 2009
Return Values : None
Parameters : Log_String - String to be transmitted
Description : Transmits the given number of characters from Log_String
*/
void Transmit_To_HASP(char *Log_String) {
int Line_Ready = 0;
int Length = strlen(Log_String);
int x;
for (x = 0; x < Length; x++) {
// Check to make sure port is ready to send
while (Line_Ready == 0) {
Line_Ready = inportb(COM2_LINE_STATUS) & 0x20;
}
Line_Ready = 0;
// Send next byte
outportb(COM2_BUFFERS, Log_String[x]);
}
}
// Sets COM2_Is_Accepting_Commands Flag to given value
void Set_COM2_Is_Accepting_Commands (int Value) {
COM2_Is_Accepting_Commands = Value;
}
// Gets a manual command via COM2
char Get_Manual_Command() {
char Manual_Command = '~';
char *Temp = (char*) malloc(sizeof(char) * 5);
COM2_Is_Accepting_Commands = FALSE;
if (COM2_Buffer_Read_Position != COM2_Buffer_Write_Position) {
Manual_Command = COM2_Buffer[COM2_Buffer_Read_Position];
Transmit_To_HASP(" - Command Accepted (");
sprintf(Temp, "%c", Manual_Command);
Transmit_To_HASP(Temp);
Transmit_To_HASP(").\n\r");
Reset_HASP_Comm_Buffer();
}
COM2_Is_Accepting_Commands = TRUE;
free(Temp);
return Manual_Command;
}
Code:
// main.c
#define MAX_FAILURES 5 // Maximum number of failures allowed before action is taken
#define COLLECTION_PERIOD 20 // The number of seconds between each data dump from the DP4/DP4
// INCLUDE Files
#include <time.h> // time() function used to get timestamps
#include <stdio.h> // Standard I/O functions (File I/O)
#include "help_fun.h" // Helper Functions
#include "hasp_com.h" // HASP/GPS Communicatioln Functions (COM2)
// Function Prototypes
void Initialize (ts *Time_Stamp); // Initializes certain values and allocates memory for global variables as needed
// Global Constants
const char * const Flash_Card_Base_Path = "C:\\Data\\"; // Needs changed to actual path of Flash Card drive on SBC
const char * const Diagnostic_Log_Path = "diag_log.txt"; // Saves in program directory
const char * const Data_Log_Path = "Data\\data_log.txt"; // Saves in program directory
/* Main Function
Version 0.7
April 14, 2009
Return Values : None
Parameters : None
Description : Main Control Function
*/
int main() {
int HASP_Comm_Setup_Result = 0; // Holds the value returned by HASP_Comm_Setup
ts Time_Stamp; // Holds the old timestamp (Unix Epoch Seconds)
int Terminate_Data_Acquisition = 0;// Flag that Terminates Data Acquisition Cycle on any value other than 0
char Manual_Command = '~'; // Holds the Manual Commands sent via HASP/COM2
int x = 0;
int y = 0;
// Set all initial values
Initialize(&Time_Stamp);
// HASP/GPS Communication Setup
HASP_Comm_Setup_Result = HASP_Comm_Setup();
// Write SBC Boot Info to Log File/Screen
Write_to_Diagnostic_Log("*******************************************************************\n", -1, Diagnostic_Log_Path, &Time_Stamp);
Write_to_Diagnostic_Log("SBC booted successfully. Control software initiated.\n", -1, Diagnostic_Log_Path, &Time_Stamp);
// Write HASP Communication Setup Info to Log File/Screen
if (HASP_Comm_Setup_Result == HASP_COMM_PASS) {
Write_to_Diagnostic_Log("HASP/GPS Comm Setup..... PASSED!", -1, Diagnostic_Log_Path, &Time_Stamp);
} else {
Write_to_Diagnostic_Log("HASP/GPS Comm Setup..... FAILED! (Error Code : 0x%03X)", HASP_Comm_Setup_Result, Diagnostic_Log_Path, &Time_Stamp);
//*************************************************************************************************************************NEED CODE FOR FAILED COMMUNICATION WITH HASP/GPS
}
// Main Control Loop
Write_to_Diagnostic_Log("\n", -1, Diagnostic_Log_Path, &Time_Stamp);
Write_to_Diagnostic_Log("Begin Data Collection Phase...\n", -1, Diagnostic_Log_Path, &Time_Stamp);
while (Terminate_Data_Acquisition == 0) {
Update_Time_Stamp(&Time_Stamp, TRUE);
Write_to_Diagnostic_Log(" Collection Cycle (%d seconds) Started.", COLLECTION_PERIOD, Diagnostic_Log_Path, &Time_Stamp);
// Allow Manual Commands
Reset_HASP_Comm_Buffer();
Transmit_To_HASP("\n\r Accepting Manual Commands > ");
Manual_Command = '~';
Set_COM2_Is_Accepting_Commands(TRUE);
printf("\nAccepting Commands Delay : ");
// Wait for next time period (Flash LED While waiting)
for (x = 0; x < COLLECTION_PERIOD * 2; x++) {
delay(500);
printf("\b\b\b%03d", x);
Manual_Command = Get_Manual_Command();
switch (Manual_Command) {
case 'e': // End Collection Cycle
Write_to_Diagnostic_Log(" MANUAL COMMAND : End Collection Cycle.", -1, Diagnostic_Log_Path, &Time_Stamp);
Transmit_To_HASP("\n\r");
x = COLLECTION_PERIOD * 2;
break;
case 't': // Temporary test command
Write_to_Diagnostic_Log(" MANUAL COMMAND : Temporary Test Command.", -1, Diagnostic_Log_Path, &Time_Stamp);
Transmit_To_HASP("\n\r Accepting Manual Commands > ");
break;
case '~': // No Command Received
break;
default: // Command Received but Not recognized
Write_to_Diagnostic_Log(" MANUAL COMMAND : Command Unkown.", -1, Diagnostic_Log_Path, &Time_Stamp);
Transmit_To_HASP("\n\r Accepting Manual Commands > ");
}
// Flash LED while debugging so we know the thing is working
outportb(SBC_LED, inportb(SBC_LED) ^ 0x01);
}
Set_COM2_Is_Accepting_Commands(FALSE);
if (Manual_Command == '~') Transmit_To_HASP(" No Manual Commands Received.\n\n\r");
Write_to_Diagnostic_Log(" Collection Cycle Complete.", -1, Diagnostic_Log_Path, &Time_Stamp);
// Turn off LED
outportb(SBC_LED, inportb(SBC_LED) & 0x00);
// Pull Location Data from GPS
Transmit_To_HASP(" Switching Communication to GPS.\n\r");
Reset_HASP_Comm_Buffer();
//Get_GPS_Data_Result = Get_GPS_Data(MAX_FAILURES);
Reset_HASP_Comm_Buffer();
Transmit_To_HASP(" Returning Communication to HASP.\n\r");
// Transmit/Log GPS Results
y++; // REMOVE AFTER TESTING
if (y == 5) Terminate_Data_Acquisition = 1;// REMOVE AFTER TESTING
}
Write_to_Diagnostic_Log("End Data Collection...\n\n", -1, Diagnostic_Log_Path, &Time_Stamp);
// Write SBC Shutdown Info to Log file/Screen
Write_to_Diagnostic_Log("Control software shutting down.\n", -1, Diagnostic_Log_Path, &Time_Stamp);
Write_to_Diagnostic_Log("*******************************************************************\n", -1, Diagnostic_Log_Path, &Time_Stamp);
// Turn On LED To Signal Run Complete
outportb(SBC_LED, inportb(SBC_LED) | 0x01);
return 0;
}
/* Initialization Function
Version 0.8
April 17, 2009
Return Values : None
Parameters : Time_Stamp
Description : Initializes certain initial values
*/
void Initialize (ts *Time_Stamp) {
int x;
// Two calls are required to flush the initial values for the timestamps
Update_Time_Stamp(Time_Stamp, FALSE);
Update_Time_Stamp(Time_Stamp, FALSE);
}
Code:
// help_fun.h
#ifndef HELP_FUN_H
#define HELP_FUN_H
#include <string.h> // String Functions
#include <stdio.h> // Standard I/O functions (File I/O)
#include <stdlib.h>
#include <time.h> // time_t typedef
#define FALSE 0
#define TRUE 1
typedef struct ts{
time_t Old;
time_t New;
time_t Start; // Only updated at beginning of collection cycle
} ts;
char * String_Concat (const char *s1, const char *s2); // Concatenates two strings and returns the result. Both s1 and s2 are unchanged.
void Update_Time_Stamp (ts *Time_Stamp, int Do_Start); // Updates the the timestamp
void Write_to_Diagnostic_Log (const char * const In_String, int Error_Code,
const char * const Diagnostic_Log_Path, ts *Time_Stamp);
#endif
Code:
// help_fun.c
#include <string.h> // String Functions
#include <stdio.h> // Standard I/O functions (File I/O)
#include <stdlib.h>
#include <time.h> // time_t typedef
#include "hasp_com.h" // for sending debug info to HASP
#include "help_fun.h"
/* String Concatenation Function
Version 1.0
February 10, 2009
Return Values : A pointer to a C-Style String
Parameters : Two pointers to C-Style Strings
Description : Concatenates two C-Style strings and returns the result. Both original strings are unchanged.
*/
char * String_Concat (const char *s1, const char *s2) {
char *sTemp = (char*) malloc((sizeof(char) * strlen(s1)) + (sizeof(char) * strlen(s2)));
strcpy(sTemp, s1);
strcat(sTemp, s2);
return sTemp;
}
/* Update Time Stamp Function
Version 1.1
February 11, 2009
Return Values : None
Parameters : Time_Stamp
Do_Start - Flag indicating whether or not to update Start
Description : Copies Time_Stamp.New into Time_Stamp.Old and sets Time_Stamp.New to the current timestamp and updates Start time
*/
void Update_Time_Stamp(ts *Time_Stamp, int Do_Start) {
Time_Stamp->Old = Time_Stamp->New;
Time_Stamp->New = time(NULL);
if (Do_Start) Time_Stamp->Start = Time_Stamp->New;
}
/* Diagnostic Log Writing Function
Version 0.5
February 23, 2009
Return Values : None
Parameters : In_String - The string to write to the log/screen
Error_Code - The error code, if any, to be included in the output (any negative number and no error code is printed)
Diagnostic_Log_Path
Time_Stamp
Description : Appends the given "string" to the END of the file at the given path.
In_String is less than 5 characters then a timestamp is included, otherwise only the "string" is written. (Mainly used for printing blank lines)
NOTE : Currently does NOT generate an error if a write failure of some kind occurs
NOTE : Time_Stamp is always updated
*/
void Write_to_Diagnostic_Log(const char * const In_String, int Error_Code, const char * const Diagnostic_Log_Path, ts *Time_Stamp) {
FILE *Diagnostic_Log; // Pointer to the Diagnostic Log File
char *Temp = (char*) malloc(sizeof(char)*23); // Holds string version of Time_Stamp(New)
char *Log_String; // String to be written to log file
int Error_Code_Length = 0; // Length of the Error Code, if any
if (Error_Code > 0) Error_Code_Length = 5;
printf("\n1");
Log_String = (char*) malloc(sizeof(char) * (strlen(In_String) + 1 + Error_Code_Length));
printf("2");
if (Error_Code >= 0) sprintf(Log_String, In_String, Error_Code);
else strcpy (Log_String, In_String);
printf("3");
Diagnostic_Log = fopen(Diagnostic_Log_Path, "a");
if (Diagnostic_Log == 0) printf("FILE ERROR!");
printf("4");
Update_Time_Stamp(Time_Stamp, FALSE);
printf("5");
if (strlen(Log_String) > 5 && Log_String[0] != '*') {
strftime(Temp, 23, "(%H:%M:%S %m-%d-%Y) ", gmtime(&(Time_Stamp->New)));
fprintf(Diagnostic_Log, "%s", Temp);
}
printf("6");
fprintf(Diagnostic_Log, "%s\n", Log_String);
printf("7");
Transmit_To_HASP(String_Concat(Log_String, "\n\r"));
printf("8");
fclose(Diagnostic_Log);
free(Temp);
free(Log_String);
}
There may be references to things that I have removed from this post here for convenience. Right now they are commented out so are not part of the executing code. Hopefully this makes sense.