#include <math.h>
#include <float.h>
#include <string.h>
#include <stdlib.h>
#include "rcs.hh"
#include "rcs_print.hh"
#include "timer.hh"
#include "emc.hh"
#include "emc_nml.hh"
#include "emcglb.h"
#include "initool.hh"
static RCS_CMD_CHANNEL *emcIoCommandBuffer = 0;
static RCS_STAT_CHANNEL *emcIoStatusBuffer = 0;
EMC_IO_STAT *emcIoStatus = 0;
static int emcIoCommandSerialNumber = 0;
static double EMCIO_BUFFER_GET_TIMEOUT = 5.0;
static int forceCommand(RCS_CMD_MSG *msg);
static int emcioNmlGet()
{
int retval = 0;
double start_time;
RCS_PRINT_DESTINATION_TYPE orig_dest;
if (emcIoCommandBuffer == 0) {
orig_dest = get_rcs_print_destination();
set_rcs_print_destination(RCS_PRINT_TO_NULL);
start_time = etime();
while (start_time - etime() < EMCIO_BUFFER_GET_TIMEOUT) {
emcIoCommandBuffer =
new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "emc",
emc_nmlfile);
if (!emcIoCommandBuffer->valid()) {
delete emcIoCommandBuffer;
emcIoCommandBuffer = 0;
} else {
break;
}
esleep(0.1);
}
set_rcs_print_destination(orig_dest);
}
if (emcIoCommandBuffer == 0) {
emcIoCommandBuffer =
new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "emc", emc_nmlfile);
if (!emcIoCommandBuffer->valid()) {
delete emcIoCommandBuffer;
emcIoCommandBuffer = 0;
retval = -1;
}
}
if (emcIoStatusBuffer == 0) {
orig_dest = get_rcs_print_destination();
set_rcs_print_destination(RCS_PRINT_TO_NULL);
start_time = etime();
while (start_time - etime() < EMCIO_BUFFER_GET_TIMEOUT) {
emcIoStatusBuffer =
new RCS_STAT_CHANNEL(emcFormat, "toolSts", "emc",
emc_nmlfile);
if (!emcIoStatusBuffer->valid()) {
delete emcIoStatusBuffer;
emcIoStatusBuffer = 0;
} else {
emcIoStatus =
(EMC_IO_STAT *) emcIoStatusBuffer->get_address();
break;
}
esleep(0.1);
}
set_rcs_print_destination(orig_dest);
}
if (emcIoStatusBuffer == 0) {
emcIoStatusBuffer =
new RCS_STAT_CHANNEL(emcFormat, "toolSts", "emc", emc_nmlfile);
if (!emcIoStatusBuffer->valid()
|| EMC_IO_STAT_TYPE != emcIoStatusBuffer->peek()) {
delete emcIoStatusBuffer;
emcIoStatusBuffer = 0;
emcIoStatus = 0;
retval = -1;
} else {
emcIoStatus = (EMC_IO_STAT *) emcIoStatusBuffer->get_address();
}
}
return retval;
}
static RCS_CMD_MSG *last_io_command = 0;
static long largest_io_command_size = 0;
static int sendCommand(RCS_CMD_MSG * msg)
{
if (0 == emcIoCommandBuffer) {
return -1;
}
if (0 == emcIoStatusBuffer || !emcIoStatusBuffer->valid()) {
return -1;
}
if (msg->type == EMC_TOOL_ABORT_TYPE) {
int rc = forceCommand(msg);
if (rc) {
rcs_print_error("forceCommand(EMC_TOOL_ABORT) returned %d\n", rc);
}
return 0;
}
double send_command_timeout = etime() + 5.0;
int serial_diff = 0;
while (etime() < send_command_timeout) {
emcIoStatusBuffer->peek();
serial_diff = emcIoStatus->echo_serial_number - emcIoCommandSerialNumber;
if (serial_diff < 0 || emcIoStatus->status == RCS_EXEC) {
esleep(0.001);
continue;
} else {
break;
}
}
if (serial_diff < 0 || emcIoStatus->status == RCS_EXEC) {
rcs_print_error
("Command to IO level (%s:%s) timed out waiting for last command done. \n",
emcSymbolLookup(msg->type), emcIoCommandBuffer->msg2str(msg));
rcs_print_error
("emcIoStatus->echo_serial_number=%d, emcIoCommandSerialNumber=%d, emcIoStatus->status=%d\n",
emcIoStatus->echo_serial_number, emcIoCommandSerialNumber,
emcIoStatus->status);
if (0 != last_io_command) {
rcs_print_error("Last command sent to IO level was (%s:%s)\n",
emcSymbolLookup(last_io_command->type),
emcIoCommandBuffer->msg2str(last_io_command));
}
return -1;
}
if (0 != emcIoCommandBuffer->write(msg)) {
rcs_print_error("Failed to send command to IO level (%s:%s)\n",
emcSymbolLookup(msg->type),
emcIoCommandBuffer->msg2str(msg));
return -1;
}
emcIoCommandSerialNumber = msg->serial_number;
if (largest_io_command_size < msg->size) {
largest_io_command_size = std::max<long>(msg->size, 4096);
last_io_command = (RCS_CMD_MSG *) realloc(last_io_command, largest_io_command_size);
}
if (0 != last_io_command) {
memcpy(last_io_command, msg, msg->size);
}
return 0;
}
static int forceCommand(RCS_CMD_MSG * msg)
{
if (0 == emcIoCommandBuffer) {
return -1;
}
if (0 == emcIoStatusBuffer || !emcIoStatusBuffer->valid()) {
return -1;
}
if (0 != emcIoCommandBuffer->write(msg)) {
rcs_print_error("Failed to send command to IO level (%s:%s)\n",
emcSymbolLookup(msg->type),
emcIoCommandBuffer->msg2str(msg));
return -1;
}
emcIoCommandSerialNumber = msg->serial_number;
if (largest_io_command_size < msg->size) {
largest_io_command_size = std::max<long>(msg->size, 4096);
last_io_command = (RCS_CMD_MSG *) realloc(last_io_command, largest_io_command_size);
}
if (0 != last_io_command) {
memcpy(last_io_command, msg, msg->size);
}
return 0;
}
int emcIoInit()
{
EMC_TOOL_INIT ioInitMsg;
if (0 != emcioNmlGet()) {
rcs_print_error("emcioNmlGet() failed.\n");
return -1;
}
if (0 != iniTool(emc_inifile)) {
return -1;
}
if (forceCommand(&ioInitMsg)) {
rcs_print_error("Can't forceCommand(ioInitMsg)\n");
return -1;
}
return 0;
}
int emcIoHalt()
{
EMC_TOOL_HALT ioHaltMsg;
if (emcIoCommandBuffer != 0) {
forceCommand(&ioHaltMsg);
}
if (emcIoStatusBuffer != 0) {
delete emcIoStatusBuffer;
emcIoStatusBuffer = 0;
emcIoStatus = 0;
}
if (emcIoCommandBuffer != 0) {
delete emcIoCommandBuffer;
emcIoCommandBuffer = 0;
}
if (last_io_command) {
free(last_io_command);
last_io_command = 0;
}
return 0;
}
int emcIoAbort(int reason)
{
EMC_TOOL_ABORT ioAbortMsg;
ioAbortMsg.reason = reason;
sendCommand(&ioAbortMsg);
return 0;
}
int emcIoSetDebug(int debug)
{
EMC_SET_DEBUG ioDebugMsg;
ioDebugMsg.debug = debug;
return sendCommand(&ioDebugMsg);
}
int emcAuxEstopOn()
{
EMC_AUX_ESTOP_ON estopOnMsg;
return forceCommand(&estopOnMsg);
}
int emcAuxEstopOff()
{
EMC_AUX_ESTOP_OFF estopOffMsg;
return forceCommand(&estopOffMsg); }
int emcCoolantMistOn()
{
EMC_COOLANT_MIST_ON mistOnMsg;
sendCommand(&mistOnMsg);
return 0;
}
int emcCoolantMistOff()
{
EMC_COOLANT_MIST_OFF mistOffMsg;
sendCommand(&mistOffMsg);
return 0;
}
int emcCoolantFloodOn()
{
EMC_COOLANT_FLOOD_ON floodOnMsg;
sendCommand(&floodOnMsg);
return 0;
}
int emcCoolantFloodOff()
{
EMC_COOLANT_FLOOD_OFF floodOffMsg;
sendCommand(&floodOffMsg);
return 0;
}
int emcLubeOn()
{
EMC_LUBE_ON lubeOnMsg;
sendCommand(&lubeOnMsg);
return 0;
}
int emcLubeOff()
{
EMC_LUBE_OFF lubeOffMsg;
sendCommand(&lubeOffMsg);
return 0;
}
int emcToolPrepare(int p, int tool)
{
EMC_TOOL_PREPARE toolPrepareMsg;
toolPrepareMsg.pocket = p;
toolPrepareMsg.tool = tool;
sendCommand(&toolPrepareMsg);
return 0;
}
int emcToolStartChange()
{
EMC_TOOL_START_CHANGE toolStartChangeMsg;
sendCommand(&toolStartChangeMsg);
return 0;
}
int emcToolLoad()
{
EMC_TOOL_LOAD toolLoadMsg;
sendCommand(&toolLoadMsg);
return 0;
}
int emcToolUnload()
{
EMC_TOOL_UNLOAD toolUnloadMsg;
sendCommand(&toolUnloadMsg);
return 0;
}
int emcToolLoadToolTable(const char *file)
{
EMC_TOOL_LOAD_TOOL_TABLE toolLoadToolTableMsg;
strcpy(toolLoadToolTableMsg.file, file);
sendCommand(&toolLoadToolTableMsg);
return 0;
}
int emcToolSetOffset(int pocket, int toolno, EmcPose offset, double diameter,
double frontangle, double backangle, int orientation)
{
EMC_TOOL_SET_OFFSET toolSetOffsetMsg;
toolSetOffsetMsg.pocket = pocket;
toolSetOffsetMsg.toolno = toolno;
toolSetOffsetMsg.offset = offset;
toolSetOffsetMsg.diameter = diameter;
toolSetOffsetMsg.frontangle = frontangle;
toolSetOffsetMsg.backangle = backangle;
toolSetOffsetMsg.orientation = orientation;
sendCommand(&toolSetOffsetMsg);
return 0;
}
int emcToolSetNumber(int number)
{
EMC_TOOL_SET_NUMBER toolSetNumberMsg;
toolSetNumberMsg.tool = number;
sendCommand(&toolSetNumberMsg);
return 0;
}
int emcIoUpdate(EMC_IO_STAT * stat)
{
if (0 == emcIoStatusBuffer || !emcIoStatusBuffer->valid()) {
return -1;
}
switch (emcIoStatusBuffer->peek()) {
case -1:
return -1;
break;
case 0: case EMC_IO_STAT_TYPE: break;
default:
return -1;
break;
}
*stat = *emcIoStatus;
int serial_diff = emcIoStatus->echo_serial_number - emcIoCommandSerialNumber;
if (serial_diff < 0) {
stat->status = RCS_EXEC;
}
return 0;
}