void Adafruit_DotStar::show(void) { if(!pixels) return; uint8_t *ptr = pixels, i; // -> LED data uint16_t n = numLEDs; // Counter uint16_t b16 = (uint16_t)brightness; // Type-convert for fixed-point math //__disable_irq(); // If 100% focus on SPI clocking required if(dataPin == USE_HW_SPI) { for(i=0; i<4; i++) spi_out(0x00); // 4 byte start-frame marker if(brightness) { // Scale pixel brightness on output do { // For each pixel... spi_out(0xFF); // Pixel start for(i=0; i<3; i++) spi_out((*ptr++ * b16) >> 8); // Scale, write RGB } while(--n); } else { // Full brightness (no scaling) do { // For each pixel... spi_out(0xFF); // Pixel start for(i=0; i<3; i++) spi_out(*ptr++); // Write R,G,B } while(--n); } // Four end-frame bytes are seemingly indistinguishable from a white // pixel, and empirical testing suggests it can be left out...but it's // always a good idea to follow the datasheet, in case future hardware // revisions are more strict (e.g. might mandate use of end-frame // before start-frame marker). i.e. let's not remove this. for(i=0; i<4; i++) spi_out(0xFF); } else { // Soft (bitbang) SPI
void Adafruit_DotStar::show(void) { if(!pixels) return; uint8_t *ptr = pixels, i; // -> LED data uint16_t n = numLEDs; // Counter uint16_t b16 = (uint16_t)brightness; // Type-convert for fixed-point math if(dataPin == USE_HW_SPI) { #ifdef SPI_PIPELINE uint8_t next; for(i=0; i<3; i++) spi_out(0x00); // First 3 start-frame bytes SPDR = 0x00; // 4th is pipelined do { // For each pixel... while(!(SPSR & _BV(SPIF))); // Wait for prior byte out SPDR = 0xFF; // Pixel start for(i=0; i<3; i++) { // For R,G,B... next = brightness ? (*ptr++ * b16) >> 8 : *ptr++; // Read, scale while(!(SPSR & _BV(SPIF))); // Wait for prior byte out SPDR = next; // Write scaled color } } while(--n); while(!(SPSR & _BV(SPIF))); // Wait for last byte out #else for(i=0; i<4; i++) spi_out(0x00); // 4 byte start-frame marker if(brightness) { // Scale pixel brightness on output do { // For each pixel... spi_out(0xFF); // Pixel start for(i=0; i<3; i++) spi_out((*ptr++ * b16) >> 8); // Scale, write RGB } while(--n); } else { // Full brightness (no scaling) do { // For each pixel...
static uint8_t readOp (uint8_t op, uint8_t address) { spi_enable_eth(); spi_out(op | (address & ADDR_MASK)); if (address & 0x80) spi_out(0x00); uint8_t result = spi_in(); spi_disable_eth(); return result; }
static int ap_get_head(struct sc8800_data *sc8800, struct bp_head *packet) { int err = 0, count = 5; char buf[BP_PACKET_SIZE]; retry: spi_out(sc8800, packet, BP_PACKET_SIZE, &err); if(err < 0 && count > 0) { dev_warn(sc8800->dev, "%s spi_out return error, retry count = %d\n", __func__, count); count--; mdelay(10); goto retry; } if(err < 0) return err; //memcpy((char *)(packet), buf, BP_PACKET_SIZE); sc8800_dbg(sc8800->dev, "%s tag = 0x%4x, type = 0x%4x, length = %x\n", __func__, packet->tag, packet->type, packet->length); if ((packet->tag != 0x7e7f) || (packet->type != 0xaa55)) return -1; else return 0; }
static int sc8800_rx(struct sc8800_data *sc8800) { int ret = 0, len, real_len; struct bp_head packet; char *buf = NULL; ap_rdy(sc8800,0); ret = ap_get_head(sc8800, &packet); if(ret < 0){ dev_err(sc8800->dev, "ERR: %s ap_get_head err = %d\n", __func__, ret); goto out; } len = packet.length; if(len > BP_PACKET_DATA_LEN) real_len = (((len -BP_PACKET_DATA_LEN-1)/BP_PACKET_SIZE)+2)*BP_PACKET_SIZE; else real_len = BP_PACKET_SIZE; if(len > RD_BUF_SIZE){ dev_err(sc8800->dev, "ERR: %s len[%d] is large than buffer size[%lu]\n", __func__, real_len, RD_BUF_SIZE); goto out; } buf = kzalloc(real_len, GFP_KERNEL); if(!buf){ dev_err(sc8800->dev,"ERR: %s no memmory for rx_buf\n", __func__); goto out; } memcpy(buf, packet.data, BP_PACKET_DATA_LEN); if(len > BP_PACKET_DATA_LEN) spi_out(sc8800, buf + BP_PACKET_DATA_LEN, real_len-BP_PACKET_SIZE, &ret); if(ret < 0){ dev_err(sc8800->dev, "ERR: %s spi out err = %d\n", __func__, ret); goto out; } spin_lock(&sc8800->lock); if(sc8800->rx_len + len > RD_BUF_SIZE){ dev_warn(sc8800->dev, "WARN: %s read buffer is full\n", __func__); }else { memcpy(sc8800->rx_buf+sc8800->rx_len, buf, len); sc8800->rx_len += len; } spin_unlock(&sc8800->lock); sc8800_dbg(sc8800->dev, "%s rx_len = %d\n", __func__, sc8800->rx_len); ret = sc8800->rx_len; out: ap_rdy(sc8800,1); if(buf) kfree(buf); buf = NULL; return ret; }
void Adafruit_WS2801::show(void) { uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED uint8_t bit; // Write 24 bits per pixel: if(hardwareSPI) { for(i=0; i<nl3; i++) spi_out(pixels[i]); } else { for(i=0; i<nl3; i++ ) { for(bit=0x80; bit; bit >>= 1) { #ifdef __AVR__ if(pixels[i] & bit) *dataport |= datapinmask; else *dataport &= ~datapinmask; *clkport |= clkpinmask; *clkport &= ~clkpinmask; #else if(pixels[i] & bit) digitalWrite(datapin, HIGH); else digitalWrite(datapin, LOW); digitalWrite(clkpin, HIGH); digitalWrite(clkpin, LOW); #endif } } } delay(1); // Data is latched by holding clock pin low for 1 millisecond }
/** * @brief Set SPI divider * @param[in] dev pointer to spi interface structure * @param[in] speed desire spi speed * @return speed set actually */ static uint32_t spiSetSpeed(spi_dev * dev, uint32_t speed) { uint16_t div = (uint16_t)(SPI_INPUT_CLOCK / (2 * speed)) - 1; spi_out(dev, div, DIVIDER); return ( SPI_INPUT_CLOCK / (2*(div+1))); }
/** * @brief Write data to spi interface * @param[in] fd is interface number. * @param[in] buff_id is buffer number. If transfer number is 4, application needs write 4 times (buff_id is from 0 to 3) to buffer. * @param[in] data is data to be written. * @return none */ void spiWrite(int32_t fd, uint8_t buff_id, uint32_t data) { spi_dev *dev; dev = (spi_dev *)((uint32_t)&spi_device[fd]); spi_out(dev, data, (TX0+4*buff_id)); }
void LPD8806::show(void) { uint8_t *ptr = pixels; uint16_t i = numBytes; // This doesn't need to distinguish among individual pixel color // bytes vs. latch data, etc. Everything is laid out in one big // flat buffer and issued the same regardless of purpose. if(hardwareSPI) { while(i--) spi_out(*ptr++); } else { uint8_t p, bit; while(i--) { p = *ptr++; for(bit=0x80; bit; bit >>= 1) { #ifdef __AVR__ if(p & bit) *dataport |= datapinmask; else *dataport &= ~datapinmask; *clkport |= clkpinmask; *clkport &= ~clkpinmask; #else if(p & bit) digitalWrite(datapin, HIGH); else digitalWrite(datapin, LOW); digitalWrite(clkpin, HIGH); digitalWrite(clkpin, LOW); #endif } } } }
static void readBuf(uint16_t len, uint8_t* data) { spi_enable_eth(); spi_out(ENC28J60_READ_BUF_MEM); while (len--) { *data++ = spi_in(); } spi_disable_eth(); }
uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch (msg) { case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: // init spi and ports u8g_MicroDelay(); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ //u8g_10MicroDelay(); GPIO_SET_PIN_VAL(LCD_A0, arg_val); u8g_MicroDelay(); break; case U8G_COM_MSG_CHIP_SELECT: GPIO_SET_PIN_VAL(LCD_CSB, !arg_val); u8g_MicroDelay(); break; case U8G_COM_MSG_RESET: GPIO_SET_PIN_VAL(LCD_RSTB, arg_val); u8g_MicroDelay(); break; case U8G_COM_MSG_WRITE_BYTE: spi_out(arg_val); u8g_MicroDelay(); break; case U8G_COM_MSG_WRITE_SEQ: case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while (arg_val > 0) { spi_out(*ptr++); arg_val--; } } break; } return 1; }
// Enable SPI hardware and set up protocol details: void LPD8806::startSPI(void) { #ifdef __AVR_ATtiny85__ PORTB &= ~(_BV(PORTB1) | _BV(PORTB2)); // Outputs DDRB |= _BV(PORTB1) | _BV(PORTB2); // DO (NOT MOSI) + SCK #else SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); // SPI bus is run at 2MHz. Although the LPD8806 should, in theory, // work up to 20MHz, the unshielded wiring from the Arduino is more // susceptible to interference. Experiment and see what you get. #if defined(__AVR__) || defined(CORE_TEENSY) SPI.setClockDivider(SPI_CLOCK_DIV8); #else SPI.setClockDivider((F_CPU + 1000000L) / 2000000L); #endif #endif // Issue initial latch/reset to strip: for(uint16_t i=((numLEDs+31)/32); i>0; i--) spi_out(0); }
static void writeOp (uint8_t op, uint8_t address, uint8_t data) { spi_enable_eth(); spi_out(op | (address & ADDR_MASK)); spi_out(data); spi_disable_eth(); }
uint8_t u8g_com_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { switch(msg) { case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: if ( arg_val <= U8G_SPI_CLK_CYCLE_50NS ) { spi_init(SPI_BAUDRATEPRESCALER_2); } else if ( arg_val <= U8G_SPI_CLK_CYCLE_300NS ) { spi_init(SPI_BAUDRATEPRESCALER_4); } else if ( arg_val <= U8G_SPI_CLK_CYCLE_400NS ) { spi_init(SPI_BAUDRATEPRESCALER_4); } else { spi_init(SPI_BAUDRATEPRESCALER_8); } u8g_MicroDelay(); break; case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ u8g_10MicroDelay(); set_gpio_level(LCD_CD_PIN, arg_val); u8g_10MicroDelay(); break; case U8G_COM_MSG_CHIP_SELECT: if ( arg_val == 0 ) { /* disable */ uint8_t i; /* this delay is required to avoid that the display is switched off too early --> DOGS102 with LPC1114 */ for( i = 0; i < 5; i++ )u8g_10MicroDelay(); set_gpio_level(LCD_CS_PIN, 1); } else { /* enable */ set_gpio_level(LCD_CS_PIN, 0); } u8g_MicroDelay(); break; case U8G_COM_MSG_RESET: set_gpio_level(LCD_RST_PIN, arg_val); u8g_10MicroDelay(); break; case U8G_COM_MSG_WRITE_BYTE: spi_out(arg_val); u8g_MicroDelay(); break; case U8G_COM_MSG_WRITE_SEQ: case U8G_COM_MSG_WRITE_SEQ_P: { register uint8_t *ptr = arg_ptr; while( arg_val > 0 ) { spi_out(*ptr++); arg_val--; } } break; } return 1; }
/** * @brief Support some spi driver commands for application. * @param[in] fd is interface number. * @param[in] cmd is command. * @param[in] arg0 is the first argument of command. * @param[in] arg1 is the second argument of command. * @return command status. * @retval 0 Success otherwise fail. Fail value could be * - \ref SPI_ERR_NODEV * - \ref SPI_ERR_IO * - \ref SPI_ERR_ARG */ int32_t spiIoctl(int32_t fd, uint32_t cmd, uint32_t arg0, uint32_t arg1) { spi_dev *dev; if(fd != 0 && fd != 1) return(SPI_ERR_NODEV); dev = (spi_dev *)((uint32_t)&spi_device[fd]); if(dev->openflag == 0) return(SPI_ERR_IO); switch(cmd) { case SPI_IOC_TRIGGER: dev->intflag = 0; spi_out(dev, spi_in(dev, CNTRL) | 0x1 ,CNTRL); break; case SPI_IOC_SET_INTERRUPT: if(arg0 == SPI_ENABLE_INTERRUPT) spi_out(dev, spi_in(dev, CNTRL) | (0x1<<17) ,CNTRL); else spi_out(dev, spi_in(dev, CNTRL) & ~(0x1<<17) ,CNTRL); break; case SPI_IOC_SET_SPEED: spiSetSpeed(dev, (uint32_t)arg0); break; case SPI_IOC_SET_DUAL_QUAD_MODE: if(arg0 == SPI_DISABLE_DUAL_QUAD) { spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) ,CNTRL); break; } if(arg0 == SPI_DUAL_MODE) spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) | (0x1 << 22) ,CNTRL); else spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 21)) | (0x1 << 21) ,CNTRL); break; case SPI_IOC_SET_DUAL_QUAD_DIR: if(arg0 == SPI_DUAL_QUAD_INPUT) spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 20) ,CNTRL); else spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 20) ,CNTRL); break; case SPI_IOC_SET_LSB_MSB: if(arg0 == SPI_MSB) spi_out(dev, spi_in(dev, CNTRL) & ~(0x1 << 10) ,CNTRL); else spi_out(dev, spi_in(dev, CNTRL) | (0x1 << 10) ,CNTRL); break; case SPI_IOC_SET_TX_NUM: if(arg0 < 4) spi_out(dev, (spi_in(dev, CNTRL) & ~(0x3 << 8)) | (arg0 << 8) ,CNTRL); else return SPI_ERR_ARG; break; case SPI_IOC_SET_TX_BITLEN: if(arg0 < 32) spi_out(dev, (spi_in(dev, CNTRL) & ~(0x1f << 3)) | (arg0 << 3) ,CNTRL); else return SPI_ERR_ARG; break; case SPI_IOC_SET_MODE: if(arg0 > SPI_MODE_3) return SPI_ERR_ARG; if(arg0 == SPI_MODE_0) spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | (1<<2) ,CNTRL); else if(arg0 == SPI_MODE_1) spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | (1<<1) ,CNTRL); else if(arg0 == SPI_MODE_2) spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | ((1UL<<31) | (1<<2)) ,CNTRL); else spi_out(dev, (spi_in(dev, CNTRL) & ~((0x3<<1) | (1UL<<31))) | ((1UL<<31) | (1<<1)) ,CNTRL); break; case SPI_IOC_ENABLE_SS: if(arg0 == SPI_SS_SS0) spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x1 ,SSR); else if(arg0 == SPI_SS_SS1) spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x2 ,SSR); else if(arg0 == SPI_SS_BOTH) spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) | 0x3 ,SSR); else return SPI_ERR_ARG; break; case SPI_IOC_DISABLE_SS: if(arg0 == SPI_SS_SS0) spi_out(dev, (spi_in(dev, SSR) & ~(0x1)) ,SSR); else if(arg0 == SPI_SS_SS1) spi_out(dev, (spi_in(dev, SSR) & ~(0x2)) ,SSR); else if(arg0 == SPI_SS_BOTH) spi_out(dev, (spi_in(dev, SSR) & ~(0x3)) ,SSR); else return SPI_ERR_ARG; break; case SPI_IOC_SET_AUTOSS: if(arg0 == SPI_DISABLE_AUTOSS) spi_out(dev, spi_in(dev, SSR) & ~(0x1 << 3) ,SSR); else spi_out(dev, spi_in(dev, SSR) | (0x1 << 3) ,SSR); break; case SPI_IOC_SET_SS_ACTIVE_LEVEL: if(arg0 == SPI_SS_ACTIVE_LOW) spi_out(dev, spi_in(dev, SSR) & ~(0x1 << 2) ,SSR); else spi_out(dev, spi_in(dev, SSR) | (0x1 << 2) ,SSR); default: break; } return 0; }