c1351.c File Reference

C1350 and C1351 implementation. More...

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "ioconfig.h"
#include "c1351.h"
#include "ps2.h"

Include dependency graph for c1351.c:


Functions

void potmouse_init ()
 Init all C1351-related I/O and interrupts, but don't start yet.
void potmouse_start (uint8_t m)
 Set mode and start working.
void potmouse_movt (int16_t dx, int16_t dy, uint8_t button)
 Report movement from PS2 mouse.
void potmouse_zero (uint16_t zero)
 Define zero-point in time (normally 320us).
 ISR (INT1_vect)
 ISR (TIMER1_OVF_vect)

Detailed Description

C1350 and C1351 implementation.

Everything that emulates C1351 (proportional) and C1350 (Joystick) mice. Every movement of a real mouse is signalled with potmouse_movt(). In proportional (analog) mode, INT1 interrupt senses SID measurement cycle start and loads timer OCR1A/OCR1B values with accordance to reported counter values.

In Joystick mode, pulses are generated on UP/DOWN/LEFT/RIGHT joystick lines every time a movement is reported.


Function Documentation

ISR ( TIMER1_OVF_vect   ) 

TIMER1 Overflow vector

Ends joystick emulator pulse.

00170                      {
00171     JOYDDR  &= ~(_BV(JOYFIRE) | _BV(JOYUP) | _BV(JOYDOWN) | _BV(JOYLEFT) | _BV(JOYRIGHT));
00172     POTDDR  &= ~_BV(POTX);
00173     TIMSK &= ~_BV(TOIE1);
00174 }

ISR ( INT1_vect   ) 

SID measuring cycle detected.

1. SID pulls POTX low
2. SID waits 256 cycles us
3. SID releases POTX
4. 0 to 255 cycles until the cap is charged

This handler stops the Timer1, clears OC1A/OC1B outputs, loads the timer with values precalculated in potmouse_movt() and starts the timer.

OC1A/OC1B (YPOT/XPOT) lines will go up by hardware. Normal SID cycle is 512us. Timer will overflow not before 65535us. Next cycle will begin before that so there's no need to stop the timer. Output compare match interrupts are thus not used.

00139                {
00140     // SID started to measure the pots, uuu
00141 
00142     // disable INT1 until the measurement cycle is complete
00143     // stop the timer
00144     TCCR1B = 0;
00145     
00146     // clear OC1A/OC1B:
00147     // 1. set output compare to clear OC1A/OC1B ("10" in table 37 on page 97)
00148     TCCR1A = _BV(COM1A1) | _BV(COM1B1);
00149     // 2. force output compare to make it happen
00150     TCCR1A |= _BV(FOC1A) | _BV(FOC1B);
00151 
00152     // Set OC1A/OC1B on Compare Match (Set output to high level) 
00153     // WGM13:0 = 00, normal mode: count from BOTTOM to MAX
00154     TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0);
00155 
00156     // load the timer 
00157     TCNT1 = 0;
00158     
00159     // init the output compare values 
00160     OCR1A = ocr1a_load;
00161     OCR1B = ocr1b_load;
00162     
00163     // start timer with prescaler clk/8 (1 count = 1us)
00164     TCCR1B = _BV(CS11);  
00165 }

void potmouse_init (  ) 

Init all C1351-related I/O and interrupts, but don't start yet.

00033                      {
00034     // Joystick outputs, all to Z and no pullup
00035     JOYPORT &= ~(_BV(JOYFIRE) | _BV(JOYUP) | _BV(JOYDOWN) | _BV(JOYLEFT) | _BV(JOYRIGHT)); 
00036     JOYDDR  &= ~(_BV(JOYFIRE) | _BV(JOYUP) | _BV(JOYDOWN) | _BV(JOYLEFT) | _BV(JOYRIGHT));
00037     
00038     // SID sensing port
00039     SENSEDDR  &= ~_BV(POTSENSE); // SENSE is input
00040     SENSEPORT &= ~_BV(POTSENSE); // pullup off, hi-biased by OC1B
00041 
00042     // SID POTX/POTY port
00043     POTPORT &= ~(_BV(POTX) | _BV(POTY));
00044     POTDDR  &= ~(_BV(POTX) | _BV(POTY));
00045 
00046     // prepare INT1
00047     GICR &= ~_BV(INT1);                     // disable INT1
00048     MCUCR &= ~(_BV(ISC11)|_BV(ISC10));  
00049     MCUCR |= _BV(ISC11);                    // ISC11:ISC10 == 10, @negedge   
00050     
00051     mode = POTMOUSE_C1351;
00052 }

void potmouse_movt ( int16_t  dx,
int16_t  dy,
uint8_t  button 
)

Report movement from PS2 mouse.

00080                                                            {
00081     uint16_t a, b;
00082     
00083     switch (mode) {
00084         case POTMOUSE_C1351:
00085             potmouse_xcounter = (potmouse_xcounter + dx) & 077; // modulo 64
00086             potmouse_ycounter = (potmouse_ycounter + dy) & 077;
00087         
00088             (button & 001) ? (JOYDDR |= _BV(JOYFIRE)) : (JOYDDR &= ~_BV(JOYFIRE));
00089             (button & 002) ? (JOYDDR |= _BV(JOYUP))   : (JOYDDR &= ~_BV(JOYUP));
00090             (button & 004) ? (JOYDDR |= _BV(JOYDOWN)) : (JOYDDR &= ~_BV(JOYDOWN));
00091             
00092             // scale should be 2x here, but for this particular chip, 66 counts work better where
00093             // 64 counds should be. so 66/64=100/96 and times two
00094             a = ocr_zero + potmouse_ycounter*200/96;
00095             b = ocr_zero + potmouse_xcounter*200/96;
00096             
00097             ocr1a_load = a;
00098             ocr1b_load = b;
00099             break;
00100         case POTMOUSE_JOYSTICK:
00101             JOYDDR  &= ~(_BV(JOYFIRE) | _BV(JOYUP) | _BV(JOYDOWN) | _BV(JOYLEFT) | _BV(JOYRIGHT));
00102 
00103             (dx < 0) ? (JOYDDR |= _BV(JOYLEFT)) : (JOYDDR &= ~_BV(JOYLEFT));
00104             (dx > 0) ? (JOYDDR |= _BV(JOYRIGHT)): (JOYDDR &= ~_BV(JOYRIGHT));
00105             (dy < 0) ? (JOYDDR |= _BV(JOYDOWN)) : (JOYDDR &= ~_BV(JOYDOWN));
00106             (dy > 0) ? (JOYDDR |= _BV(JOYUP))   : (JOYDDR &= ~_BV(JOYUP));
00107             (button & 001) ? (JOYDDR |= _BV(JOYFIRE)) : (JOYDDR &= ~_BV(JOYFIRE));
00108             (button & 002) ? (POTDDR |= _BV(POTX)) : (POTDDR &= ~_BV(POTX));
00109   
00110             TCNT1 = 65535-256;
00111             TCCR1A = 0;
00112             TCCR1B = _BV(CS12)|_BV(CS10);
00113             TIFR |= _BV(TOV1);
00114             TIMSK |= _BV(TOIE1);
00115             break;
00116     }
00117 }

void potmouse_start ( uint8_t  mode  ) 

Set mode and start working.

Parameters:
mode see _potmode
00054                                {
00055     mode = m;
00056     switch (mode) {
00057         case POTMOUSE_C1351:
00058             // Initialize Timer1 and use OC1A/OC1B to output values
00059             // don't count yet    
00060             TCCR1B = 0; 
00061             
00062             // POTX/Y normally controlled by output compare unit
00063             // initially should be pulled up to provide high bias on SENSE pin
00064             POTDDR  |= _BV(POTX) | _BV(POTY);   // enable POTX/POTY as outputs
00065             POTPORT |= _BV(POTX) | _BV(POTY);   // output "1" on both
00066             
00067             GIFR |= _BV(INTF1);                     // clear INT1 flag
00068             GICR |= _BV(INT1);                      // enable INT1
00069             break;
00070         case POTMOUSE_JOYSTICK:
00071             // Joystick emulation
00072             // close directional pins for ~20ms while there is movement
00073             TCCR1B = 0;
00074             TCCR1A = 0;
00075             
00076             break;
00077     }
00078 }

void potmouse_zero ( uint16_t  zero  ) 

Define zero-point in time (normally 320us).

00119                                   {
00120     ocr_zero = zero;
00121 }


Generated on Fri Nov 13 04:21:20 2009 for [M]ouse by  doxygen 1.5.9