void parse_SE_packet(void) { UINT8 State = 0; UINT16 Power = 1024; // Extract each of the values. extract_number (kUCHAR, &State, kREQUIRED); extract_number (kUINT, &Power, kOPTIONAL); // Bail if we got a conversion error if (error_byte) { return; } // Limit check if (Power <= 1023) { StoredEngraverPower = Power; // Set up PWM for Engraver control // We will use ECCP1 and Timer2 for the engraver PWM output on RB3 // Our PWM will operate at about 40Khz. // Set our reload value PR2 = 0xFF; // Set to %50 power on boot StoredEngraverPower = 512; // Initalize Timer2 // The prescaler will be at 1 T2CONbits.T2CKPS = 0b00; // Do not generate an interrupt PIE1bits.TMR2IE = 0; TCLKCONbits.T3CCP1 = 1; // ECCP1 uses Timer1/2 and ECCP2 uses Timer3/4 TCLKCONbits.T3CCP2 = 0; // ECCP1 uses Timer1/2 and ECCP2 uses Timer3/4 CCP1CONbits.CCP1M = 0b1100; // Set EECP1 as PWM mode CCP1CONbits.P1M = 0b00; // Enhanged PWM mode: single ouptut // Set up output routing to go to RB3 (RP6) RPOR6 = 14; // 14 is CCP1/P1A - ECCP1 PWM Output Channel A T2CONbits.TMR2ON = 1; // Turn it on } // Now act on the State if (State) { // Set RB3 to StoredEngraverPower CCPR1L = StoredEngraverPower >> 2; CCP1CON = (CCP1CON & 0b11001111) | ((StoredEngraverPower << 4) & 0b00110000); } else {
// Set Pen // Usage: SP,<State>,<Duration>,<PortB_Pin><CR> // <State> is 0 (for down) or 1 (for up) // <Duration> is how long to wait (in milliseconds) before the next command // in the motion control FIFO should start. // <PortB_Pin> Is a value from 0 to 7 and allows you to re-assign the Pen // RC Servo output to different PortB pins. // This is a command that the user can send from the PC to set the pen state. // Note that there is only one pen RC servo output - if you use the <PortB_Pin> // parameter, then that new pin becomes the pen RC servo output. This command // does not allow for mulitple servo signals at the same time from port B pins. // Use the S2 command for that. // // This function will use the values for <serv_min>, <servo_max>, // <servo_rate_up> and <servo_rate_down> (SC,4 SC,5, SC,11, SC,10 commands) // when it schedules the servo command. // // Internally, the parse_SP_packet() function makes a call to // process_SP() function to actually make the change in the servo output. // void parse_SP_packet(void) { UINT8 State = 0; UINT16 CommandDuration = 0; UINT8 Pin = DEFAULT_EBB_SERVO_PORTB_PIN; ExtractReturnType Ret; // Extract each of the values. extract_number (kUCHAR, &State, kREQUIRED); extract_number (kUINT, &CommandDuration, kOPTIONAL); Ret = extract_number (kUCHAR, &Pin, kOPTIONAL); // Bail if we got a conversion error if (error_byte) { return; } // Error check if (Pin > 7) { Pin = DEFAULT_EBB_SERVO_PORTB_PIN; } if (State > 1) { State = 1; } // Make sure that the selected pin we're going to use is an output // (This code only works for PortB - maybe expand it in the future for all ports.) // TRISB = TRISB & ~(1 << Pin); // Set the PRn of the Pen Servo output // Add 3 to get from PORTB pin number to RPn number if (g_servo2_RPn != (Pin + 3)) { // if we are changing which pin the pen servo is on, we need to cancel // the servo output on the old channel first RCServo2_Move(0, g_servo2_RPn, 0, 0); // Now record the new RPn g_servo2_RPn = Pin + 3; } // Execute the servo state change process_SP(State, CommandDuration); 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; // Extract each of the values. extract_number (kUINT, &Duration, kREQUIRED); extract_number (kINT, &A1Steps, kREQUIRED); extract_number (kINT, &A2Steps, kOPTIONAL); // Bail if we got a conversion error if (error_byte) { return; } process_SM(Duration, A1Steps, A2Steps); print_ack(); }
void svg_items_container::add_item (abstract_svg_item *item) { string id = item->name (); extract_number (id.c_str ()); DEBUG_ASSERT (!id.empty ()); DEBUG_ASSERT (!contains (id)); m_map.insert (std::make_pair (id, item)); }
// Set Node counter // Usage: SN,<value><CR> // <value> is a 4 byte unsigned value void parse_SN_packet(void) { unsigned long Temp; ExtractReturnType RetVal; RetVal = extract_number (kULONG, &Temp, kREQUIRED); if (kEXTRACT_OK == RetVal) { NodeCount = Temp; } print_ack(); }
static CborError extract_length(const CborParser *parser, const uint8_t **ptr, size_t *len) { uint64_t v; CborError err = extract_number(ptr, parser->end, &v); if (err) return err; *len = v; if (v != *len) return CborErrorDataTooLarge; return CborNoError; }
// Set Layer // Usage: SL,<NewLayer><CR> void parse_SL_packet(void) { // Extract each of the values. extract_number (kUCHAR, &Layer, kREQUIRED); // Bail if we got a conversion error if (error_byte) { return; } print_ack(); }
static CborError advance_internal(CborValue *it) { uint64_t length; CborError err = extract_number(&it->ptr, it->parser->end, &length); assert(err == CborNoError); if (it->type == CborByteStringType || it->type == CborTextStringType) { assert(length == (size_t)length); assert((it->flags & CborIteratorFlag_UnknownLength) == 0); it->ptr += length; } return preparse_next_value(it); }
/** * Creates a CborValue iterator pointing to the first element of the container * represented by \a it and saves it in \a recursed. The \a it container object * needs to be kept and passed again to cbor_value_leave_container() in order * to continue iterating past this container. * * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance() */ CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed) { CborError err; assert(cbor_value_is_container(it)); *recursed = *it; if (it->flags & CborIteratorFlag_UnknownLength) { recursed->remaining = UINT32_MAX; ++recursed->ptr; err = preparse_value(recursed); if (err != CborErrorUnexpectedBreak) return err; // actually, break was expected here // it's just an empty container ++recursed->ptr; } else { uint64_t len; err = extract_number(&recursed->ptr, recursed->parser->end, &len); assert(err == CborNoError); recursed->remaining = len; if (recursed->remaining != len || len == UINT32_MAX) { // back track the pointer to indicate where the error occurred recursed->ptr = it->ptr; return CborErrorDataTooLarge; } if (recursed->type == CborMapType) { // maps have keys and values, so we need to multiply by 2 if (recursed->remaining > UINT32_MAX / 2) { // back track the pointer to indicate where the error occurred recursed->ptr = it->ptr; return CborErrorDataTooLarge; } recursed->remaining *= 2; } if (len != 0) return preparse_value(recursed); } // the case of the empty container recursed->type = CborInvalidType; recursed->remaining = 0; return CborNoError; }
/** * * Closes the CBOR container (array or map) provided by \a containerEncoder and * updates the CBOR stream provided by \a encoder. Both parameters must be the * same as were passed to cbor_encoder_create_array() or * cbor_encoder_create_map(). * * Unlike cbor_encoder_close_container(), this function checks that the number * of items (or pair of items, in the case of a map) was correct. If the number * of items inserted does not match the length originally passed to * cbor_encoder_create_array() or cbor_encoder_create_map(), this function * returns either CborErrorTooFewItems or CborErrorTooManyItems. * * \sa cbor_encoder_create_array(), cbor_encoder_create_map() */ CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder) { const uint8_t *ptr = encoder->data.ptr; CborError err = cbor_encoder_close_container(encoder, containerEncoder); if (containerEncoder->flags & CborIteratorFlag_UnknownLength || encoder->end == NULL) return err; /* check what the original length was */ uint64_t actually_added; err = extract_number(&ptr, encoder->data.ptr, &actually_added); if (err) return err; if (containerEncoder->flags & CborIteratorFlag_ContainerIsMap) { if (actually_added > SIZE_MAX / 2) return CborErrorDataTooLarge; actually_added *= 2; } return actually_added == containerEncoder->added ? CborNoError : actually_added < containerEncoder->added ? CborErrorTooManyItems : CborErrorTooFewItems; }
// 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(); }
// 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) { 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 (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 { 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; } else { Enable2IO = DISABLE_MOTOR; } } else { if (EA2 > 0) { Enable2AltIO = ENABLE_MOTOR; } else { Enable2AltIO = DISABLE_MOTOR; } } } print_ack(); }
// Stepper (mode) Configure command // SC,1,0<CR> will use just solenoid output for pen up/down // 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 (default) // 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 (both up and down) // SC,11,<servo2_rate><CR> sets the pen up speed // SC,12,<servo2_rate><CR> sets the pen down speed // SC,13,1<CR> enables RB3 as parallel input to PRG button for pause detection // SC,13,0<CR> disables RB3 as parallel input to PRG button for pause detection // SC,14,1<CR> enables solenoid output on RB4 // SC,14,0<CR> disables solenoid output on RB4 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 select which (solenoid/servo) gets used for pen if (Para1 == 1) { // Use just solenoid if (Para2 == 0) { gUseSolenoid = TRUE; gUseRCPenServo = FALSE; // Turn off RC signal on Pen Servo output RCServo2_Move(0, g_servo2_RPn, 0, 0); } // Use just RC servo else if (Para2 == 1) { gUseSolenoid = FALSE; gUseRCPenServo = TRUE; } // Use solenoid AND servo (default) else { gUseSolenoid = TRUE; gUseRCPenServo = TRUE; } // Send a new command to set the state of the servo/solenoid process_SP(PenState, 0); } // 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; Enable1AltIO_TRIS = 0; Enable2AltIO_TRIS = 0; } else { UseBuiltInDrivers = FALSE; } } // Set <min_servo> for Servo2 method else if (Para1 == 4) { g_servo2_min = Para2; } // Set <max_servo> for Servo2 else if (Para1 == 5) { g_servo2_max = Para2; } // Set <gRC2Slots> else if (Para1 == 8) { if (Para2 > MAX_RC2_SERVOS) { Para2 = MAX_RC2_SERVOS; } gRC2Slots = Para2; } else if (Para1 == 9) { if (Para2 > 6) { Para2 = 6; } gRC2SlotMS = Para2; } else if (Para1 == 10) { g_servo2_rate_up = Para2; g_servo2_rate_down = Para2; } else if (Para1 == 11) { g_servo2_rate_up = Para2; } else if (Para1 == 12) { g_servo2_rate_down = Para2; } if (Para1 == 13) { if (Para2) { UseAltPause = TRUE; } else { UseAltPause = FALSE; } } print_ack(); }
// Enable Motor // Usage: EM,<EnableAxis1>,<EnableAxis2><CR> // Everything afer EnableAxis1 is optional // Each parameter can have a value of // 0 to disable that motor driver // FOR OLD DRIVER CHIP (A3967) - can do separate enables for each axis // 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 (A4988/A4983) // (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) // Note that when using 0 or 1 for a paraemter, you can use both axis even // on a 'new' driver chip board. (i.e. EM,0,1 will disable motor 1 and enable 2) // Note that the MSx lines do not come to any headers, so even when an external // source is controlling the drivers, the PIC still needs to control the // MSx lines. void parse_EM_packet(void) { unsigned char EA1, EA2; 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 ( (DriverConfiguration == PIC_CONTROLS_DRIVERS) || (DriverConfiguration == EXTERNAL_CONTROLS_DRIVERS) ) { if (EA1 > 0) { if (DriverConfiguration == PIC_CONTROLS_DRIVERS) { Enable1IO = ENABLE_MOTOR; } 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 (DriverConfiguration == PIC_CONTROLS_DRIVERS) { Enable1IO = DISABLE_MOTOR; } } } else if (DriverConfiguration == PIC_CONTROLS_EXTERNAL) { 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 (DriverConfiguration == PIC_CONTROLS_DRIVERS) { if (EA2 > 0) { Enable2IO = ENABLE_MOTOR; } else { Enable2IO = DISABLE_MOTOR; } } else if (DriverConfiguration == PIC_CONTROLS_EXTERNAL) { if (EA2 > 0) { Enable2AltIO = ENABLE_MOTOR; } else { Enable2AltIO = DISABLE_MOTOR; } } } print_ack(); }