/* * \brief Write to command channel of codec 0. * * This routine will not check the DREQ line. * * \param cmd Points to the buffer. On entry it contains the data to * send. On exit it will contain the data received from * the chip. * \param len Number of bytes to send and receive. */ static int VsCodec0RecvData(void *buf, size_t len) { int rc; uint8_t *bp = (uint8_t *) buf; const uint8_t cmd[4] = { VS_OPCODE_READ, VS_HDAT0_REG, 0xFF, 0xFF }; uint8_t rsp[4]; VsCodecWaitReady(&devSpiVsCodec0, VSCODEC_CMD_TIMEOUT); //(*nodeSpiVsCodec0.node_bus->bus_set_rate) (&nodeSpiVsCodec0, 20000000); /* Allocate the SPI bus. */ rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT); if (rc == 0) { len >>= 1; while (len--) { /* Activate chip selects. */ #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT) GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT); #endif GpioPinSetLow(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT); /* XCS=PA31 */ /* Send command bytes and receive response. */ rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, rsp, 4); /* Deactivate chip selects. */ GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT); #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT) GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT); #endif *bp++ = rsp[2]; *bp++ = rsp[3]; } /* Release the SPI bus. */ (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0); }
/*! * \brief Set pin level. * * Trying to set undefined pins is silently ignored. * * \param bank GPIO bank/port number. * \param bit Bit number of the specified bank/port. * \param value Level, 0 for low or any other value for high. */ void GpioPinSet(int bank, int bit, int value) { if (value) { GpioPinSetHigh(bank, bit); } else { GpioPinSetLow(bank, bit); } }
/* * Init Port D */ void init_dio(void) { /* Configure input pins, enable pull up. */ #ifdef INBANK #ifdef INPIN1 GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP); #endif #ifdef INPIN2 GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP); #endif #ifdef INPIN3 GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP); #endif #ifdef INPIN4 GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP); #endif #endif /* INBANK */ /* Configure output pins, set to low. */ #ifdef OUTBANK #ifdef OUTPIN1 GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN1); #endif #ifdef OUTPIN2 GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN2); #endif #ifdef OUTPIN3 GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN3); #endif #ifdef OUTPIN4 GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN4); #endif #endif /* OUTBANK */ }
/* * \brief Write to command channel of codec 0. * * This routine will not check the DREQ line. * * \param cmd Points to the buffer. On entry it contains the data to * send. On exit it will contain the data received from * the chip. * \param len Number of bytes to send and receive. */ static int VsCodec0SendCmd(void *cmd, size_t len) { int rc; /* Allocate the SPI bus. */ rc = (*nodeSpiVsCodec0.node_bus->bus_alloc) (&nodeSpiVsCodec0, VSCODEC0_SPIBUS_WAIT); if (rc == 0) { /* Activate chip selects. */ #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT) GpioPinSetLow(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT); #endif GpioPinSetLow(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT); /* Send command bytes and receive response. */ rc = (*nodeSpiVsCodec0.node_bus->bus_transfer) (&nodeSpiVsCodec0, cmd, cmd, len); /* Dectivate chip selects. */ GpioPinSetHigh(VSCODEC0_XCS_PORT, VSCODEC0_XCS_BIT); #if defined(VSCODEC0_VSCS_PORT) && defined(VSCODEC0_VSCS_BIT) GpioPinSetHigh(VSCODEC0_VSCS_PORT, VSCODEC0_VSCS_BIT); #endif /* Release the SPI bus. */ (*nodeSpiVsCodec0.node_bus->bus_release) (&nodeSpiVsCodec0); } return rc; }
/*! \brief Select a device on the SPI bus. * * Locks and activates the bus for the specified node. * * \param node Specifies the SPI bus node. * \param tmo Timeout in milliseconds. To disable timeout, set this * parameter to NUT_WAIT_INFINITE. * * \return 0 on success. In case of an error, -1 is returned and the bus * is not locked. */ int GpioSpiBus0Select(NUTSPINODE * node, uint32_t tmo) { int rc; /* Sanity check. */ NUTASSERT(node != NULL); NUTASSERT(node->node_stat != NULL); /* Allocate the bus. */ rc = NutEventWait(&node->node_bus->bus_mutex, tmo); if (rc) { errno = EIO; } else { /* Do the update, if the mode update bit is set. */ if (node->node_mode & SPI_MODE_UPDATE) { GpioSpiSetup(node); } /* Set clock output using the correct idle mode level. */ #if defined(SBBI0_SCK_BIT) GpioPinSetLow(SBBI0_SCK_PORT, (node->node_mode & SPI_MODE_CPOL) != 0); GpioPinConfigSet(SBBI0_SCK_PORT, SBBI0_SCK_BIT, GPIO_CFG_OUTPUT); #endif /* Enable MOSI output and MISO input. */ #if defined(SBBI0_MOSI_BIT) GpioPinConfigSet(SBBI0_MOSI_PORT, SBBI0_MOSI_BIT, GPIO_CFG_OUTPUT); #endif #if defined(SBBI0_MISO_BIT) GpioPinConfigSet(SBBI0_MISO_PORT, SBBI0_MISO_BIT, 0); #endif /* Activate the node's chip select. */ if (GpioSpi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) != 0) == NULL) { /* Release the bus in case of an error. */ NutEventPost(&node->node_bus->bus_mutex); rc = -1; } } return rc; }
/* Idle clock is high and data is captured on the rising edge. */ static void SpiMode3Transfer(GSPIREG *gspi, CONST uint8_t *txbuf, uint8_t *rxbuf, int xlen) { #if defined(SBBI0_SCK_BIT) uint_fast8_t mask; while (xlen--) { for (mask = 0x80; mask; mask >>= 1) { NutMicroDelay(gspi->gspi_dly_rate); GpioPinSetLow(SBBI0_SCK_PORT, SBBI0_SCK_BIT); #if defined(SBBI0_MOSI_BIT) if (txbuf) { GpioPinSet(SBBI0_MOSI_PORT, SBBI0_MOSI_BIT, (*txbuf & mask) != 0); } #endif /* SBBI0_MOSI_BIT */ NutMicroDelay(gspi->gspi_dly_rate); GpioPinSetHigh(SBBI0_SCK_PORT, SBBI0_SCK_BIT); #if defined(SBBI0_MISO_BIT) if (rxbuf) { if (GpioPinGet(SBBI0_MISO_PORT, SBBI0_MISO_BIT)) { *rxbuf |= mask; } else { *rxbuf &= ~mask; } } #endif /* SBBI0_MISO_BIT */ } if (txbuf) { txbuf++; } if (rxbuf) { rxbuf++; } } #endif /* SBBI0_SCK_BIT */ }
/* * Process client requests. */ void ProcessRequests(FILE * stream) { char buff[128]; char *cp; int stat = -1; fputs("200 Welcome to portdio. Type help to get help.\r\n", stream); for (;;) { fflush(stream); /* * Read a line from the client. Ignore * blank lines. */ if (fgets(buff, sizeof(buff), stream) == 0) break; if ((cp = strchr(buff, '\r')) != 0) *cp = 0; if ((cp = strchr(buff, '\n')) != 0) *cp = 0; if (buff[0] == 0) continue; /* * Memory info. */ if (strncmp(buff, "memory", strlen(buff)) == 0) { fprintf(stream, "210 %u bytes RAM free\r\n", (unsigned int)NutHeapAvailable()); continue; } #ifdef OUTBANK /* * Reset output bit. */ if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) { int ok = 1; switch (buff[strlen(buff) - 1]) { #ifdef OUTPIN1 case '1': GpioPinSetLow(OUTBANK, OUTPIN1); break; #endif #ifdef OUTPIN2 case '2': GpioPinSetLow(OUTBANK, OUTPIN2); break; #endif #ifdef OUTPIN3 case '3': GpioPinSetLow(OUTBANK, OUTPIN3); break; #endif #ifdef OUTPIN4 case '4': GpioPinSetLow(OUTBANK, OUTPIN4); break; #endif default: ok = 0; break; } if (ok) { fputs("210 OK\r\n", stream); } else fputs("410 Bad pin\r\n", stream); continue; } /* * Set output bit. */ if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) { int ok = 1; switch (buff[strlen(buff) - 1]) { #ifdef OUTPIN1 case '1': GpioPinSetHigh(OUTBANK, OUTPIN1); break; #endif #ifdef OUTPIN2 case '2': GpioPinSetHigh(OUTBANK, OUTPIN2); break; #endif #ifdef OUTPIN3 case '3': GpioPinSetHigh(OUTBANK, OUTPIN3); break; #endif #ifdef OUTPIN4 case '4': GpioPinSetHigh(OUTBANK, OUTPIN4); break; #endif default: ok = 0; break; } if (ok) { fputs("210 OK\r\n", stream); } else fputs("410 Bad pin\r\n", stream); continue; } #endif /* OUTBANK */ #ifdef INBANK /* * Port status. */ if (strncmp(buff, "query", strlen(buff)) == 0) { stat = PortStatus(); fprintf(stream, "210 %02X\r\n", stat); continue; } /* * wait for status change. */ if (strncmp(buff, "wait", strlen(buff)) == 0) { while (stat == PortStatus()) NutThreadYield(); stat = PortStatus(); fprintf(stream, "210 %02X\r\n", stat); continue; } #endif /* INBANK */ /* * Help. */ fputs("400 List of commands follows\r\n", stream); fputs("memory\tQueries number of RAM bytes free\r\n", stream); #if OUTBANK fputs("reset#\tSet output bit 1..4 low\r\n", stream); fputs("set#\tSet output bit 1..4 high\r\n", stream); #endif #if INBANK fputs("query\tQuery digital i/o status\r\n", stream); fputs("wait\tWaits for digital i/o change\r\n", stream); #endif fputs(".\r\n", stream); } }