evil-mad-EggBot/EBF/ebb.c

1246 wiersze
28 KiB
C

// Versions:
// 1.8 -
// 1.8.1 5/19/10 - Only change is to recompile with Microchip USB Stack v2.7
// 1.8.2 5/31/10 - Only change is to change name in USB enumeration string to Ei Bot Board - using new PID for SchmalzHaus
// 1.9 6/11/10 - Added two commands:
// SQ - Solenoid Query - returns 0 or 1 for down and up
// ST - Solenoid Toggle - toggles state of the servo/solenoid
#include <p18cxxx.h>
#include <usart.h>
#include <stdio.h>
#include <ctype.h>
#include <delays.h>
#include "Usb\usb.h"
#include "Usb\usb_function_cdc.h"
#include "GenericTypeDefs.h"
#include "Compiler.h"
#include "usb_config.h"
#include "Usb\usb_device.h"
#include "HardwareProfile.h"
#include "ubw.h"
#include "ebb.h"
#include "delays.h"
#include "ebb_demo.h"
/// TODO: Fix this based upon type of CPU
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
#include "RCServo2.h"
#endif
// Reload value for TIMER1
// We need a 25KHz ISR to fire, so we take Fosc (48Mhz), devide by 4
// (normal CPU instruction rate of Fosc/4), then use the TIMER1 prescaler
// to divide by 4 again. Then we use a reload value of 120 to give us
// a rate of 48MHz/4/4/120 = 25KHz.
#define TIMER1_L_RELOAD (255 - 113)
#define TIMER1_H_RELOAD (255)
// This is the value that gets multiplied by Steps/Duration to compute
// the StepAdd values.
#define OVERFLOW_MUL (0x8000 / 25)
#define MAX_RC_DURATION 11890
#if defined(BOARD_EBB_V10)
#define DIR1_BIT (0x80)
#define STEP1_BIT (0x40)
#define DIR2_BIT (0x20)
#define STEP2_BIT (0x10)
#define DIR3_BIT (0x08)
#define STEP3_BIT (0x04)
#define DIR4_BIT (0x02)
#define STEP4_BIT (0x01)
#elif defined(BOARD_EBB_V11)
#define STEP1_BIT (0x01)
#define DIR1_BIT (0x02)
#define STEP2_BIT (0x04)
#define DIR2_BIT (0x08)
#elif defined(BOARD_EBB_V12)
#define STEP1_BIT (0x01)
#define DIR1_BIT (0x02)
#define STEP2_BIT (0x04)
#define DIR2_BIT (0x08)
#elif defined(BOARD_EBB_V13)
/// TODO: Edit these
#define STEP1_BIT (0x01)
#define DIR1_BIT (0x02)
#define STEP2_BIT (0x04)
#define DIR2_BIT (0x08)
#elif defined(BOARD_UBW)
#define DIR1_BIT (0x02)
#define STEP1_BIT (0x01)
#define DIR2_BIT (0x08)
#define STEP2_BIT (0x04)
#define DIR3_BIT (0x20)
#define STEP3_BIT (0x10)
#define DIR4_BIT (0x80)
#define STEP4_BIT (0x40)
#endif
typedef enum
{
COMMAND_NONE = 0,
COMMAND_MOVE,
COMMAND_DELAY,
COMMAND_PEN_UP,
COMMAND_PEN_DOWN
} CommandType;
typedef enum
{
SOLENOID_OFF = 0,
SOLENOID_ON,
SOLENOID_PWM
} SolenoidStateType;
// LOCAL FUNCTIONS
static void process_SM(
unsigned int Duration,
signed int A1Stp,
signed int A2Stp,
signed int A3Stp,
signed int A4Stp
);
#pragma udata access fast_vars
// Working registers
static near unsigned int StepAcc[4];
static near signed int StepAdd[4];
static near unsigned int StepsCounter[4];
static near unsigned char DirBits;
static near unsigned char OutByte;
static near unsigned char TookStep;
static near unsigned char AllDone;
static near unsigned char i;
near unsigned char NextReady;
static near CommandType Command;
#pragma udata
// ToLoad registers
static signed int ToLoadStepAdd[4];
static unsigned int ToLoadStepsCounter[4];
static unsigned char ToLoadDirBits;
static CommandType ToLoadCommand;
static unsigned short ToLoadDelayCounter;
static unsigned short DelayCounter;
unsigned int DemoModeActive;
unsigned int comd_counter;
static SolenoidStateType SolenoidState;
static unsigned int SolenoidDelay;
static unsigned char UseBuiltInDrivers;
static unsigned char UseServoForUpDown;
static unsigned int g_servo_max;
static unsigned int g_servo_min;
static PenStateType PenState;
// ISR
// PORTB is the step and direction port
// RB0 = Step4
// RB1 = Dir4
// RB2 = Step3
// RB3 = Dir3
// RB4 = Step2
// RB5 = Dir2
// RB6 = Step1
// RB7 = Dir1
#pragma interrupt high_ISR
void high_ISR(void)
{
//Check which interrupt flag caused the interrupt.
//Service the interrupt
//Clear the interrupt flag
//Etc.
#if defined(USB_INTERRUPT)
USBDeviceTasks();
#endif
if (PIR1bits.TMR1IF)
{
// Clear the interrupt
PIR1bits.TMR1IF = 0;
TMR1L = TIMER1_L_RELOAD; // Set to 120 for 25KHz ISR fire
TMR1H = TIMER1_H_RELOAD; //
OutByte = DirBits;
TookStep = FALSE;
AllDone = TRUE;
if (Command == COMMAND_DELAY)
{
if (DelayCounter)
{
DelayCounter--;
}
if (DelayCounter)
{
AllDone = FALSE;
}
}
else if (Command == COMMAND_MOVE)
{
// Only output DIR bits if we are actually doing something
if (StepsCounter[0] || StepsCounter[1] || StepsCounter[2] || StepsCounter[3])
{
// Always output direction bits early so they're ready when we step
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
if (UseBuiltInDrivers)
{
PORTB = DirBits;
}
else
{
PORTC = DirBits;
}
#elif defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (UseBuiltInDrivers)
{
if (DirBits & DIR1_BIT)
{
Dir1IO = 1;
}
else
{
Dir1IO = 0;
}
if (DirBits & DIR2_BIT)
{
Dir2IO = 1;
}
else
{
Dir2IO = 0;
}
}
else
{
if (DirBits & DIR1_BIT)
{
Dir1AltIO = 1;
}
else
{
Dir1AltIO = 0;
}
if (DirBits & DIR2_BIT)
{
Dir2AltIO = 1;
}
else
{
Dir2AltIO = 0;
}
}
#endif
// Only do this if there are steps left to take
if (StepsCounter[0])
{
StepAcc[0] = StepAcc[0] + StepAdd[0];
if (StepAcc[0] > 0x8000)
{
StepAcc[0] = StepAcc[0] - 0x8000;
OutByte = OutByte | STEP1_BIT;
TookStep = TRUE;
StepsCounter[0]--;
}
AllDone = FALSE;
}
if (StepsCounter[1])
{
StepAcc[1] = StepAcc[1] + StepAdd[1];
if (StepAcc[1] > 0x8000)
{
StepAcc[1] = StepAcc[1] - 0x8000;
OutByte = OutByte | STEP2_BIT;
TookStep = TRUE;
StepsCounter[1]--;
}
AllDone = FALSE;
}
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
if (StepsCounter[2])
{
StepAcc[2] = StepAcc[2] + StepAdd[2];
if (StepAcc[2] > 0x8000)
{
StepAcc[2] = StepAcc[2] - 0x8000;
OutByte = OutByte | STEP3_BIT;
TookStep = TRUE;
StepsCounter[2]--;
}
AllDone = FALSE;
}
if (StepsCounter[3])
{
StepAcc[3] = StepAcc[3] + StepAdd[3];
if (StepAcc[3] > 0x8000)
{
StepAcc[3] = StepAcc[3] - 0x8000;
OutByte = OutByte | STEP4_BIT;
TookStep = TRUE;
StepsCounter[3]--;
}
AllDone = FALSE;
}
#endif
if (TookStep)
{
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
if (UseBuiltInDrivers)
{
PORTB = OutByte;
}
else
{
PORTC = OutByte;
}
#elif defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (UseBuiltInDrivers)
{
if (OutByte & STEP1_BIT)
{
Step1IO = 1;
}
if (OutByte & STEP2_BIT)
{
Step2IO = 1;
}
}
else
{
if (OutByte & STEP1_BIT)
{
Step1AltIO = 1;
}
if (OutByte & STEP2_BIT)
{
Step2AltIO = 1;
}
}
#endif
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
Delay1TCY();
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
if (UseBuiltInDrivers)
{
PORTB = DirBits;
}
else
{
PORTC = DirBits;
}
#elif defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (UseBuiltInDrivers)
{
Step1IO = 0;
Step2IO = 0;
}
else
{
Step1AltIO = 0;
Step2AltIO = 0;
}
#endif
}
}
}
// Check to see if we should change the state of the pen
else if (Command == COMMAND_PEN_UP)
{
if (gUseRCServo1)
{
g_RC_value[9] = g_servo_min;
}
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
else if (gUseRCServo2)
{
// This code below is the meat of the Process_S2() function
// We have to manually write it in here rather than calling
// the function because a real function inside the ISR
// causes the compiler to generate enormous amounts of setup/teardown
// code and things run way too slowly.
// Process_S2(1, g_servo2_min, 4, g_servo2_rate);
gRC2Rate[0] = g_servo2_rate;
gRC2Target[0] = g_servo2_min;
gRC2Pin[0] = 4;
if (gRC2Value[0] == 0)
{
gRC2Value[0] = g_servo2_min;
}
}
#endif
else
{
SolenoidState = SOLENOID_OFF;
}
PenUpDownIO = 0;
if (DelayCounter)
{
DelayCounter--;
}
if (DelayCounter)
{
AllDone = FALSE;
}
PenState = PEN_UP;
}
else if (Command == COMMAND_PEN_DOWN)
{
if (gUseRCServo1)
{
g_RC_value[9] = g_servo_max;
}
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
else if (gUseRCServo2)
{
// This code below is the meat of the Process_S2() function
// We have to manually write it in here rather than calling
// the function because a real function inside the ISR
// causes the compiler to generate enormous amounts of setup/teardown
// code and things run way too slowly.
// Process_S2(1, g_servo2_max, 4, g_servo2_rate);
gRC2Rate[0] = g_servo2_rate;
gRC2Target[0] = g_servo2_max;
gRC2Pin[0] = 4;
if (gRC2Value[0] == 0)
{
gRC2Value[0] = g_servo2_max;
}
}
#endif
else
{
SolenoidState = SOLENOID_ON;
}
PenUpDownIO = 1;
if (DelayCounter)
{
DelayCounter--;
}
if (DelayCounter)
{
AllDone = FALSE;
}
PenState = PEN_DOWN;
}
else
{
}
// Load the next move set in
if (AllDone && NextReady)
{
for (i=0; i<4; i++)
{
StepAdd[i] = ToLoadStepAdd[i];
StepsCounter[i] = ToLoadStepsCounter[i];
}
DirBits = ToLoadDirBits;
Command = ToLoadCommand;
DelayCounter = ToLoadDelayCounter;
NextReady = FALSE;
}
}
}
// Init code
void EBB_Init(void)
{
StepAdd[0] = 1;
StepAdd[1] = 1;
StepAdd[2] = 1;
StepAdd[3] = 1;
StepsCounter[0] = 0;
StepsCounter[1] = 0;
StepsCounter[2] = 0;
StepsCounter[3] = 0;
NextReady = FALSE;
#if defined(BOARD_EBB_V10)
// Allow access to our bits in T1CON
WDTCONbits.ADSHR = 0;
#endif
#if defined(BOARD_EBB_V10) || defined(BOARD_UBW)
// Set up TMR1 for our 25KHz High ISR for stepping
T1CONbits.RD16 = 0; // Set 8 bit mode
T1CONbits.T1RUN = 0; // System clocked from other than T1
T1CONbits.T1CKPS1 = 1; // Use 1:4 Prescale value
T1CONbits.T1CKPS0 = 0;
T1CONbits.T1OSCEN = 0; // Don't use external osc
T1CONbits.T1SYNC = 0;
T1CONbits.TMR1CS = 0; // Use Fosc/4 to clock timer
#elif defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
// Set up TMR1 for our 25KHz High ISR for stepping
T1CONbits.RD16 = 0; // Set 8 bit mode
T1CONbits.TMR1CS1 = 0; // System clocked from Fosc/4
T1CONbits.TMR1CS0 = 0;
T1CONbits.T1CKPS1 = 1; // Use 1:4 Prescale value
T1CONbits.T1CKPS0 = 0;
T1CONbits.T1OSCEN = 0; // Don't use external osc
T1CONbits.T1SYNC = 0;
#endif
TMR1L = TIMER1_L_RELOAD; // Set to 120 for 25KHz ISR fire
TMR1H = TIMER1_H_RELOAD; //
T1CONbits.TMR1ON = 1; // Turn the timer on
IPR1bits.TMR1IP = 1; // Use high priority interrupt
PIR1bits.TMR1IF = 0; // Clear the interrupt
PIE1bits.TMR1IE = 1; // Turn on the interrupt
// For debugging
#if defined(BOARD_EBB_V10)
PORTA = 0;
TRISA = 0;
PORTB = 0;
TRISB = 0;
PORTC = 0; // Start out low
TRISC = 0; // Make portC
PORTD = 0;
TRISD = 0;
PORTE = 0x16;
TRISE = 0;
PORTF = 0xA4;
TRISF = 0x40; // RF6 needs to be an input
PORTG = 0;
TRISG = 0;
PORTH = 0;
TRISH = 0;
PORTJ = 0;
TRISJ = 0;
Enable1IO = ENABLE_MOTOR;
Enable1IO_TRIS = OUTPUT_PIN;
Enable2IO = ENABLE_MOTOR;
Enable2IO_TRIS = OUTPUT_PIN;
Enable3IO = ENABLE_MOTOR;
Enable3IO_TRIS = OUTPUT_PIN;
Enable4IO = ENABLE_MOTOR;
Enable4IO_TRIS = OUTPUT_PIN;
Sleep1IO = 1;
Sleep2IO = 1;
Sleep3IO = 1;
Sleep4IO = 1;
MS1_1IO = 1;
MS2_1IO = 1;
MS1_2IO = 1;
MS2_2IO = 1;
MS1_3IO = 1;
MS2_3IO = 1;
MS1_4IO = 1;
MS2_4IO = 1;
#elif defined(BOARD_EBB_V11)
PORTA = 0;
TRISA = 0x81; // Bit0 and Bit7 needs to be an input (RA0 is REF analog input)
PORTB = 0;
TRISB = 2; // Bit1 is our StartDemo switch
INTCON2bits.RBPU = 0; // Turn on weak-pull ups for port B
PORTC = 0; // Start out low
TRISC = 0x80; // Make portC output execpt for PortC bit 7, USB bus sense
PORTD = 0;
TRISD = 0;
PORTE = 0;
TRISE = 0;
ANCON0 = 0xFE; // Let AN0 (RA0) be an analog input
ANCON1 = 0x1F; // Set all the rest to digital I/O
Enable1IO = ENABLE_MOTOR;
Enable2IO = ENABLE_MOTOR;
MS1_1IO = 1;
MS2_1IO = 1;
MS1_2IO = 1;
MS2_2IO = 1;
Sleep1IO = 1;
Sleep2IO = 1;
Step1IO = 0;
Dir1IO = 0;
Step2IO = 0;
Dir2IO = 0;
#elif defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
// PORTA = 0;
RefRA0_IO_TRIS = INPUT_PIN;
// PORTB = 0;
// INTCON2bits.RBPU = 0; // Turn on weak-pull ups for port B
// PORTC = 0; // Start out low
// TRISC = 0x80; // Make portC output execpt for PortC bit 7, USB bus sense
// PORTD = 0;
// TRISD = 0;
// PORTE = 0;
// TRISE = 0;
ANCON0 = 0xFE; // Let AN0 (RA0) be an analog input
ANCON1 = 0x1F; // Set all the rest to digital I/O
MS1_IO = 1;
MS1_IO_TRIS = OUTPUT_PIN;
MS2_IO = 1;
MS2_IO_TRIS = OUTPUT_PIN;
MS3_IO = 1;
MS3_IO_TRIS = OUTPUT_PIN;
Enable1IO = 1;
Enable1IO_TRIS = OUTPUT_PIN;
Enable2IO = 1;
Enable2IO_TRIS = OUTPUT_PIN;
Step1IO = 0;
Step1IO_TRIS = OUTPUT_PIN;
Dir1IO = 0;
Dir1IO_TRIS = OUTPUT_PIN;
Step2IO = 0;
Step2IO_TRIS = OUTPUT_PIN;
Dir2IO = 0;
Dir2IO_TRIS = OUTPUT_PIN;
#elif defined(BOARD_UBW)
PORTA = 0;
TRISA = 0;
PORTB = 0;
TRISB = 0;
PORTC = 0; // Start out low
TRISC = 0; // Make portC outputs
#endif
// Set up pen up/down direction as output
PenUpDownIO = 0;
PenUpDownIO_TRIS = OUTPUT_PIN;
SolenoidState = SOLENOID_ON;
UseBuiltInDrivers = TRUE;
gUseRCServo1 = FALSE;
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
gUseRCServo2 = TRUE;
#endif
PenState = PEN_UP;
}
// Stepper (mode) Configure command
// SC,1,0<CR> will use solenoid output for pen up/down (default)
// SC,1,1<CR> will use servo on RB1 for pen up/down
// SC,1,2<CR> will use servo on RB1 for pen up/down, but with ECCP2 (PWM) in hardware
// SC,2,0<CR> will use built-in stepper driver chips (default)
// SC,2,1<CR> will use the following pins for stepper driver outputs (EBB_V11)
// ENABLE1 = RA5
// ENABLE2 = RB5
// STEP1 = RD1
// DIR1 = RD0
// STEP2 = RC2
// DIR2 = RC0
// SC,4,<servo2_min><CR> will set <servo2_min> as the minimum value for the servo (1 to 65535)
// SC,5,<servo2_max><CR> will set <servo2_max> as the maximum value for the servo (1 to 65535)
// SC,6,<servo_min><CR> will set <servo_min> as the minimum value for the servo (1 to 11890)
// SC,7,<servo_max><CR> will set <servo_max> as the maximum value for the servo (1 to 11890)
// SC,8,<servo2_slots><CR> sets the number of slots for the servo2 system (1 to 24)
// SC,9,<servo2_slotMS><CR> sets the number of ms in duration for each slot (1 to 6)
// SC,10,<servo2_rate><CR> sets the rate of change for the servo
//
void parse_SC_packet (void)
{
unsigned char Para1 = 0;
unsigned int Para2 = 0;
// Extract each of the values.
extract_number (kUCHAR, &Para1, kREQUIRED);
extract_number (kUINT, &Para2, kREQUIRED);
// Bail if we got a conversion error
if (error_byte)
{
return;
}
// Check for command to use servo rather than solenoid (we'll leave
// the solenoid on too)
if (Para1 == 1)
{
if (Para2 == 0)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
gUseRCServo2 = FALSE;
#endif
gUseRCServo1 = FALSE;
// Turn off RC Servo pulses on RB1
g_RC_value[9] = 0;
}
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13) // NOTE: Only VBB V1.1 and above have this RC Servo option
else if (Para2 == 1)
{
gUseRCServo1 = TRUE;
gUseRCServo2 = FALSE;
TRISBbits.TRISB1 = 0; // RB1 needs to be an output
// We're going to do the work here of an 'RC' command, and set the RC servo to one
// of it limits.
// Store the new RC time value
// g_RC_value[9] = (65535 - (g_servo_min + 45));
// Only set this state if we are off - if we are already running on
// this pin, then the new value will be picked up next time around (19ms)
if (kOFF == g_RC_state[9])
{
g_RC_state[9] = kWAITING;
}
}
else
{
gUseRCServo1 = FALSE;
TRISBbits.TRISB1 = 0; // RB1 needs to be an output
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
Process_S2(1, g_servo2_min, 4, g_servo2_rate);
#endif
process_SP(PEN_UP, 0); // Start servo up
}
#endif
}
// Check for command to switch between built-in drivers and external drivers
else if (Para1 == 2)
{
if (Para2 == 0)
{
UseBuiltInDrivers = TRUE;
// Initalize the alternate driver I/O ports
Dir1AltIO_TRIS = 0;
Dir2AltIO_TRIS = 0;
Step1AltIO_TRIS = 0;
Step2AltIO_TRIS = 0;
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
Enable1AltIO_TRIS = 0;
Enable2AltIO_TRIS = 0;
#endif
}
else
{
UseBuiltInDrivers = FALSE;
}
}
// Set <min_servo> for Servo2 method
else if (Para1 == 4)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
g_servo2_min = Para2;
#endif
}
// Set <max_servo> for Servo2
else if (Para1 == 5)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
g_servo2_max = Para2;
#endif
}
// Set <min_servo>
else if (Para1 == 6)
{
if (Para2 > MAX_RC_DURATION)
{
Para2 = MAX_RC_DURATION;
}
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
g_servo_min = Para2;
#endif
}
// Set <max_servo>
else if (Para1 == 7)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (Para2 > MAX_RC_DURATION)
{
Para2 = MAX_RC_DURATION;
}
g_servo_max = Para2;
#endif
}
// Set <gRC2Slots>
else if (Para1 == 8)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (Para2 > MAX_RC2_SERVOS)
{
Para2 = MAX_RC2_SERVOS;
}
gRC2Slots = Para2;
#endif
}
else if (Para1 == 9)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (Para2 > 6)
{
Para2 = 6;
}
gRC2SlotMS = Para2;
#endif
}
else if (Para1 == 10)
{
#if defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
g_servo2_rate = Para2;
#endif
}
print_ack();
}
// The Stepper Motor command
// Usage: SM,<move_duration>,<axis1_steps>,<axis2_steps>,<axis3_steps>,<axis4_steps><CR>
// <move_duration> is a number from 1 to 65535, indiciating the number of milliseconds this move should take
// <axisX_steps> is a signed 16 bit number indicating how many steps (and what direction) the axis should take
// NOTE1: <axis2_steps>, <axis3_steps> and <axis4_steps> are optional and can be left off
// If the EBB can not make the move in the speicified time, it will take as long as it needs to at max speed
// i.e. SM,1,1000 will not produce 1000steps in 1ms. Instead, it will take 40ms (25KHz max step rate)
// NOTE2: If you specify zero steps for the axies, then you effectively create a delay. Use for small
// pauses before raising or lowering the pen, for example.
void parse_SM_packet (void)
{
unsigned int Duration;
signed int A1Steps = 0, A2Steps = 0, A3Steps = 0, A4Steps = 0;
// Extract each of the values.
extract_number (kUINT, &Duration, kREQUIRED);
extract_number (kINT, &A1Steps, kREQUIRED);
extract_number (kINT, &A2Steps, kOPTIONAL);
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
extract_number (kINT, &A3Steps, kOPTIONAL);
extract_number (kINT, &A4Steps, kOPTIONAL);
#endif
// Bail if we got a conversion error
if (error_byte)
{
return;
}
process_SM(Duration, A1Steps, A2Steps, A3Steps, A4Steps);
print_ack();
}
static void process_SM(
unsigned int Duration,
signed int A1Stp,
signed int A2Stp,
signed int A3Stp,
signed int A4Stp
)
{
// Trial: Spin here until there's space in the fifo
while(NextReady)
;
// Check for delay
if (A1Stp == 0 && A2Stp == 0 && A3Stp == 0 && A4Stp == 0)
{
ToLoadCommand = COMMAND_DELAY;
ToLoadDelayCounter = 25 * Duration;
}
else
{
ToLoadDelayCounter = 1;
ToLoadDirBits = 0;
// Always enable both motors when we want to move them
#if defined(BOARD_EBB_V10) || defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
Enable1IO = ENABLE_MOTOR;
Enable2IO = ENABLE_MOTOR;
#if defined(BOARD_EBB_V10)
Enable3IO = ENABLE_MOTOR;
Enable4IO = ENABLE_MOTOR;
#endif
#endif
// First, set the direction bits
if (A1Stp < 0)
{
ToLoadDirBits = ToLoadDirBits | DIR1_BIT;
A1Stp = -A1Stp;
}
if (A2Stp < 0)
{
ToLoadDirBits = ToLoadDirBits | DIR2_BIT;
A2Stp = -A2Stp;
}
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
if (A3Stp < 0)
{
ToLoadDirBits = ToLoadDirBits | DIR3_BIT;
A3Stp = -A3Stp;
}
if (A4Stp < 0)
{
ToLoadDirBits = ToLoadDirBits | DIR4_BIT;
A4Stp = -A4Stp;
}
#endif
// Range check Steps/Duration
// if (
// (A1Steps / Duration < 25)
// ||
// (A2Steps / Duration < 25)
// ||
// (A3Steps / Duration < 25)
// ||
// (A4Steps / Duration < 25)
// )
// {
// bitset (error_byte, kERROR_BYTE_STEPS_TO_FAST);
// return;
// }
// else
// {
// To compute StepAdd values from Duration,
ToLoadStepAdd[0] = (unsigned int)
(
((unsigned long)0x8000 * (unsigned long)A1Stp)
/
((unsigned long)25 * (unsigned long)Duration)
) + 1;
ToLoadStepsCounter[0] = A1Stp;
ToLoadStepAdd[1] = (unsigned int)
(
((unsigned long)0x8000 * (unsigned long)A2Stp)
/
((unsigned long)25 * (unsigned long)Duration)
) + 1;
ToLoadStepsCounter[1] = A2Stp;
#if defined(BOARD_UBW) || defined(BOARD_EBB_V10)
ToLoadStepAdd[2] = (unsigned int)
(
((unsigned long)0x8000 * (unsigned long)A3Stp)
/
((unsigned long)25 * (unsigned long)Duration)
) + 1;
ToLoadStepsCounter[2] = A3Stp;
ToLoadStepAdd[3] = (unsigned int)
(
((unsigned long)0x8000 * (unsigned long)A4Stp)
/
((unsigned long)25 * (unsigned long)Duration)
) + 1;
ToLoadStepsCounter[3] = A4Stp;
#endif
ToLoadCommand = COMMAND_MOVE;
//printf("SA:%5d S:%4d SA:%5d S:%4d\n\r", ToLoadStepAdd[0], ToLoadStepsCounter[0], ToLoadStepAdd[1], ToLoadStepsCounter[1]);
// }
}
NextReady = TRUE;
}
// Query Pen
// Usage: QP<CR>
// Returns: 0 for down, 1 for up, then OK<CR>
void parse_QP_packet(void)
{
printf((far rom char *)"%d\n\r", PenState);
print_ack();
}
// Toggle Pen
// Usage: TP<CR>
// Returns: OK<CR>
// Just toggles state of pen arm
void parse_TP_packet(void)
{
unsigned short CommandDuration = 500;
// Extract each of the values.
extract_number (kUINT, &CommandDuration, kOPTIONAL);
// Bail if we got a conversion error
if (error_byte)
{
return;
}
if (PenState == PEN_UP)
{
process_SP(PEN_DOWN, CommandDuration);
}
else
{
process_SP(PEN_UP, CommandDuration);
}
print_ack();
}
// Set Pen
// Usage: SP,<1,0>,<Duration><CR>
void parse_SP_packet(void)
{
unsigned char State = 0;
unsigned short CommandDuration = 0;
// Extract each of the values.
extract_number (kUCHAR, &State, kREQUIRED);
extract_number (kUINT, &CommandDuration, kOPTIONAL);
// Bail if we got a conversion error
if (error_byte)
{
return;
}
process_SP(State, CommandDuration);
print_ack();
}
void process_SP(SolenoidStateType NewState, unsigned short CommandDuration)
{
// Trial: Spin here until there's space in the fifo
while(NextReady)
;
if (NewState == PEN_UP)
{
ToLoadCommand = COMMAND_PEN_UP;
}
else
{
ToLoadCommand = COMMAND_PEN_DOWN;
}
ToLoadDelayCounter = CommandDuration * 25;
NextReady = TRUE;
}
// Enable Motor
// Usage: EM,<EnableAxis1>,<EnableAxis2>,<EnableAxis3>,<EnableAxis4><CR>
// Everything afer EnableAxis1 is optional
// Each parameter can have a value of
// 0 to disable that motor driver
// FOR OLD DRIVER CHIP
// 1 to enable the driver in 1/8th step mode
// 2 to enable the driver in 1/4 step mode
// 3 to enable the driver in 1/2 step mode
// 4 to enable the driver in full step mode
// FOR NEW DRIVER CHIP (only first parameter applies, and it applies to both drivers)
// 1 to enable the driver in 1/16th step mode
// 2 to enable the driver in 1/8 step mode
// 3 to enable the driver in 1/4 step mode
// 4 to enable the driver in 1/2 step mode
// 5 to enable the driver in full step mode
// If you disable a motor, it goes 'limp' (we clear the ENABLE pin on that motor's
// driver chip)
void parse_EM_packet(void)
{
#if defined(BOARD_EBB_V10) || defined(BOARD_EBB_V11) || defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
unsigned char EA1, EA2, EA3, EA4;
ExtractReturnType RetVal;
// Extract each of the values.
RetVal = extract_number (kUCHAR, &EA1, kREQUIRED);
if (kEXTRACT_OK == RetVal)
{
// Bail if we got a conversion error
if (error_byte)
{
return;
}
if (UseBuiltInDrivers)
{
if (EA1 > 0)
{
Enable1IO = ENABLE_MOTOR;
#if defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13)
if (EA1 == 1)
{
MS1_IO = 1;
MS2_IO = 1;
MS3_IO = 1;
}
if (EA1 == 2)
{
MS1_IO = 1;
MS2_IO = 1;
MS3_IO = 0;
}
if (EA1 == 3)
{
MS1_IO = 0;
MS2_IO = 1;
MS3_IO = 0;
}
if (EA1 == 4)
{
MS1_IO = 1;
MS2_IO = 0;
MS3_IO = 0;
}
if (EA1 == 5)
{
MS1_IO = 0;
MS2_IO = 0;
MS3_IO = 0;
}
#else
if (EA1 == 1)
{
MS1_1IO = 1;
MS2_1IO = 1;
}
if (EA1 == 2)
{
MS1_1IO = 0;
MS2_1IO = 1;
}
if (EA1 == 3)
{
MS1_1IO = 1;
MS2_1IO = 0;
}
if (EA1 == 4)
{
MS1_1IO = 0;
MS2_1IO = 0;
}
#endif
}
else
{
Enable1IO = DISABLE_MOTOR;
}
}
else
{
if (EA1 > 0)
{
Enable1AltIO = ENABLE_MOTOR;
}
else
{
Enable1AltIO = DISABLE_MOTOR;
}
}
}
RetVal = extract_number (kUCHAR, &EA2, kOPTIONAL);
if (kEXTRACT_OK == RetVal)
{
// Bail if we got a conversion error
if (error_byte)
{
return;
}
if (UseBuiltInDrivers)
{
if (EA2 > 0)
{
Enable2IO = ENABLE_MOTOR;
#if !(defined(BOARD_EBB_V12) || defined(BOARD_EBB_V13))
/// TODO: fix this based upon type of driver chip
if (EA2 == 1)
{
MS1_2IO = 1;
MS2_2IO = 1;
}
if (EA2 == 2)
{
MS1_2IO = 0;
MS2_2IO = 1;
}
if (EA2 == 3)
{
MS1_2IO = 1;
MS2_2IO = 0;
}
if (EA2 == 4)
{
MS1_2IO = 0;
MS2_2IO = 0;
}
#endif
}
else
{
Enable2IO = DISABLE_MOTOR;
}
}
else
{
if (EA2 > 0)
{
Enable2AltIO = ENABLE_MOTOR;
}
else
{
Enable2AltIO = DISABLE_MOTOR;
}
}
}
#if defined(BOARD_EBB_V10)
RetVal = extract_number (kUCHAR, &EA3, kOPTIONAL);
if (kEXTRACT_OK == RetVal)
{
// Bail if we got a conversion error
if (error_byte)
{
return;
}
if (EA3 > 0)
{
Enable3IO = ENABLE_MOTOR;
}
else
{
Enable3IO = DISABLE_MOTOR;
}
}
RetVal = extract_number (kUCHAR, &EA4, kOPTIONAL);
if (kEXTRACT_OK == RetVal)
{
// Bail if we got a conversion error
if (error_byte)
{
return;
}
if (EA4 > 0)
{
Enable4IO = ENABLE_MOTOR;
}
else
{
Enable4IO = DISABLE_MOTOR;
}
}
#endif
#endif
print_ack();
}