AJ_Status AJS_TargetIO_SpiOpen(uint8_t mosi, uint8_t miso, uint8_t cs, uint8_t clk, uint32_t clock, uint8_t master, uint8_t cpol, uint8_t cpha, uint8_t data, void** spiCtx) { SPI_Pin* spi; uint8_t mode = 0; uint16_t mosiPin = AJS_TargetIO_GetInfo(mosi)->physicalPin; uint16_t misoPin = AJS_TargetIO_GetInfo(miso)->physicalPin; uint16_t csPin = AJS_TargetIO_GetInfo(cs)->physicalPin; uint16_t clkPin = AJS_TargetIO_GetInfo(clk)->physicalPin; uint8_t indexMosi, indexMiso, indexCs, indexClk; /* * Get the pin information for all the SPI pins */ for (indexMosi = 0; indexMosi < ArraySize(spiInfo); ++indexMosi) { if (spiInfo[indexMosi].pinNum == mosiPin) { break; } } for (indexMiso = 0; indexMiso < ArraySize(spiInfo); ++indexMiso) { if (spiInfo[indexMiso].pinNum == misoPin) { break; } } for (indexCs = 0; indexCs < ArraySize(spiInfo); ++indexCs) { if (spiInfo[indexCs].pinNum == csPin) { break; } } for (indexClk = 0; indexClk < ArraySize(spiInfo); ++indexClk) { if (spiInfo[indexClk].pinNum == clkPin) { break; } } spi = (SPI_Pin*)AJS_Alloc(NULL, sizeof(SPI_Pin)); spi->object = new SPI((PinName)spiInfo[indexMosi].pinId, (PinName)spiInfo[indexMiso].pinId, (PinName)spiInfo[indexClk].pinId); spi->cs = new DigitalOut((PinName)spiInfo[indexCs].pinId); spi->object->frequency(clock); /* * Mode cpol cpha * 0 0 0 * 1 0 1 * 2 1 0 * 3 1 1 */ mode = (cpol << 1 | cpha << 0); if (mode > 3) { AJ_ErrPrintf(("AJS_TargetIO_SpiOpen(): cpol/cpha must be either 0 or 1\n")); return AJ_ERR_UNEXPECTED; } spi->object->format(data, mode); *spiCtx = spi; return AJ_OK; }
AJ_Status AJS_TargetIO_I2cOpen(uint8_t sda, uint8_t scl, uint32_t clock, uint8_t mode, uint8_t ownAddress, void** ctx) { GPIO_InitTypeDef i2cGPIO; I2C_InitTypeDef i2cInit; uint16_t sdaPin = AJS_TargetIO_GetInfo(sda)->physicalPin; uint16_t sclPin = AJS_TargetIO_GetInfo(scl)->physicalPin; uint8_t indexSda, indexScl; I2C_Pin* i2cPin; uint8_t pinSource; i2cPin = AJS_Alloc(NULL, sizeof(I2C_Pin)); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); for (indexSda = 0; indexSda < ArraySize(i2cInfo); indexSda++) { if (i2cInfo[indexSda].pinNum == sda) { break; } } for (indexScl = 0; indexScl < ArraySize(i2cInfo); indexScl++) { if (i2cInfo[indexScl].pinNum == scl) { break; } } i2cGPIO.GPIO_Pin = i2cInfo[indexSda].physicalPin | i2cInfo[indexScl].physicalPin; i2cGPIO.GPIO_Mode = GPIO_Mode_AF; i2cGPIO.GPIO_OType = GPIO_OType_OD; i2cGPIO.GPIO_PuPd = GPIO_PuPd_UP; i2cGPIO.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(i2cInfo[indexSda].GPIOx, &i2cGPIO); pinSource = pinToSource(i2cInfo[indexSda].physicalPin); GPIO_PinAFConfig(i2cInfo[indexSda].GPIOx, pinSource, GPIO_AF_I2C1); pinSource = pinToSource(i2cInfo[indexScl].physicalPin); GPIO_PinAFConfig(i2cInfo[indexScl].GPIOx, pinSource, GPIO_AF_I2C1); i2cInit.I2C_Ack = I2C_Ack_Disable; i2cInit.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2cInit.I2C_ClockSpeed = clock; i2cInit.I2C_DutyCycle = I2C_DutyCycle_2; i2cInit.I2C_Mode = I2C_Mode_I2C; i2cInit.I2C_OwnAddress1 = 0x00; I2C_Init(I2C1, &i2cInit); I2C_Cmd(I2C1, ENABLE); *ctx = i2cCtx; return AJ_OK; }
extern "C" AJ_Status AJS_TargetIO_PinOpen(uint16_t pinIndex, AJS_IO_PinConfig config, void** pinCtx) { GPIO* gpio; size_t pin; uint16_t physicalPin = AJS_TargetIO_GetInfo(pinIndex)->physicalPin; for (pin = 0; pin < ArraySize(pinInfo); ++pin) { if (pinInfo[pin].pinNum == physicalPin) { break; } } if (pin >= ArraySize(pinInfo)) { return AJ_ERR_INVALID; } gpio = (GPIO*)AJS_Alloc(NULL, sizeof(GPIO)); memset(gpio, 0, sizeof(GPIO)); /* * Find if this is a digitalOut, digitalIn or both */ uint32_t direction = AJS_TargetIO_GetInfo(pinIndex)->functions; if (direction & AJS_IO_FUNCTION_DIGITAL_OUT) { gpio->out = new DigitalOut((PinName)pinInfo[pin].pinId, 0); *(gpio->out) = 0; } else if ((direction & AJS_IO_FUNCTION_DIGITAL_IN) && (config != AJS_IO_PIN_OUTPUT)) { gpio->in = new DigitalIn((PinName)pinInfo[pin].pinId); switch (config) { case (AJS_IO_PIN_OPEN_DRAIN): //gpio->in->mode(OpenDrain); //TODO: This enum does not exist break; case (AJS_IO_PIN_PULL_UP): gpio->in->mode(PullUp); break; case (AJS_IO_PIN_PULL_DOWN): gpio->in->mode(PullDown); break; default: break; } } else { gpio->inOut = new DigitalInOut((PinName)pinInfo[pin].pinId); } gpio->trigId = -1; gpio->pinIdx = pinIndex; *pinCtx = gpio; return AJ_OK; }
/* * Returns information about this pin */ static int NativeInfoGetter(duk_context* ctx) { int idx; uint32_t pin; const AJS_IO_Info* info; duk_push_this(ctx); pin = GetPinId(ctx, -1, 0); duk_pop(ctx); info = AJS_TargetIO_GetInfo(pin); if (!info) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Undefined I/O pin%d", pin); return 0; } duk_push_string(ctx, ", "); idx = duk_push_object(ctx); duk_push_int(ctx, info->physicalPin); duk_put_prop_string(ctx, idx, "physicalPin"); duk_push_string(ctx, info->schematicId); duk_put_prop_string(ctx, idx, "schematicId"); duk_push_string(ctx, info->datasheetId); duk_put_prop_string(ctx, idx, "datasheetId"); duk_push_string(ctx, info->description); duk_put_prop_string(ctx, idx, "description"); /* * Return the object we just created */ return 1; }
/* * Returns the IO functions supported by this pin */ static int NativeFunctionsGetter(duk_context* ctx) { uint8_t bit; uint8_t numFuncs = 0; const AJS_IO_Info* info; uint32_t pin; duk_push_this(ctx); pin = GetPinId(ctx, -1, 0); duk_pop(ctx); info = AJS_TargetIO_GetInfo(pin); if (!info) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Undefined I/O pin%d", pin); return 0; } duk_push_string(ctx, ", "); /* * Test each function bit */ for (bit = 0; bit < 32; ++bit) { if (info->functions & (1 << bit)) { const char* name = AJS_IO_FunctionName(1 << bit); duk_push_string(ctx, name); ++numFuncs; } } duk_join(ctx, numFuncs); return 1; }
/* * Returns the pid id for a pin object. Also checks that the pin supports the requested function. */ static uint32_t GetPinId(duk_context* ctx, int idx, uint32_t function) { uint32_t id; if (!duk_is_object(ctx, idx)) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Requires a pin object"); } /* * Get pin id */ duk_get_prop_string(ctx, idx, "id"); id = duk_require_int(ctx, -1); duk_pop(ctx); /* * Check that the required I/O function is supported */ if (function) { const AJS_IO_Info* info = AJS_TargetIO_GetInfo(id); if (!info) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Undefined I/O pin%d", id); return 0; } if (!(info->functions & function)) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "I/O function %s not supported on pin%d", AJS_IO_FunctionName(function), id); } } return id; }
extern "C" AJ_Status AJS_TargetIO_PinEnableTrigger(void* pinCtx, AJS_IO_PinTriggerMode trigger, int32_t* trigId, uint8_t debounce) { GPIO* gpio = (GPIO*)pinCtx; size_t pin; uint16_t pinId; uint16_t physicalPin = AJS_TargetIO_GetInfo(gpio->pinIdx)->physicalPin; for (pin = 0; pin < ArraySize(pinInfo); ++pin) { if (pinInfo[pin].pinNum == physicalPin) { pinId = pinInfo[pin].pinId; break; } } if (!pinInfo[pin].func) { return AJ_ERR_INVALID; } gpio->trigId = AllocTrigId(pin); if (gpio->trigId == AJS_IO_PIN_NO_TRIGGER) { return AJ_ERR_RESOURCES; } gpio->interrupt = new InterruptIn((PinName)pinId); if (trigger == AJS_IO_PIN_TRIGGER_ON_RISE) { gpio->interrupt->rise(pinInfo[pin].func); } else if (trigger == AJS_IO_PIN_TRIGGER_ON_FALL) { gpio->interrupt->fall(pinInfo[pin].func); } *trigId = gpio->trigId; return AJ_OK; }
AJ_Status AJS_TargetIO_PinOpen(uint16_t pinIndex, AJS_IO_PinConfig config, void** pinCtx) { GPIO* gpio; GPIO_InitTypeDef GPIO_Pin; size_t pin; uint16_t physicalPin = AJS_TargetIO_GetInfo(pinIndex)->physicalPin; for (pin = 0; pin < ArraySize(pinInfo); ++pin) { if (pinInfo[pin].pinNum == physicalPin) { break; } } if (pin >= ArraySize(pinInfo)) { return AJ_ERR_INVALID; } gpio = AJS_Alloc(NULL, sizeof(GPIO)); memset(gpio, 0, sizeof(GPIO)); gpio->trigId = -1; gpio->gpioAF = 0; gpio->GPIOx = pinInfo[pin].GPIOx; gpio->gpioPin = pinInfo[pin].physicalPin; GPIO_Pin.GPIO_Speed = GPIO_Speed_50MHz; if (config & AJS_IO_PIN_OUTPUT) { GPIO_Pin.GPIO_Mode = GPIO_Mode_OUT; GPIO_Pin.GPIO_OType = GPIO_OType_PP; GPIO_Pin.GPIO_Pin = pinInfo[pin].physicalPin; GPIO_Pin.GPIO_PuPd = GPIO_PuPd_UP; } else if (config & AJS_IO_PIN_INPUT) { GPIO_Pin.GPIO_Mode = GPIO_Mode_IN; GPIO_Pin.GPIO_OType = GPIO_OType_PP; GPIO_Pin.GPIO_Pin = pinInfo[pin].physicalPin; GPIO_Pin.GPIO_PuPd = GPIO_PuPd_UP; } else { if (config & AJS_IO_PIN_OPEN_DRAIN) { GPIO_Pin.GPIO_Mode = GPIO_Mode_OUT; GPIO_Pin.GPIO_OType = GPIO_OType_OD; GPIO_Pin.GPIO_Pin = pinInfo[pin].physicalPin; GPIO_Pin.GPIO_PuPd = GPIO_PuPd_UP; } else if (config & AJS_IO_PIN_PULL_UP) { GPIO_Pin.GPIO_Mode = GPIO_Mode_OUT; GPIO_Pin.GPIO_OType = GPIO_OType_PP; GPIO_Pin.GPIO_Pin = pinInfo[pin].physicalPin; GPIO_Pin.GPIO_PuPd = GPIO_PuPd_UP; } else { GPIO_Pin.GPIO_Mode = GPIO_Mode_OUT; GPIO_Pin.GPIO_OType = GPIO_OType_PP; GPIO_Pin.GPIO_Pin = pinInfo[pin].physicalPin; GPIO_Pin.GPIO_PuPd = GPIO_PuPd_DOWN; } } GPIO_Init(gpio->GPIOx, &GPIO_Pin); *pinCtx = gpio; return AJ_OK; }
AJ_Status AJS_TargetIO_PinOpen(uint16_t pinIndex, AJS_IO_PinConfig config, void** pinCtx) { AJ_Status status = AJ_OK; int fd; uint16_t physicalPin = AJS_TargetIO_GetInfo(pinIndex)->physicalPin; size_t pin; GPIO* gpio; const char* dev; /* * Locate GPIO associated with the physical pin */ for (pin = 0; pin < ArraySize(pinInfo); ++pin) { if (pinInfo[pin].physicalPin == physicalPin) { break; } } if (pin >= ArraySize(pinInfo)) { return AJ_ERR_INVALID; } dev = pinInfo[pin].gpioDev; status = ExportIfNeeded(dev, pinInfo[pin].gpioId, gpio_root); if (status != AJ_OK) { return status; } /* * Set the pin direction */ status = SetDeviceProp(dev, gpio_root, "direction", (config == AJS_IO_PIN_OUTPUT) ? "out" : "in"); if (status != AJ_OK) { return status; } /* * Save the open file handle */ fd = OpenDeviceProp(dev, gpio_root, "value", (config == AJS_IO_PIN_OUTPUT) ? O_RDWR : O_RDONLY); if (fd >= 0) { gpio = malloc(sizeof(GPIO)); if (!gpio) { AJ_ErrPrintf(("AJS_TargetIO_PinOpen(): Malloc failed to allocate %d bytes\n", sizeof(GPIO))); return AJ_ERR_RESOURCES; } gpio->fd = fd; gpio->pinId = pin; gpio->trigId = AJS_IO_PIN_NO_TRIGGER; gpio->pwmPeriod = 0; AJS_TargetIO_PinGet(gpio); } else { status = AJ_ERR_DRIVER; } *pinCtx = gpio; return status; }
AJ_Status AJS_TargetIO_UartOpen(uint8_t txPin, uint8_t rxPin, uint32_t baud, void** uartCtx) { UART* uart; uint16_t pinTx, pinRx; uint16_t physicalTxPin = AJS_TargetIO_GetInfo(txPin)->physicalPin; uint16_t physicalRxPin = AJS_TargetIO_GetInfo(rxPin)->physicalPin; for (pinTx = 0; pinTx < ArraySize(uartInfo); ++pinTx) { if (uartInfo[pinTx].pinNum == physicalTxPin) { break; } } // Make sure the pin exists and its a TX pin if (pinTx >= ArraySize(uartInfo) || uartInfo[pinTx].function != AJS_IO_FUNCTION_UART_TX) { return AJ_ERR_INVALID; } for (pinRx = 0; pinRx < ArraySize(uartInfo); ++pinRx) { if (uartInfo[pinRx].pinNum == physicalRxPin) { break; } } // Make sure the pin exists and its an RX pin if (pinRx >= ArraySize(uartInfo) || uartInfo[pinRx].function != AJS_IO_FUNCTION_UART_RX) { return AJ_ERR_INVALID; } // Dont initialize the UART peripheral, just point the object to the current UART class if (uartInfo[pinTx].init == false || uartInfo[pinRx].init == false) { uart->object = pc; *uartCtx = uart; return AJ_OK; } uart = (UART*)AJS_Alloc(NULL, sizeof(UART)); uart->object = new Serial((PinName)uartInfo[pinTx].pinId, (PinName)uartInfo[pinRx].pinId); uart->object->baud(baud); *uartCtx = uart; return AJ_OK; }
/* * Configures a pin as a digital output pin */ static int NativeIoDigitalOut(duk_context* ctx) { AJ_Status status; int idx; void* pinCtx; uint32_t pin = GetPinId(ctx, 0, AJS_IO_FUNCTION_DIGITAL_OUT); /* * Target specific I/O pin initialization */ status = AJS_TargetIO_PinOpen(pin, AJS_IO_PIN_OUTPUT, &pinCtx); if (status != AJ_OK) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Failed to configure digital output pin: %s", AJ_StatusText(status)); } idx = NewIOObject(ctx, pinCtx, AJS_IO_FUNCTION_DIGITAL_OUT, NativePinFinalizer); /* * Functions to set/get the pin level */ AJS_SetPropertyAccessors(ctx, idx, "level", NativeLevelSetter, NativeLevelGetter); /* * Check for and set initial value */ if (duk_is_number(ctx, 1)) { duk_dup(ctx, 1); duk_put_prop_string(ctx, idx, "level"); } /* * Toggle function */ duk_push_c_lightfunc(ctx, NativeTogglePin, 0, 0, 0); duk_put_prop_string(ctx, idx, "toggle"); /* * Only allow if the PWM functions is supported */ if (AJS_TargetIO_GetInfo(pin)->functions & AJS_IO_FUNCTION_PWM) { duk_push_c_lightfunc(ctx, NativePWM, 2, 0, 0); duk_put_prop_string(ctx, idx, "pwm"); } /* * Return the digital output pin object */ return 1; }
AJ_Status AllocPWM(GPIO* pin) { size_t i; size_t idx; uint16_t physicalPin = AJS_TargetIO_GetInfo(pin->pinIdx)->physicalPin; for (idx = 0; idx < ArraySize(pinInfo); ++idx) { if (pinInfo[idx].pinNum == physicalPin) { break; } } AJ_ASSERT(!pin->pwm.dutyCycle); for (i = 0; i < MAX_PWM_PINS; ++i) { if (!pwmPins[i]) { pwmPins[i] = pin; pin->pwm.count = 0; ++pwmCount; //pin->pwm.object = new PwmOut((PinName)pinInfo[idx].pinId); return AJ_OK; } } return AJ_ERR_RESOURCES; }
AJ_Status AJS_TargetIO_AdcOpen(uint16_t pinIndex, void** adcCtx) { ADC* adc; size_t pin; uint16_t physicalPin = AJS_TargetIO_GetInfo(pinIndex)->physicalPin; for (pin = 0; pin < ArraySize(pinInfo); ++pin) { if (pinInfo[pin].pinNum == physicalPin) { break; } } if (pin >= ArraySize(pinInfo)) { return AJ_ERR_INVALID; } adc = (ADC*)AJS_Alloc(NULL, sizeof(ADC)); memset(adc, 0, sizeof(ADC)); adc->adcObj = new AnalogIn((PinName)pinInfo[pin].pinId); *adcCtx = adc; return AJ_OK; }