⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alt_touchscreen.c

📁 基于NIOSII软核的触摸屏驱动软体.采用的是AD7843触摸屏数字转换器
💻 C
📖 第 1 页 / 共 3 页
字号:
  *y = assemble_sample ((sm->rxdata_values)[3], (sm->rxdata_values)[4]);}staticvoid pen_adc_data_init (alt_touchscreen_pen_adc_data* dat){  dat->x = 0;  dat->y = 0;}static void pen_adc_data_update (alt_touchscreen_pen_adc_data* dat, int x, int y){  dat->x = x;  dat->y = y;}////////////////// The SPI command-values.////    The AD7843 has these command-bits:////     #  Name   Meaning                         X-samp      Y-samp //   +-+------+------------------------------+----------+-----------+//   |7| Start| Every cmd starts with 1      |    1     |     1     |//   |6| A2   | 0 (x) or 1 (y) sample        |    0     |     1     |//   |5| A1   | Use bonus-inputs (not screen)|    0     |     0     |//   |4| A0   | For us:  Just ~A1            |    1     |     1     |//   |3| SER  | Singe-Ended (1), or diff (0) |    0     |     0     |//   |2| Mode | 0=12-bit 1=8-bit resolution  |    0     |     0     |//   |1| PD1  | Chip always powered-up       |    1     |     1     |//   |0| PD0  | Disable "penIRQ" feature     |    0     |     0     |//   +-+------+------------------------------+----------+-----------+//   //     We want to use the chip in 12-bit mode and we don't want it to//     power-down between samples (we want to leave the resistive//     screen "driven" between samples to avoid settling-time issues).////     Sampling the screen in differential-mode gives true-relative//     data that's probably more noise-immune.  Sounds good.////     The Pen IRQ issue//        The "Pen IRQ" issue is a different can of worms.  An //        interrupt when the pen arrives *seems* like both a nice feature//        and a good idea.  It's neither.  Since this entire system is//        now an interrupt-driven sampling system;  and since you can//        register a civilized application-context callback for//        responding to pen up/down events, a hardware //        interrupt on pen-down is actually now actively-useless. Dealing//        with it would make this software vastly more complicated, and//        for absolutely no benefit.////        HOWEVER....////        We "hijack" the so-called "Pen IRQ" feature as just a polled//        pen-detection feature.  We have to.  There's no other//        reliable way to tell if the pen is down.  Looking at sensor//        data and guessing is just no way to run a//        railroad--especially not when there's a perfectly-good//        digital bit sitting right there that tells you reliably//        whether the pen is present.  So we leave the so-called "Pen//        IRQ" feature enabled--and then don't take interrupts from it.////     Of course: After every "real" command we have to send 8 bits of//     pure-zero to reclaim the four "leftover" bits of our 12-bit sample//////////////////////////////////////////////////////////////////#define ALT_TOUCHSCREEN_X_SAMPLE_CMD  0x92#define ALT_TOUCHSCREEN_Y_SAMPLE_CMD  0xD2#define ALT_TOUCHSCREEN_ZERO_FILL_CMD 0x00////////////////////////////////////////////////////////////////// hardware_retrieve_rxdata ////   Get pending data from the rxdata register in the SPI peripheral.//   You have to have some reason to believe that there IS pending//   data.  If not, this routine will return garbage.  ////   One way to be sure there's pending data: Only call this routine//   from an interrupt-handler that's triggered by the RRDY interrupt.//////////////////////////////////////////////////////////////////staticalt_u8 hardware_retrieve_rxdata (alt_touchscreen_hardware* hw){  return  (alt_u8) IORD_ALTERA_AVALON_SPI_RXDATA (hw->spi_controller_base);}//////////////////////////////////////////////////////////////////  hardware_stop//// Disables interrupts from the peripheral and un-registers the ISR// handler. //////////////////////////////////////////////////////////////////staticvoid hardware_stop (alt_touchscreen_hardware* hw){  IOWR_ALTERA_AVALON_SPI_CONTROL  (hw->spi_controller_base,   0);  // Un-register our ISR.  alt_irq_register (hw->spi_controller_irq_number, NULL, NULL);}staticint hardware_pen_detect (alt_touchscreen_hardware* hw){  // Pen-signal is active-low from AD7843 chip  return  (IORD_ALTERA_AVALON_PIO_DATA(hw->pen_detect_pio_base) == 0); }staticvoid hardware_send_spi_command (alt_touchscreen_hardware* hw,				alt_u8 command,				int link_with_next_command){  // Assert continuous-select BEFORE we do the command.  if (link_with_next_command)    IOWR_ALTERA_AVALON_SPI_CONTROL (hw->spi_controller_base,				    ALTERA_AVALON_SPI_CONTROL_IRRDY_MSK |				    ALTERA_AVALON_SPI_CONTROL_SSO_MSK   );      IOWR_ALTERA_AVALON_SPI_TXDATA (hw->spi_controller_base, command);  // De-assert continuous-select AFTER we do the command.  if (!link_with_next_command)    IOWR_ALTERA_AVALON_SPI_CONTROL (hw->spi_controller_base,				    ALTERA_AVALON_SPI_CONTROL_IRRDY_MSK );}staticvoid sample_machine_update_from_rxdata (alt_touchscreen_sample_machine* sm, 					alt_u8 rx_data){  (sm->rxdata_values) [(sm->sample_phase)++] = rx_data;}staticint sample_machine_done (alt_touchscreen_sample_machine* sm){  return sm->sample_phase >= NUM_SAMPLE_MACHINE_PHASES;}staticint sample_machine_ready (alt_touchscreen_sample_machine* sm){  return sm->sample_phase == 0;}staticalt_u8 sample_machine_next_command (alt_touchscreen_sample_machine* sm){  return (sm->scheduled_commands) [sm->sample_phase];}staticint sample_machine_link_next_command (alt_touchscreen_sample_machine* sm){  return (sm->link_with_next_command) [sm->sample_phase];}staticvoid sample_machine_reset (alt_touchscreen_sample_machine* sm){  sm->sample_phase = 0;}staticvoid sample_machine_init (alt_touchscreen_sample_machine* sm){  int i;  sample_machine_reset (sm);  for (i = 0; i < NUM_SAMPLE_MACHINE_PHASES; i++)    (sm->rxdata_values) [i] = 0;  (sm->scheduled_commands)     [0]  = ALT_TOUCHSCREEN_X_SAMPLE_CMD;  (sm->scheduled_commands)     [1]  = ALT_TOUCHSCREEN_ZERO_FILL_CMD;  (sm->scheduled_commands)     [2]  = ALT_TOUCHSCREEN_Y_SAMPLE_CMD;  (sm->scheduled_commands)     [3]  = ALT_TOUCHSCREEN_ZERO_FILL_CMD;  (sm->scheduled_commands)     [4]  = ALT_TOUCHSCREEN_ZERO_FILL_CMD;  (sm->link_with_next_command) [0]  = 1;  (sm->link_with_next_command) [1]  = 1;  (sm->link_with_next_command) [2]  = 1;  (sm->link_with_next_command) [3]  = 1;  (sm->link_with_next_command) [4]  = 0;}  staticvoid spi_isr_context_init (alt_touchscreen_spi_isr_context*  context,			   alt_touchscreen_hardware*         hw,			   alt_touchscreen_sample_machine*   machine,			   alt_touchscreen_pen_adc_data*     adc_data,			   alt_touchscreen_pen_state*        pen_state,			   alt_touchscreen_event_flag_group* event_flags){  context->hw             = hw;  context->sample_machine = machine;  context->adc_data       = adc_data;  context->pen_state      = pen_state;  context->event_flags    = event_flags;}staticvoid alarm_context_init (alt_touchscreen_alarm_context*   context,			 int                               samples_per_second,			 alt_touchscreen_hardware*         hw,			 alt_touchscreen_sample_machine*   machine,			 alt_touchscreen_pen_state*        pen_state,			 alt_touchscreen_event_flag_group* event_flags){    // Compute this only once here, so we don't do a divide in the    // timer ISR. context->nticks        =    alt_ticks_per_second() / samples_per_second;  context->hw             = hw;  context->sample_machine = machine;  context->pen_state      = pen_state;  context->event_flags    = event_flags;}//////////////////////////////////////////////////////////////////// SPI ISR callback////  This is the heart of the touchscreen sampling system.////  This routine deals with incoming data arriving on the touchscreen//  SPI port--and chooses which command to send next.////  This is the "mastermind" of the whole screen-sampling//  process...and yet, it is event-driven.   This implies some sort //  of sequencing state-machine of a perfectly-conventional sort.////  The ISR is actually two nested state-machines.////  The "outer" state-machine (implemented right here in this//  function) keeps track of which "sample phase" we're in.  //  If we don't have a complete sample, then there isn't much to do.////  When we've finally got a complete new sample, we call (as a//  subroutine) the "inner" state-machine, which knows, basically,//  what's the next thing to do with the sample.// ////////////////////////////////////////////////////////////////staticvoid spi_isr (void* context, alt_u32 interrupt_number){  alt_touchscreen_spi_isr_context* spi_isr_context =    (alt_touchscreen_spi_isr_context*) context;  int pen_detect;  alt_touchscreen_hardware*         hardware  = spi_isr_context->hw;  alt_touchscreen_sample_machine*   machine  = spi_isr_context->sample_machine;   alt_touchscreen_pen_adc_data*     pen_data  = spi_isr_context->adc_data;  alt_touchscreen_pen_state*        pen_state = spi_isr_context->pen_state;  alt_touchscreen_event_flag_group* flags     = spi_isr_context->event_flags;    alt_u8 rx_data = hardware_retrieve_rxdata (hardware);  sample_machine_update_from_rxdata (machine, rx_data);  if (sample_machine_done (machine)) {    pen_detect = hardware_pen_detect (hardware);    pen_state_update_from_detect_sample (pen_state, pen_detect);    event_flag_group_update_from_pen_state (flags, pen_state);						          if (pen_detect) {      int x;      int y;      sample_machine_assemble_x_y (machine, &x, &y);      pen_adc_data_update(pen_data, x, y);    }    sample_machine_reset (machine);  } else {    hardware_send_spi_command  (hardware, 				sample_machine_next_command      (machine),				sample_machine_link_next_command (machine));  }}//////////////////////////////////////////////////////////////////// init_hardware////  This does a little more than just putting the SPI hardware into a//  known state.  It:////    * Initializes the SPI-peripheral, //    * Sends a command to configure the AD7843 the way we like it.//       -- in particular, we NEED the "PEN_IRQ" feature enabled,//          or else we'll never see the pen arrive!//    * WAITS AROUND for the first "throw-away" data to come back.//    * Registers the ISR routine.//    * Enables interrupts on the hardware.//   //   Returns zero if successful.//////////////////////////////////////////////////////////////////staticint hardware_init (alt_touchscreen_hardware* hw,		   alt_u32 spi_controller_base,		   alt_u32 spi_controller_irq_number,		   alt_u32 pen_detect_pio_base,		   alt_touchscreen_spi_isr_context* context){  int    error_code;  int    tx_done = 0;  int    spi_retry_count = 0;  // Trivial setup of just-my-variables:  hw->spi_controller_base       = spi_controller_base;   hw->spi_controller_irq_number = spi_controller_irq_number;  hw->pen_detect_pio_base       = pen_detect_pio_base;   // Take no chances.  Disable interrupts; put the peripheral in a   // safe state.  IOWR_ALTERA_AVALON_SPI_CONTROL (spi_controller_base, 0);  // Clear any lingering garbage from the RX-register.  IORD_ALTERA_AVALON_SPI_RXDATA(spi_controller_base);  // Writing to the status-register clears some of the error-condition  // bits (if they happen to have gotten set somehow).  IOWR_ALTERA_AVALON_SPI_STATUS(spi_controller_base, 0);  // Select slave zero.  // The "select" register is a bit-mask.  A "1" in any bit-position  // means "please select the corresponding slave."  We only expect   // to have one slave, which is slave number zero.  So we write a "1"   // into bit zero to select it.  // This is a little counter-intuitive, because we're writing a 1 to  // select slave zero.  Still:  That's how it works.   //   IOWR_ALTERA_AVALON_SPI_SLAVE_SEL (spi_controller_base, 1);  // Write a sampling-command to the AD7843 just to turn-on the  // pen-detection feature.  We wait-around-for, and then throw away,  // the returning data.  Note that the SPI is SLOOOW, so this might  // add many, many microseconds to the callers (presumably  // initialization) code.  //  // We place a timeout on this, because it would be unseemly to  // lock-up the caller's code mysteriously at start-up if there's  // some kind of catastrophic  problem with the SPI peripheral.  //  IOWR_ALTERA_AVALON_SPI_TXDATA (spi_controller_base, 				 ALT_TOUCHSCREEN_X_SAMPLE_CMD  );  do {    tx_done =       (IORD_ALTERA_AVALON_SPI_STATUS (spi_controller_base)) &       (ALTERA_AVALON_SPI_STATUS_RRDY_MSK                          ) ;    usleep (1000);   // 1ms of waiting-around.    if (spi_retry_count++ > 20)       return -1;      }  while (!tx_done);   // Read and discard the garbage-value in the RXDATA register  IORD_ALTERA_AVALON_SPI_RXDATA(spi_controller_base);  // Before we enable interrupts, it would be a good idea to install  // our interrupt-handler.  Otherwise:  Who would handle them?  //  error_code = alt_irq_register (hw->spi_controller_irq_number,				 (void*) context,				 spi_isr);  if (error_code)     return 1;  // Now we've sent the first command and (only incidentally)  // cleared-out the recieve-buffer.  //   // Directly and belligerently write the SPI control-register to   //     * Continuously-select the slave.  //     * Enable interrupts on RX-complete (RRDY)  //  IOWR_ALTERA_AVALON_SPI_CONTROL     (spi_controller_base,     ALTERA_AVALON_SPI_CONTROL_IRRDY_MSK |     ALTERA_AVALON_SPI_CONTROL_SSO_MSK );  return 0; // Happy.}//////////////////////////////////////////////////////////////////// get_coherent_pen_data//// This is the only legal way to get sensor-data in the application// context.  Otherwise, you might get interrupted in the middle and// get something unexpected.  Did I say "might?"  This is an embedded// system.  After millions of cycles, you certainly will.//// This returns the sample-count (so software can tell if it got // a new sample).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -