// LabView LINX Remote I/O PWM services specific to the // Raspberry Pi LPC1114 I/O Processor Expansion Board // Copyright (C)2016-2018, Philip Munts, President, Munts AM Corp. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #include #include #include "linx-server/common.h" #include "lpc1114-pwm.h" //*************************************************************************** // PWM output channel constructor PWM_LPC1114::PWM_LPC1114(int32_t pin, int32_t *error) { this->pin = -1; if (!IS_PWM(pin)) { *error = ENODEV; return; } spiagent_pwm_configure(pin, error); if (*error) return; this->pin = pin; this->configured = true; *error = 0; } //*************************************************************************** // PWM output channel constructor, with deferred configuration flag PWM_LPC1114::PWM_LPC1114(int32_t pin, int32_t deferconfig, int32_t *error) { this->pin = -1; if (!IS_PWM(pin)) { *error = ENODEV; return; } if (deferconfig) { this->pin = pin; this->configured = false; } else { spiagent_pwm_configure(pin, error); if (*error) return; this->pin = pin; this->configured = true; } *error = 0; } //*************************************************************************** void PWM_LPC1114::set_frequency(uint32_t frequency, int32_t *error) { spiagent_pwm_set_frequency(frequency, error); } //*************************************************************************** // PWM output channel write() method void PWM_LPC1114::write(uint8_t dutycycle, int32_t *error) { float d = dutycycle/255.0; // Configure the PWM output, if necessary if (!this->configured) { spiagent_pwm_configure(this->pin, error); if (*error) return; this->configured = true; } spiagent_pwm_put(this->pin, d, error); } //*************************************************************************** // Custom command handler for setting the LPC1114 PWM pulse frequency, which // is common to all of the LPC1114 PWM outputs static void SetFrequency(LINX_command_t *cmd, LINX_response_t *resp, int32_t *error) { PREPARE_RESPONSE; CHECK_COMMAND_SIZE(11, 11); // Extract frequency from arguments uint32_t f = LINX_makeu32(cmd->Args[0], cmd->Args[1], cmd->Args[2], cmd->Args[3]); // Check the frequency value against the allowed range if ((f < LPC1114_PWM_FREQ_MIN) || (f > LPC1114_PWM_FREQ_MAX)) { resp->Status = L_UNKNOWN_ERROR; *error = EINVAL; return; } // Set the PWM pulse frequency spiagent_pwm_set_frequency(f, error); if (*error) { resp->Status = L_UNKNOWN_ERROR; return; } resp->Status = L_OK; *error = 0; } //*************************************************************************** void lpc1114_pwm_init(void) { int32_t error; // Register a custom command for setting the pulse frequency common to // all LPC1114 PWM outputs. The frequency should be set before // configuring any PWM outputs. AddCommand(CMD_CUSTOM1, SetFrequency); // Register PWM output channel objects pwm_add_channel(LPC1114_PWM1, new PWM_LPC1114(LPC1114_PWM1, true, &error)); pwm_add_channel(LPC1114_PWM2, new PWM_LPC1114(LPC1114_PWM2, true, &error)); pwm_add_channel(LPC1114_PWM3, new PWM_LPC1114(LPC1114_PWM3, true, &error)); pwm_add_channel(LPC1114_PWM4, new PWM_LPC1114(LPC1114_PWM4, true, &error)); }