void Nhdc12832::refresh(void){ Spi spi(spi_port); uint8_t buffer[MEM_ROWS]; unsigned int i,j; unsigned char page = 0xB0; //Page Address + 0xB0 //cmd_out(0xAE); //Display OFF cmd_out(0x40); //Display start address + 0x40 for(i=0;i<MEM_COLUMNS;i++){ //32pixel display / 8 pixels per page = 4 pages assert_cmd(); buffer[0] = page; //send page address buffer[1] = 0x10; //column address upper 4 bits + 0x10 buffer[2] = 0x00; //column address lower 4 bits + 0x00 assert_cs(); spi.write(buffer, 3); deassert_cs(); for(j=0;j<MEM_ROWS;j++){ //128 rows wide buffer[j] = nhd_mem[j][i]; } assert_data(); assert_cs(); spi.write(buffer, MEM_ROWS); deassert_cs(); page++; //after 128 columns, go to next page } cmd_out(0xAF); //Display ON }
int lcd_spi_complete_event(void * context, const void * data){ int j; int i; //deassert CS each time a SPI event completes deassert_cs(); i = lcd_page - 0xB0; if( i == LCD_COLS ){ lcd_hold = 0x00; update_count(); //interrupt again on next timer match return 0; //all done } switch(lcd_write_state){ case LCD_WRITE_PAGE: command_mode(); lcd_buffer[0] = lcd_page; lcd_buffer[1] = 0x10; lcd_buffer[2] = 0x00; op.nbyte = 3; assert_cs(); lcd_write_state = LCD_WRITE_DATA; hwpl_spi_write(context, &op); return 1; case LCD_WRITE_DATA: data_mode(); assert_cs(); for(j=0;j<LCD_ROWS;j++){ //128 rows high lcd_buffer[j] = mem[LCD_ROWS - j - 1][i]; } op.nbyte = LCD_ROWS; lcd_page++; lcd_write_state = LCD_WRITE_PAGE; hwpl_spi_write(context, &op); break; } return 1; }
void Nhdc12832::cmd_out(unsigned char c){ Spi spi(spi_port); assert_cmd(); assert_cs(); spi.swap(c); deassert_cs(); }
void Nhdc12832::cmd_out(const void * cmd, int nbyte){ Spi spi(spi_port); int i; const unsigned char * p = (const unsigned char*)cmd; assert_cmd(); for(i=0; i < nbyte; i++){ assert_cs(); spi.swap(*p++); deassert_cs(); } }
void Nhdc12832::data_out(const void * data, int nbyte){ Spi spi(spi_port); int i; const char * p = (const char*)data; assert_data(); for(i=0; i < nbyte; i++){ assert_cs(); spi.swap(*p++); deassert_cs(); } }
static int jlink_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { uint32_t length; uint8_t *buffer; length = writecnt + readcnt; if (length > JTAG_MAX_TRANSFER_SIZE) return SPI_INVALID_LENGTH; buffer = malloc(length); if (!buffer) { msg_perr("Memory allocation failed.\n"); return SPI_GENERIC_ERROR; } /* Reverse all bytes because the device transfers data LSB first. */ reverse_bytes(buffer, writearr, writecnt); memset(buffer + writecnt, 0x00, readcnt); if (!assert_cs()) { free(buffer); return SPI_PROGRAMMER_ERROR; } int ret; ret = jaylink_jtag_io(jaylink_devh, buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2); if (ret != JAYLINK_OK) { msg_perr("jaylink_jag_io() failed: %s.\n", jaylink_strerror(ret)); free(buffer); return SPI_PROGRAMMER_ERROR; } if (!deassert_cs()) { free(buffer); return SPI_PROGRAMMER_ERROR; } /* Reverse all bytes because the device transfers data LSB first. */ reverse_bytes(readarr, buffer + writecnt, readcnt); free(buffer); return 0; }
//***************************************************************************** // //! The IntSpiGPIOHandler interrupt handler //! //! \param none //! //! \return none //! //! \brief GPIO A interrupt handler. When the external SSI WLAN device is //! ready to interact with Host CPU it generates an interrupt signal. //! After that Host CPU has registrated this interrupt request //! it set the corresponding /CS in active state. // //***************************************************************************** void CC3000InterruptHandler(void) { if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { /* This means IRQ line was low call a callback of HCI Layer to inform on event */ sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED; } else if (sSpiInformation.ulSpiState == eSPI_STATE_IDLE) { sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; /* IRQ line goes down - start reception */ assert_cs(); SpiReadHeader(); sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; SSIContReadOperation(); } else if (sSpiInformation.ulSpiState == eSPI_STATE_WRITE_IRQ) { SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; negate_cs(); } }
//***************************************************************************** // //! This function enter point for write flow //! //! \param buffer //! //! \return none //! //! \brief ... // //***************************************************************************** long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength) { // // workaround for first transaction // assert_cs(); delayMicroseconds(50); // SPI writes first 4 bytes of data SpiWriteDataSynchronous(ucBuf, 4); delayMicroseconds(50); SpiWriteDataSynchronous(ucBuf + 4, usLength - 4); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; negate_cs(); return (0); }
//***************************************************************************** // //! This function enter point for write flow //! //! \param buffer //! //! \return none //! //! \brief ... // //***************************************************************************** long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength) { unsigned char ucPad = 0; // // Figure out the total length of the packet in order to figure out if there is padding or not // if (!(usLength & 0x0001)) ucPad++; pUserBuffer[0] = SPI_WRITE; pUserBuffer[1] = HI(usLength + ucPad); pUserBuffer[2] = LO(usLength + ucPad); pUserBuffer[3] = 0; pUserBuffer[4] = 0; usLength += (SPI_HEADER_SIZE + ucPad); // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) // for the purpose of overrun detection. If the magic number is overwritten - buffer overrun // occurred - and we will be stuck here forever! if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { while (1); } if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED); } if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) { // // This is time for first TX/RX transactions over SPI: the IRQ is down - so need to send read buffer size command // SpiFirstWrite(pUserBuffer, usLength); } else { // // We need to prevent here race that can occur in case two back to back packets are sent to the // device, so the state will move to IDLE and once again to not IDLE due to IRQ // tSLInformation.WlanInterruptDisable(); while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE); sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ; sSpiInformation.pTxPacket = pUserBuffer; sSpiInformation.usTxPacketLength = usLength; // // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation // assert_cs(); // // Re-enable IRQ - if it was not disabled - this is not a problem... // tSLInformation.WlanInterruptEnable(); // // check for a missing interrupt between the CS assertion and enabling back the interrupts // if (tSLInformation.ReadWlanInterruptPin() == 0) { SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); sSpiInformation.ulSpiState = eSPI_STATE_IDLE; negate_cs(); } } // // Due to the fact that we are currently implementing a blocking situation // here we will wait till end of transaction // while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState); return (0); }
int lcd_ioctl(const device_cfg_t * cfg, int request, void * ctl){ mlcd_attr_t * attr = (mlcd_attr_t*)ctl; tmr_action_t action; pio_attr_t pattr; device_periph_t p; switch(request){ case I_MLCD_GETATTR: attr->freq = LCD_FREQ; //LCD updates 30 times per second attr->h = LCD_HEIGHT; attr->w = LCD_WIDTH; attr->size = LCD_ROWS * LCD_COLS; attr->mem = mem; attr->hold = lcd_hold; attr->rows = LCD_ROWS; attr->cols = LCD_COLS/4; attr->orientation = (ORIENT_BOTTOM)|(ORIENT_LEFT); break; case I_MLCD_CLEAR: memset(mem, 0, LCD_ROWS * LCD_COLS); lcd_hold = 0x80; break; case I_MLCD_HOLD: if( LCD_HOLD_COUNT() < 127 ){ lcd_hold++; } break; case I_MLCD_RELEASE: if( LCD_HOLD_COUNT() > 0 ){ lcd_hold--; LCD_TOUCH(); } break; case I_MLCD_INIT: //initialize the IO -- chip select first pattr.mask = LCD_SPI_CS_PINMASK; pattr.mode = PIO_MODE_OUTPUT; p.port = LCD_SPI_CS_PORT; hwpl_pio_open((device_cfg_t*)&p); hwpl_pio_setattr(LCD_SPI_CS_PORT, &pattr); hwpl_pio_setmask(LCD_SPI_CS_PORT, (void*)LCD_SPI_CS_PINMASK); //Now A0 pattr.mask = LCD_SPI_A0_PINMASK; if( p.port != LCD_SPI_A0_PORT ){ p.port = LCD_SPI_A0_PORT; hwpl_pio_open((device_cfg_t*)&p); } hwpl_pio_setattr(LCD_SPI_A0_PORT, &pattr); hwpl_pio_setmask(LCD_SPI_A0_PORT, (void*)LCD_SPI_A0_PINMASK); //configure the timer to update the LCD action.channel = LCD_USECOND_OC; action.event = TMR_ACTION_EVENT_INTERRUPT; action.callback = lcd_usecond_match_event; action.context = (void*)cfg; hwpl_tmr_setaction(LCD_USECOND_TMR, &action); const char start[] = {0xA0, 0xAE, 0xC0, 0xA2, 0x2F, 0x21, 0x81, 0x2F}; int i; const char * p = (const char*)start; command_mode(); hwpl_pio_clrmask(LCD_SPI_A0_PORT, (void*)LCD_SPI_A0_PINMASK); //enter command mode for(i=0; i < 8; i++){ assert_cs(); hwpl_spi_swap(LCD_SPI_PORT, (void*)(uint32_t)(*p++)); deassert_cs(); } //start the timer update to refresh the screen update_count(); break; case I_MLCD_ON: command_mode(); assert_cs(); hwpl_spi_swap(LCD_SPI_PORT, (void*)0xAF); deassert_cs(); break; case I_MLCD_OFF: command_mode(); assert_cs(); hwpl_spi_swap(LCD_SPI_PORT, (void*)0xAE); deassert_cs(); break; default: errno = EINVAL; return -1; } return 0; }