# Conversor USB - RS232



## soopy_46 (Sep 27, 2010)

buenas, como podria conversar el puerto usb a RS232? se que puedo comprar un adaptador, cual viene con un CD de instalacion.
No podria hacer esta conversion virtualmente? osea que me detecte algo con usb y que lo reconozca como puerto serie RS232 (COM).
He hecho un pic tengu y lo necesitaria, lo que si que he encontrado son estos codigos, y traduciondo lo que pone el primero dice que es hacer esto virtualmente:


```
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
////                            usb_cdc.h                            ////
////                                                                 ////
//// Library for adding a virtual COM port on your PC over USB using ////
//// the standard Communication Device Class (CDC) specification.    ////
//// Including this file in your code will add all USB code,         ////
//// interrupts, descriptors and handlers required.  No other        ////
//// modifications need to be made.                                  ////
////                                                                 ////
//// This library creates a virtual RS232 link between the PC and    ////
//// the PIC, therefore the library provided will be familiar to     ////
//// anyone with standard UART stream I/O:                           ////
////                                                                 ////
//// usb_cdc_kbhit() - Returns TRUE if there is one or more          ////
////      character received and waiting in the receive buffer.      ////
////                                                                 ////
//// usb_cdc_getc() - Gets a character from the receive buffer.  If  ////
////      there is no data in the receive buffer it will wait until  ////
////      there is data in the receive buffer.  If you do not want   ////
////      to wait in an infinit loop, use usb_cdc_kbhit() first to   ////
////      check if there is data before calling usb_cdc_getc().      ////
////                                                                 ////
//// usb_cdc_putc(char c) - Puts a character into the transmit       ////
////      buffer.  If the transmit buffer is full it will wait until ////
////      the transmit buffer is not full before putting the char    ////
////      into the transmit buffer.  The transmit buffer is read by  ////
////      the PC very quickly, and therefore the buffer should only  ////
////      be full for a few milli-seconds.  If you are concerned     ////
////      and don't want to be stuck in a long or infinite loop,     ////
////      use usb_cdc_putready() to see if there is space in the     ////
////      transmit buffer before putting data into the transmit      ////
////      buffer.                                                    ////
////                                                                 ////
//// usb_cdc_putready() - Returns TRUE if there is room left in the  ////
////      transmit buffer for another character.                     ////
////                                                                 ////
//// usb_cdc_connected() - Returns TRUE if we received a             ////
////      Set_Line_Coding.  On most serial terminal programs (such   ////
////      as Hyperterminal), they will send a Set_Line_Coding        ////
////      message when the program starts and it opens the virtual   ////
////      COM port.  This is a simple way to determine if the PC     ////
////      is ready to display data on a serial terminal program,     ////
////      but is not garaunteed to work all the time or on other     ////
////      terminal programs.                                         ////
////                                                                 ////
//// usb_cdc_putc_fast(char c) - Similar to usb_cdc_putc(), except   ////
////      if the transmit buffer is full it will skip the char.      ////
////                                                                 ////
//// usb_cdc_line_coding - A structure used for Set_Line_Coding and  ////
////       Get_Line_Coding.  Most of the time you can ignore this.   ////
////                                                                 ////
//// usb_cdc_break - If the PC has sent a break command, this will   ////
////       hold the break time (in milli-seconds).  If the PC sends  ////
////       a value of 0xFFFF the device is supposed to hold the      ////
////       break until it sends a value of 0                         ////
////                                                                 ////
//// usb_cdc_carrier - Where Set_Control_Line_State value is stored. ////
////       Of most relevance is the field dte_present, which is the  ////
////       DTR setting.                                              ////
////                                                                 ////
//// The following functions are also provided, and are ports of the ////
//// I/O functions in input.c.  See input.c and the CCS manual for   ////
//// documentation:                                                  ////
////   get_float_usb() - Read a float number from the user           ////
////   get_long_usb() - Read a long number from the user             ////
////   get_int_usb() - Read an integer number from the user          ////
////   get_string_usb(char *s, int max) - Read a string from the user. ////
////   gethex_usb() - Read a byte, in HEX, from the user             ////
////   gethex1_usb() - Read a HEX character                          ////
////                                                                 ////
//// This driver will load all the rest of the USB code, and a set   ////
//// of descriptors that will properly describe a CDC device for a   ////
//// virtual COM port (usb_desc_cdc.h)                               ////
////                                                                 ////
//// An .INF file is provided (cdc_NTXP.inf) that will load the      ////
//// standard CDC drivers for a virtual COM port in Windows          ////
//// NT/2000/XP and above.  Unfortunately we do not provide an .inf  ////
//// file for Windows 98 and ME.                                     ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// VERSION HISTORY                                                 ////
////                                                                 ////
//// October 27th, 2005: Changed the way incoming packets are        ////
////               handled in that CDC driver will not flush         ////
////               endpoint until user has handled all data.  This   ////
////               will prevent overflows as the USB will NAK        ////
////               incoming packets until it is ready to receive     ////
////               more.                                             ////
////            When using 18F4550 family, the RX buffer is          ////
////               mapped directly to the endpoint buffer - this     ////
////               saves a chunk of RAM.                             ////
////            When using the 18F4550 family, you can increase      ////
////               the TX and RX size over 64 bytes.                 ////
////            No longer send 0len packets in the TBE interrupt.    ////
////            Hopefully fixed bugs that caused random crashes      ////
////               if you tried sending more than 64 bytes.          ////
////                                                                 ////
//// July 6th, 2005: Global interrupts disabled when writing to TX   ////
////                   buffer.                                       ////
////                                                                 ////
//// July 1st, 2005: Initial Release.                                ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////


//api for the user:
#define usb_cdc_kbhit() (usb_cdc_get_buffer_status.got)
#define usb_cdc_putready() (usb_cdc_put_buffer_nextin<USB_CDC_DATA_IN_SIZE)
#define usb_cdc_connected() (usb_cdc_got_set_line_coding)
void usb_cdc_putc_fast(char c);
char usb_cdc_getc(void);
void usb_cdc_putc(char c);

//input.c ported to use CDC:
float get_float_usb();
signed long get_long_usb();
signed int get_int_usb();
void get_string_usb(char* s, int max);
BYTE gethex_usb();
BYTE gethex1_usb();

//functions automatically called by USB handler code
void usb_isr_tkn_cdc(void);
void usb_cdc_init(void);
void usb_isr_tok_out_cdc_control_dne(void);
void usb_isr_tok_in_cdc_data_dne(void);
void usb_isr_tok_out_cdc_data_dne(void);

void usb_cdc_flush_out_buffer(void);

//Tells the CCS PIC USB firmware to include HID handling code.
#DEFINE USB_HID_DEVICE  FALSE
#DEFINE USB_CDC_DEVICE  TRUE

#define USB_CDC_COMM_IN_ENDPOINT       1
#define USB_CDC_COMM_IN_SIZE           8
#define USB_EP1_TX_ENABLE  USB_ENABLE_INTERRUPT
#define USB_EP1_TX_SIZE  USB_CDC_COMM_IN_SIZE

//pic to pc endpoint config
#define USB_CDC_DATA_IN_ENDPOINT       2
#define USB_CDC_DATA_IN_SIZE           64
#define USB_EP2_TX_ENABLE  USB_ENABLE_BULK
#define USB_EP2_TX_SIZE  USB_CDC_DATA_IN_SIZE

//pc to pic endpoint config
#define USB_CDC_DATA_OUT_ENDPOINT       2
#define USB_CDC_DATA_OUT_SIZE           64
#define USB_EP2_RX_ENABLE  USB_ENABLE_BULK
#define USB_EP2_RX_SIZE  USB_CDC_DATA_OUT_SIZE

/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.  See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#ifndef __USB_PIC_PERIF__
#define __USB_PIC_PERIF__   1
#endif

#if __USB_PIC_PERIF__
 #if defined(__PCM__)
  #error CDC requires bulk mode!  PIC16C7x5 does not have bulk mode
 #else
  #include <pic18_usb.h>   //Microchip 18Fxx5x hardware layer for usb.c
 #endif
#else
 #include <usbn960x.c>   //National 960x hardware layer for usb.c
#endif
#include ".\include\juanfe_USB_Cdc_Monitor.h"   //USB Configuration and Device descriptors for this UBS device
#include <usb.c>        //handles usb setup tokens and get descriptor reports

struct {
        int32   dwDTERrate;   //data terminal rate, in bits per second
        int8    bCharFormat;  //num of stop bits (0=1, 1=1.5, 2=2)
        int8    bParityType;  //parity (0=none, 1=odd, 2=even, 3=mark, 4=space)
        int8    bDataBits;    //data bits (5,6,7,8 or 16)
} usb_cdc_line_coding;

//length of time, in ms, of break signal as we received in a SendBreak message.
//if ==0xFFFF, send break signal until we receive a 0x0000.
int16 usb_cdc_break;

int8 usb_cdc_encapsulated_cmd[8];

int8 usb_cdc_put_buffer[USB_CDC_DATA_IN_SIZE];
int1 usb_cdc_put_buffer_free;
#if USB_CDC_DATA_IN_SIZE>=0x100
 int16 usb_cdc_put_buffer_nextin=0;
// int16 usb_cdc_last_data_packet_size;
#else
 int8 usb_cdc_put_buffer_nextin=0;
// int8 usb_cdc_last_data_packet_size;
#endif

struct {
   int1 got;
  #if USB_CDC_DATA_OUT_SIZE>=0x100
   int16 len;
   int16 index;
  #else
   int8 len;
   int8 index;
  #endif
} usb_cdc_get_buffer_status;

int8 usb_cdc_get_buffer_status_buffer[USB_CDC_DATA_OUT_SIZE];
#if (defined(__PIC__))
 #if __PIC__
  //#locate usb_cdc_get_buffer_status_buffer=0x500+(2*USB_MAX_EP0_PACKET_LENGTH)+USB_CDC_COMM_IN_SIZE
  #if USB_MAX_EP0_PACKET_LENGTH==8
     #locate usb_cdc_get_buffer_status_buffer=0x500+24
  #elif USB_MAX_EP0_PACKET_LENGTH==64
     #locate usb_cdc_get_buffer_status_buffer=0x500+136
  #else
   #error CCS BUG WONT LET ME USE MATH IN LOCATE
  #endif
 #endif
#endif

int1 usb_cdc_got_set_line_coding;

struct  {
   int1 dte_present; //1=DTE present, 0=DTE not present
   int1 active;      //1=activate carrier, 0=deactivate carrier
   int reserved:6;
} usb_cdc_carrier;

enum {USB_CDC_OUT_NOTHING=0, USB_CDC_OUT_COMMAND=1, USB_CDC_OUT_LINECODING=2, USB_CDC_WAIT_0LEN=3} __usb_cdc_state=0;

#byte INTCON=0xFF2
#bit INT_GIE=INTCON.7

//handle OUT token done interrupt on endpoint 0 [read encapsulated cmd and line coding data]
void usb_isr_tok_out_cdc_control_dne(void) {
   debug_usb(debug_putc,"CDC %X ",__usb_cdc_state);

   switch (__usb_cdc_state) {
      //printf(putc_tbe,"@%X@\r\n", __usb_cdc_state);
      case USB_CDC_OUT_COMMAND:
         //usb_get_packet(0, usb_cdc_encapsulated_cmd, 8);
         memcpy(usb_cdc_encapsulated_cmd, usb_ep0_rx_buffer,8);
        #if USB_MAX_EP0_PACKET_LENGTH==8
         __usb_cdc_state=USB_CDC_WAIT_0LEN;
         usb_request_get_data();
        #else
         usb_put_0len_0();
         __usb_cdc_state=0;
        #endif
         break;

    #if USB_MAX_EP0_PACKET_LENGTH==8
      case USB_CDC_WAIT_0LEN:
         usb_put_0len_0();
         __usb_cdc_state=0;
         break;
    #endif

      case USB_CDC_OUT_LINECODING:
         //usb_get_packet(0, &usb_cdc_line_coding, 7);
         //printf(putc_tbe,"\r\n!GSLC FIN!\r\n");
         memcpy(&usb_cdc_line_coding, usb_ep0_rx_buffer,7);
         __usb_cdc_state=0;
         usb_put_0len_0();
         break;

      default:
         __usb_cdc_state=0;
         usb_init_ep0_setup();
         break;
   }
}

//handle IN token on 0 (setup packet)
void usb_isr_tkn_cdc(void) {
   //make sure the request goes to a CDC interface
   if ((usb_ep0_rx_buffer[4] == 1) || (usb_ep0_rx_buffer[4] == 0)) {
      //printf(putc_tbe,"!%X!\r\n", usb_ep0_rx_buffer[1]);
      switch(usb_ep0_rx_buffer[1]) {
         case 0x00:  //send_encapsulated_command
            __usb_cdc_state=USB_CDC_OUT_COMMAND;
            usb_request_get_data();
            break;

         case 0x01:  //get_encapsulated_command
            memcpy(usb_ep0_tx_buffer, usb_cdc_encapsulated_cmd, 8);
            usb_request_send_response(usb_ep0_rx_buffer[6]);  //send wLength bytes
            break;

         case 0x20:  //set_line_coding
            debug_usb(debug_putc,"!GSLC!");
            __usb_cdc_state=USB_CDC_OUT_LINECODING;
            usb_cdc_got_set_line_coding=TRUE;
            usb_request_get_data();
            break;

         case 0x21:  //get_line_coding
            memcpy(usb_ep0_tx_buffer, &usb_cdc_line_coding, sizeof(usb_cdc_line_coding));
            usb_request_send_response(sizeof(usb_cdc_line_coding)); //send wLength bytes
            break;

         case 0x22:  //set_control_line_state
            usb_cdc_carrier=usb_ep0_rx_buffer[2];
            usb_put_0len_0();
            break;

         case 0x23:  //send_break
            usb_cdc_break=make16(usb_ep0_rx_buffer[2],usb_ep0_rx_buffer[3]);
            usb_put_0len_0();
            break;

         default:
            usb_request_stall();
            break;
      }
   }
}

//handle OUT token done interrupt on endpoint 3 [buffer incoming received chars]
void usb_isr_tok_out_cdc_data_dne(void) {
   usb_cdc_get_buffer_status.got=TRUE;
   usb_cdc_get_buffer_status.index=0;
#if (defined(__PIC__))
   #if __PIC__
    usb_cdc_get_buffer_status.len=usb_rx_packet_size(USB_CDC_DATA_OUT_ENDPOINT);
   #else
    usb_cdc_get_buffer_status.len=usb_get_packet_buffer(
       USB_CDC_DATA_OUT_ENDPOINT,&usb_cdc_get_buffer_status_buffer[0],USB_CDC_DATA_OUT_SIZE);
   #endif
#else
   usb_cdc_get_buffer_status.len=usb_get_packet_buffer(
      USB_CDC_DATA_OUT_ENDPOINT,&usb_cdc_get_buffer_status_buffer[0],USB_CDC_DATA_OUT_SIZE);
#endif
}

//handle IN token done interrupt on endpoint 2 [transmit buffered characters]
void usb_isr_tok_in_cdc_data_dne(void) {
   if (usb_cdc_put_buffer_nextin) {
      usb_cdc_flush_out_buffer();
   }
   //send a 0len packet if needed
//   else if (usb_cdc_last_data_packet_size==USB_CDC_DATA_IN_SIZE) {
//      usb_cdc_last_data_packet_size=0;
//      printf(putc_tbe, "FL 0\r\n");
//      usb_put_packet(USB_CDC_DATA_IN_ENDPOINT,0,0,USB_DTS_TOGGLE);
//   }
   else {
      usb_cdc_put_buffer_free=TRUE;
      //printf(putc_tbe, "FL DONE\r\n");
   }
}

void usb_cdc_flush_out_buffer(void) {
   if (usb_cdc_put_buffer_nextin) {
      usb_cdc_put_buffer_free=FALSE;
      //usb_cdc_last_data_packet_size=usb_cdc_put_buffer_nextin;
      //printf(putc_tbe, "FL %U\r\n", usb_cdc_put_buffer_nextin);
      usb_put_packet(USB_CDC_DATA_IN_ENDPOINT,usb_cdc_put_buffer,usb_cdc_put_buffer_nextin,USB_DTS_TOGGLE);
      usb_cdc_put_buffer_nextin=0;
   }
}

void usb_cdc_init(void) {
   usb_cdc_line_coding.dwDTERrate=9600;
   usb_cdc_line_coding.bCharFormat=0;
   usb_cdc_line_coding.bParityType=0;
   usb_cdc_line_coding.bDataBits=8;
   (int8)usb_cdc_carrier=0;
   usb_cdc_got_set_line_coding=FALSE;
   usb_cdc_break=0;
   usb_cdc_put_buffer_nextin=0;
   usb_cdc_get_buffer_status.got=0;
   usb_cdc_put_buffer_free=TRUE;
}

////////////////// END USB CONTROL HANDLING //////////////////////////////////

////////////////// BEGIN USB<->RS232 CDC LIBRARY /////////////////////////////

char usb_cdc_getc(void) {
   char c;

   while (!usb_cdc_kbhit()) {}

   c=usb_cdc_get_buffer_status_buffer[usb_cdc_get_buffer_status.index++];
   if (usb_cdc_get_buffer_status.index >= usb_cdc_get_buffer_status.len) {
      usb_cdc_get_buffer_status.got=FALSE;
      usb_flush_out(USB_CDC_DATA_OUT_ENDPOINT, USB_DTS_TOGGLE);
   }

   return(c);
}

void usb_cdc_putc_fast(char c) {
   int1 old_gie;

   //disable global interrupts
   old_gie=INT_GIE;
   INT_GIE=0;

   if (usb_cdc_put_buffer_nextin >= USB_CDC_DATA_IN_SIZE) {
      usb_cdc_put_buffer_nextin=USB_CDC_DATA_IN_SIZE-1;  //we just overflowed the buffer!
   }
   usb_cdc_put_buffer[usb_cdc_put_buffer_nextin++]=c;

   //renable global interrupts
   INT_GIE=old_gie;

   /*
   if (usb_tbe(USB_CDC_DATA_IN_ENDPOINT)) {
      if (usb_cdc_put_buffer_nextin)
         usb_cdc_flush_out_buffer();
   }
   */
   if (usb_cdc_put_buffer_free) {
      usb_cdc_flush_out_buffer();
   }
}

void usb_cdc_putc(char c) {
   while (!usb_cdc_putready()) {
      if (usb_cdc_put_buffer_free) {
         usb_cdc_flush_out_buffer();
      }
      //delay_ms(500);
      //printf(putc_tbe,"TBE=%U CNT=%U LST=%U\r\n",usb_tbe(USB_CDC_DATA_IN_ENDPOINT), usb_cdc_put_buffer_nextin, usb_cdc_last_data_packet_size);
   }
   usb_cdc_putc_fast(c);
}

#include <ctype.h>

BYTE gethex1_usb() {
   char digit;

   digit = usb_cdc_getc();

   usb_cdc_putc(digit);

   if(digit<='9')
     return(digit-'0');
   else
     return((toupper(digit)-'A')+10);
}

BYTE gethex_usb() {
   int lo,hi;

   hi = gethex1_usb();
   lo = gethex1_usb();
   if(lo==0xdd)
     return(hi);
   else
     return( hi*16+lo );
}

void get_string_usb(char* s, int max) {
   int len;
   char c;

   --max;
   len=0;
   do {
     c=usb_cdc_getc();
     if(c==8) {  // Backspace
        if(len>0) {
          len--;
          usb_cdc_putc(c);
          usb_cdc_putc(' ');
          usb_cdc_putc(c);
        }
     } else if ((c>=' ')&&(c<='~'))
       if(len<max) {
         s[len++]=c;
         usb_cdc_putc(c);
       }
   } while(c!=13);
   s[len]=0;
}


// stdlib.h is required for the ato_ conversions
// in the following functions
#ifdef _STDLIB

signed int get_int_usb() {
  char s[5];
  signed int i;

  get_string_usb(s, 5);

  i=atoi(s);
  return(i);
}

signed long get_long_usb() {
  char s[7];
  signed long l;

  get_string_usb(s, 7);
  l=atol(s);
  return(l);
}

float get_float_usb() {
  char s[20];
  float f;

  get_string_usb(s, 20);
  f = atof(s);
  return(f);
}

#endif
```

y luego estos otros pero no se que son:


```
///////////////////////////////////////////////////////////////////////////
////                         usb_desc_cdc.h                            ////
////                                                                   ////
//// An example set of device / configuration descriptors for use with ////
//// CCS's CDC Virtual COM Port driver (see usb_cdc.h)                 ////
////                                                                   ////
//// Two examples are provided:                                        ////
////      ex_usb_serial.c                                              ////
////      ex_usb_serial2.c                                             ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// Version History:                                                  ////
////                                                                   ////
//// 10/28/05:                                                         ////
////    Bulk endpoint sizes updated to allow more than 255 byte        ////
////    packets.                                                       ////
////    Changed device to USB 1.10                                     ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>


//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      67  //config+interface+class+endpoint+endpoint (2 endpoints)

   const char USB_CONFIG_DESC[] = {
   //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
      //    config(s)
      //    interface(s)
      //    class(es)
      //    endpoint(s)

   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN, //length of descriptor size          ==0
         USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)     ==1
         USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config      ==2,3
         2, //number of interfaces this device supports       ==4
         0x01, //identifier for this configuration.  (IF we had more than one configurations)      ==5
         0x00, //index of string descriptor for this configuration      ==6
         0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1         ==7
         0x32, //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)  ==8

   //interface descriptor 0 (comm class interface)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =9
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =10
         0x00, //number defining this interface (IF we had more than one interface)    ==11
         0x00, //alternate setting     ==12
         1, //number of endpoints   ==13
         0x02, //class code, 02 = Comm Interface Class     ==14
         0x02, //subclass code, 2 = Abstract     ==15
         0x01, //protocol code, 1 = v.25ter      ==16
         0x00, //index of string descriptor for interface      ==17

   //class descriptor [functional header]
         5, //length of descriptor    ==18
         0x24, //dscriptor type (0x24 == )      ==19
         0, //sub type (0=functional header) ==20
         0x10,0x01, //      ==21,22 //cdc version

   //class descriptor [acm header]
         4, //length of descriptor    ==23
         0x24, //dscriptor type (0x24 == )      ==24
         2, //sub type (2=ACM)   ==25
         2, //capabilities    ==26  //we support Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.

   //class descriptor [union header]
         5, //length of descriptor    ==27
         0x24, //dscriptor type (0x24 == )      ==28
         6, //sub type (6=union)    ==29
         0, //master intf     ==30  //The interface number of the Communication or Dat a Cl ass interface, designated as the masteror controlling interface for the union.
         1, //save intf0      ==31  //Interface number of first slave or associated interface in the union. *

   //class descriptor [call mgmt header]
         5, //length of descriptor    ==32
         0x24, //dscriptor type (0x24 == )      ==33
         1, //sub type (1=call mgmt)   ==34
         0, //capabilities          ==35  //device does not handle call management itself
         1, //data interface        ==36  //interface number of data class interface

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==37
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==38
         USB_CDC_COMM_IN_ENDPOINT | 0x80, //endpoint number and direction
         0x03, //transfer type supported (0x03 is interrupt)         ==40
         USB_CDC_COMM_IN_SIZE,0x00, //maximum packet size supported                  ==41,42
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==43

   //interface descriptor 1 (data class interface)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =44
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =45
         0x01, //number defining this interface (IF we had more than one interface)    ==46
         0x00, //alternate setting     ==47
         2, //number of endpoints   ==48
         0x0A, //class code, 0A = Data Interface Class     ==49
         0x00, //subclass code      ==50
         0x00, //protocol code      ==51
         0x00, //index of string descriptor for interface      ==52

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==60
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==61
         USB_CDC_DATA_OUT_ENDPOINT, //endpoint number and direction (0x02 = EP2 OUT)       ==62
         0x02, //transfer type supported (0x02 is bulk)         ==63
//         make8(USB_CDC_DATA_OUT_SIZE,0),make8(USB_CDC_DATA_OUT_SIZE,1), //maximum packet size supported                  ==64, 65
         USB_CDC_DATA_OUT_SIZE & 0xFF, (USB_CDC_DATA_OUT_SIZE >> 8) & 0xFF, //maximum packet size supported                  ==64, 65
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==66

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==53
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==54
         USB_CDC_DATA_IN_ENDPOINT | 0x80, //endpoint number and direction (0x82 = EP2 IN)       ==55
         0x02, //transfer type supported (0x02 is bulk)         ==56
//         make8(USB_CDC_DATA_IN_SIZE,0),make8(USB_CDC_DATA_IN_SIZE,1), //maximum packet size supported                  ==57, 58
         USB_CDC_DATA_IN_SIZE & 0xFF, (USB_CDC_DATA_IN_SIZE >> 8) & 0xFF, //maximum packet size supported                  ==64, 65
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==59
   };

   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   2

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //define where to find class descriptors
   //first dimension is the config number
   //second dimension specifies which interface
   //last dimension specifies which class in this interface to get, but most will only have 1 class per interface
   //if a class descriptor is not valid, set the value to 0xFFFF
   const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][USB_MAX_NUM_INTERFACES][4]=
   {
   //config 1
      //interface 0
         //class 1-4
         18,23,27,32,
      //interface 1
         //no classes for this interface
         0xFFFF,0xFFFF,0xFFFF,0xFFFF
   };

   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   const char USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] ={
      //starts of with device configuration. only one possible
         USB_DESC_DEVICE_LEN, //the length of this report   ==0
         0x01, //the constant DEVICE (DEVICE 0x01)  ==1
         0x10,0x01, //usb version in bcd  ==2,3
         0x02, //class code. 0x02=Communication Device Class ==4
         0x00, //subclass code ==5
         0x00, //protocol code ==6
         USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8) ==7

         0xD8,0x04,           //vendor id (0x04D8 is Microchip)
         0x0A,0x00,           //product id

// RR2 cambiado para       0x61,0x04, //vendor id (0x04D8 is Microchip, or is it 0x0461 ??)  ==8,9
// compatibilidad con .inf 0x33,0x00, //product id   ==10,11
// de Microchip

         0x00,0x01, //device release number  ==12,13
         0x01, //index of string description of manufacturer. therefore we point to string_1 array (see below)  ==14
         0x02, //index of string descriptor of the product  ==15
         0x00, //index of string descriptor of serial number  ==16
         USB_NUM_CONFIGURATIONS  //number of possible configurations  ==17
   };


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
///   You must define the length else get_next_string_character() will not see the string
///   Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string.  offset[0] is the start of string 0, offset[1] is the start of string 1, etc.
char USB_STRING_DESC_OFFSET[]={0,4,18};

char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         0x09,0x04,   //Microsoft Defined for US-English
   //string 1
         14, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'J',0,
         'U',0,
         'A',0,
         'N',0,
         'F',0,
         'E',0,
   //string 2 --> nombre del dispositivo
         20, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'P',0,
         'i',0,
         'c',0,
         'T',0,
         'e',0,
         'n',0,
         'g',0,
         'u',0,
};

#ENDIF
```
y

```
///////////////////////////////////////////////////////////////////////////
////                         usb_desc_cdc.h                            ////
////                                                                   ////
//// An example set of device / configuration descriptors for use with ////
//// CCS's CDC Virtual COM Port driver (see usb_cdc.h)                 ////
////                                                                   ////
//// Two examples are provided:                                        ////
////      ex_usb_serial.c                                              ////
////      ex_usb_serial2.c                                             ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// Version History:                                                  ////
////                                                                   ////
//// 10/28/05:                                                         ////
////    Bulk endpoint sizes updated to allow more than 255 byte        ////
////    packets.                                                       ////
////    Changed device to USB 1.10                                     ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>


//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      67  //config+interface+class+endpoint+endpoint (2 endpoints)

   const char USB_CONFIG_DESC[] = {
   //IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
      //    config(s)
      //    interface(s)
      //    class(es)
      //    endpoint(s)

   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN, //length of descriptor size          ==0
         USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02)     ==1
         USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config      ==2,3
         2, //number of interfaces this device supports       ==4
         0x01, //identifier for this configuration.  (IF we had more than one configurations)      ==5
         0x00, //index of string descriptor for this configuration      ==6
         0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 unused and bit7=1         ==7
         0x32, //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)  ==8

   //interface descriptor 0 (comm class interface)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =9
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =10
         0x00, //number defining this interface (IF we had more than one interface)    ==11
         0x00, //alternate setting     ==12
         1, //number of endpoints   ==13
         0x02, //class code, 02 = Comm Interface Class     ==14
         0x02, //subclass code, 2 = Abstract     ==15
         0x01, //protocol code, 1 = v.25ter      ==16
         0x00, //index of string descriptor for interface      ==17

   //class descriptor [functional header]
         5, //length of descriptor    ==18
         0x24, //dscriptor type (0x24 == )      ==19
         0, //sub type (0=functional header) ==20
         0x10,0x01, //      ==21,22 //cdc version

   //class descriptor [acm header]
         4, //length of descriptor    ==23
         0x24, //dscriptor type (0x24 == )      ==24
         2, //sub type (2=ACM)   ==25
         2, //capabilities    ==26  //we support Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.

   //class descriptor [union header]
         5, //length of descriptor    ==27
         0x24, //dscriptor type (0x24 == )      ==28
         6, //sub type (6=union)    ==29
         0, //master intf     ==30  //The interface number of the Communication or Dat a Cl ass interface, designated as the masteror controlling interface for the union.
         1, //save intf0      ==31  //Interface number of first slave or associated interface in the union. *

   //class descriptor [call mgmt header]
         5, //length of descriptor    ==32
         0x24, //dscriptor type (0x24 == )      ==33
         1, //sub type (1=call mgmt)   ==34
         0, //capabilities          ==35  //device does not handle call management itself
         1, //data interface        ==36  //interface number of data class interface

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==37
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==38
         USB_CDC_COMM_IN_ENDPOINT | 0x80, //endpoint number and direction
         0x03, //transfer type supported (0x03 is interrupt)         ==40
         USB_CDC_COMM_IN_SIZE,0x00, //maximum packet size supported                  ==41,42
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==43

   //interface descriptor 1 (data class interface)
         USB_DESC_INTERFACE_LEN, //length of descriptor      =44
         USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04)       =45
         0x01, //number defining this interface (IF we had more than one interface)    ==46
         0x00, //alternate setting     ==47
         2, //number of endpoints   ==48
         0x0A, //class code, 0A = Data Interface Class     ==49
         0x00, //subclass code      ==50
         0x00, //protocol code      ==51
         0x00, //index of string descriptor for interface      ==52

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==60
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==61
         USB_CDC_DATA_OUT_ENDPOINT, //endpoint number and direction (0x02 = EP2 OUT)       ==62
         0x02, //transfer type supported (0x02 is bulk)         ==63
//         make8(USB_CDC_DATA_OUT_SIZE,0),make8(USB_CDC_DATA_OUT_SIZE,1), //maximum packet size supported                  ==64, 65
         USB_CDC_DATA_OUT_SIZE & 0xFF, (USB_CDC_DATA_OUT_SIZE >> 8) & 0xFF, //maximum packet size supported                  ==64, 65
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==66

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor                   ==53
         USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05)          ==54
         USB_CDC_DATA_IN_ENDPOINT | 0x80, //endpoint number and direction (0x82 = EP2 IN)       ==55
         0x02, //transfer type supported (0x02 is bulk)         ==56
//         make8(USB_CDC_DATA_IN_SIZE,0),make8(USB_CDC_DATA_IN_SIZE,1), //maximum packet size supported                  ==57, 58
         USB_CDC_DATA_IN_SIZE & 0xFF, (USB_CDC_DATA_IN_SIZE >> 8) & 0xFF, //maximum packet size supported                  ==64, 65
         250,  //polling interval, in ms.  (cant be smaller than 10)      ==59
   };

   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   2

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

   //define where to find class descriptors
   //first dimension is the config number
   //second dimension specifies which interface
   //last dimension specifies which class in this interface to get, but most will only have 1 class per interface
   //if a class descriptor is not valid, set the value to 0xFFFF
   const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS][USB_MAX_NUM_INTERFACES][4]=
   {
   //config 1
      //interface 0
         //class 1-4
         18,23,27,32,
      //interface 1
         //no classes for this interface
         0xFFFF,0xFFFF,0xFFFF,0xFFFF
   };

   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   const char USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] ={
      //starts of with device configuration. only one possible
         USB_DESC_DEVICE_LEN, //the length of this report   ==0
         0x01, //the constant DEVICE (DEVICE 0x01)  ==1
         0x10,0x01, //usb version in bcd  ==2,3
         0x02, //class code. 0x02=Communication Device Class ==4
         0x00, //subclass code ==5
         0x00, //protocol code ==6
         USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8) ==7

         0xD8,0x04,           //vendor id (0x04D8 is Microchip)
         0x0A,0x00,           //product id

// RR2 cambiado para       0x61,0x04, //vendor id (0x04D8 is Microchip, or is it 0x0461 ??)  ==8,9
// compatibilidad con .inf 0x33,0x00, //product id   ==10,11
// de Microchip

         0x00,0x01, //device release number  ==12,13
         0x01, //index of string description of manufacturer. therefore we point to string_1 array (see below)  ==14
         0x02, //index of string descriptor of the product  ==15
         0x00, //index of string descriptor of serial number  ==16
         USB_NUM_CONFIGURATIONS  //number of possible configurations  ==17
   };


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
///   You must define the length else get_next_string_character() will not see the string
///   Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string.  offset[0] is the start of string 0, offset[1] is the start of string 1, etc.
char USB_STRING_DESC_OFFSET[]={0,4,12};

char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         0x09,0x04,   //Microsoft Defined for US-English
   //string 1
         8, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'R',0,
         'R',0,
         '2',0,
   //string 2 --> nombre del dispositivo
         22, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'R',0,
         'e',0,
         'd',0,
         'P',0,
         'i',0,
         'c',0,
         ' ',0,
         'U',0,
         'S',0,
         'B',0
};

#ENDIF
```

Me imagino que debe ser todo para lo mismo, pero no se que es que ni con que programarlo...
quiza con algun programa java? con que tendria yo que  hacer esto? gracias y estaria muy agradecido que me ayudaran.

Saludos 
Sergio.

PD: o quizas sea para añadirle a la programacion del PIC? (utilizo un pic 18F2455)

la programacion del pic es la siguiente:


```
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// PIC_Tengu_v1.c                                                  ////
////                                                                 ////
//// Autor: jfmateos2                                                ////
//// Contacto: jfmateos@lycos.es                                     ////
//// Madrid, abril 2008                                              ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////

#include <18F2455.h>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN, CCP2C1
#device ADC=8
#use delay(clock=48000000)
#include <stdlib.h>
#include ".\include\usb_cdc.h"
#rom int8 0xf00000={5,0,0,0,0,0,//0-->5 (edad,copiaEdad,usos futuros,...)
12,250,1,249,251,60,61,62,63,64,65,251,254,//6-->18 (animacion: edad-vela)
29,29,25,26,21,10,48,26,10,28,10,48,10,26,10,16,10,28,48,21,10,29,48,32,14,21,10,29,48,48,//19-->48
202,17,10,35,48,27,31,18,14,23,48,26,18,14,23,29,10,48,27,31,14,48,29,25,21,25,48,31,23,48,21,
25,12,25,48,12,14,21,14,11,28,10,28,18,10,48,27,31,14,48,12,31,22,26,21,14,48,10,24,25,29,
38,48,35,48,27,31,14,48,17,10,35,48,27,31,14,48,10,26,28,25,32,14,12,17,10,28,48,26,25,28,
27,31,14,48,23,31,23,12,10,48,29,14,48,32,25,21,32,14,28,10,48,10,48,29,14,28,48,30,10,23,
48,19,25,32,14,23,38,48,10,31,23,27,31,14,48,30,10,22,26,25,12,25,48,23,31,23,12,10,48,29,
14,48,17,10,48,29,18,13,25,48,30,10,23,48,32,18,14,19,25,38,48,10,31,23,48,10,29,18,38,48,
15,14,21,18,36,48,12,31,22,26,21,14,10,24,25,29,48,10,21,22,31,37}//49-->251

#define PRECARGA_TIMER 0
#define UMBRAL_PARPADEO 100 //Max=128.Está afectado por VELOCIDAD_GESTICULACION
#define VELOCIDAD_GESTICULACION 20000
#define UMBRAL_SOPLIDO 90
#define VELOCIDAD_TEXTO 4500
#define PROPORCION_ANIMACION_AVANCE 2 
#define UMBRAL_AUDICION 3
#define UMBRAL_DORMIRSE 5000

unsigned int8 i;
unsigned int8  columnaActual=5;
int1 conversorOcupado=0;
int1 modoFuncionamiento;
int1 botonPulsado=0;
int1 resetear=0;
int16 ciclosTimer1;

int filas[7]={PIN_C0,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7};
int *cara, *caraEnVisualizacion;

//Atención, la longitud de cada array siguiente está codificada en el propio
//array, porque como cada columna sólo utiliza 7 bits he aprovechado
//el octavo para codificar la longitud.
//Numeros
int caracter0[3]={31,17,31+128};//0
int caracter1[3]={9,31,1+128};//1
int caracter2[3]={19,21,9+128};//2
int caracter3[3]={17,21,26+128};//3
int caracter4[3]={6,10,31+128};//4
int caracter5[3]={29,21,18+128};//5
int caracter6[3]={15,21,22+128};//6
int caracter7[3]={16,23,24+128};//7
int caracter8[3]={31,21,31+128};//8
int caracter9[3]={28,20,31+128};//9
//Letras mayúsculas
int caracter10[3]={15,20,15+128};//A
int caracter11[3]={31,21,10+128};//B
int caracter12[3]={14,17,10+128};//C
int caracter13[3]={31,17,14+128};//D
int caracter14[3]={31,21,17+128};//E
int caracter15[3]={31,20,16+128};//F
int caracter16[3]={14,17,23+128};//G
int caracter17[3]={31,4,31+128};//H
int caracter18[3]={17,31,17+128};//I
int caracter19[3]={2,17,31+128};//J
int caracter20[3]={31,12,19+128};//K
int caracter21[3]={31,1,1+128};//L
int caracter22[5]={31,8,4,8,31+128};//M   
int caracter23[5]={31,8,4,2,31+128};//N
int caracter24[5]={31,72,68,66,31+128};//Ñ
int caracter25[3]={14,17,14+128};//O
int caracter26[3]={31,20,8+128};//P
int caracter27[4]={31,17,19,31+128};//Q
int caracter28[3]={31,20,11+128};//R
int caracter29[3]={9,21,18+128};//S
int caracter30[3]={16,31,16+128};//T
int caracter31[3]={31,1,31+128};//U   
int caracter32[3]={30,3,30+128};//V
int caracter33[5]={31,2,4,2,31+128};//W
int caracter34[3]={27,4,27+128};//X
int caracter35[3]={24,7,24+128};//Y
int caracter36[3]={19,21,25+128};//Z
//Signos de puntuacion
int caracter37[2]={3,3+128};//.
int caracter38[2]={1,6+128};//,
int caracter39[1]={10+128};//:
int caracter40[2]={1,10+128};//;
int caracter41[1]={95+128};//¡
int caracter42[1]={125+128};//!
int caracter43[3]={14,81,2+128};//¿
int caracter44[3]={32,69,56+128};//?
int caracter45[2]={16,96+128};//´
int caracter46[2]={62,65+128};//(
int caracter47[2]={65,62+128};//)
int caracter48[2]={0,0+128};// (espacio)
//Caracteres especiales
int caracter49[5]={2,21,23,17,14+128};//@
int caracter50[3]={50,107,38+128};//$
int caracter51[5]={20,62,85,65,34+128};//€
//Signos matemáticos
int caracter52[3]={4,14,4+128};//+
int caracter53[3]={4,4,4+128};//-
int caracter54[3]={10,4,10+128};//*
int caracter55[3]={3,4,24+128};///
int caracter56[3]={19,4,25+128};//%
int caracter57[3]={4,10,17+128};//<
int caracter58[3]={17,10,4+128};//>
int caracter59[3]={10,10,10+128};//=
//Velas
int caracter60[6]={3,9,29,61,57,3+128};
int caracter61[6]={3,9,29,61,121,3+128};
int caracter62[6]={3,9,61,125,25,3+128};
int caracter63[6]={3,25,125,61,9,3+128};
int caracter64[6]={3,121,61,29,9,3+128};
int caracter65[6]={3,57,61,29,9,3+128};
int caracter66[6]={3,1,1,1,1,3+128};//vela apagada
//French
int caracter67[3]={47,74,15+128};//Á
int caracter68[3]={15,74,47+128};//À
int caracter69[3]={47,74,47+128};//Â
int caracter70[3]={63,85,17+128};//É
int caracter71[3]={31,85,49+128};//È
int caracter72[3]={63,85,49+128};//Ê
int caracter73[3]={95,21,81+128};//Ë
int caracter74[3]={41,79,9+128};//Í
int caracter75[3]={41,79,41+128};//Î
int caracter76[3]={81,31,81+128};//Ï
int caracter77[3]={38,73,6+128};//Ó
int caracter78[3]={38,73,38+128};//Ô
int caracter79[3]={47,65,15+128};//Ú
int caracter80[3]={15,47,65+128};//Ù
int caracter81[3]={47,65,47+128};//Û
int caracter82[3]={95,1,95+128};//Ü
int caracter83[3]={125,70,68+128};//Ç


//Caracteres reservados a partir del 240 (incluido)
//caracter246 -->Final de cadena transmitida por USB
//caracter247 -->Visualización inmediata del caracter siguiente (sin arrastre)
//caracter248 -->Volver al principio
//caracter249 -->Quitar espacio sufijo en caracter siguiente
//caracter250 -->Saltar a siguiente caracter
//caracter251 -->Inicio y final de animacion yo-yo
//caracter252 -->Inicio y final de animacion diente de sierra
//caracter253 -->Pausa corta/saltarse un avance
//caracter254 -->Stop
//caracter255 -->Nulo (se usa en animaciones)

int const * caracter[84]={caracter0,caracter1,caracter2,caracter3,caracter4,caracter5,
                    caracter6,caracter7,caracter8,caracter9,caracter10,caracter11,
                    caracter12,caracter13,caracter14,caracter15,caracter16,caracter17,
                    caracter18,caracter19,caracter20,caracter21,caracter22,caracter23,
                    caracter24,caracter25,caracter26,caracter27,caracter28,caracter29,
                    caracter30,caracter31,caracter32,caracter33,caracter34,caracter35,
                    caracter36,caracter37,caracter38,caracter39,caracter40,caracter41,
                    caracter42,caracter43,caracter44,caracter45,caracter46,caracter47,
                    caracter48,caracter49,caracter50,caracter51,caracter52,caracter53,
                    caracter54,caracter55,caracter56,caracter57,caracter58,caracter59,
                    caracter60,caracter61,caracter62,caracter63,caracter64,caracter65,
                    caracter66,caracter67,caracter68,caracter69,caracter70,caracter71,
                    caracter72,caracter73,caracter74,caracter75,caracter76,caracter77,
                    caracter78,caracter79,caracter80,caracter81,caracter82,caracter83};

#INT_EXT1
void int1_handler(){
   if(!botonPulsado){
      botonPulsado=1;
      modoFuncionamiento=!modoFuncionamiento;
      ciclosTimer1=400;               
      ext_int_edge(1,L_TO_H);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
      set_timer1(0);
   }else{      
      botonPulsado=0;      
      setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
      ext_int_edge(1,H_TO_L);     
      
   }   
}

#INT_TIMER1
void timer1_handler(){   
   if(--ciclosTimer1==0){         
      resetear=1;
   }   
}

#INT_AD
void ad_handler(){
   conversorOcupado=0;
}

#INT_TIMER0
void tmr_handler() {    
      //Apagar
      output_a(0);
      //Cambiar de columna
      if (columnaActual==5){
         columnaActual=0;
         if(caraEnVisualizacion!=cara){
            caraEnVisualizacion=cara;
         }
      }else{
         columnaActual++;
      } 
      //Preparar filas
      for(i=0;i<7;i++){
         output_bit(filas[i],*(caraEnVisualizacion+columnaActual)&(64>>i));
      }
      //Encender columna
      output_a(1<<columnaActual);      
      set_timer0(PRECARGA_TIMER);
}

void int mostrarTexto (int1 tipo, int parametro, int1 salirConSoplido, int1 atenuacionUmbralSoplido,int1 salirConBoton, int1 salirSoloFinal){
   unsigned int i,j;
   int16 contador=1;
   signed int columnasRestantes=0;//columnas que aún quedan 
   //por visualizar del caracterEntrante   
   int zonaTemporal[2][6]={0,0,0,0,0,0,0,0,0,0,0,0};//aquí se monta lo que se va a visualizan 
   //antes de pasárselo a *cara
   //si el bit más significativo es 1 el avance dentro de la animación es hacia
   //la derecha, y si es 0 el avance es hacia la izquierda (animaciones yo-yo).
   //Para que una columna sea animada, siguientePropietarioColumna debe contener
   //un valor distinto de 255
   int1 indiceZonaTemporalActiva=0;
   int1 incluirEspacioSufijo=1; 
   int1 actualizarVisualizacion=0;
   int1 mostrarInstantaneamente=0;
   int1 stopActivado=0;
   int1 siguienteCaracterEsAnimado=0;
   int1 sentidoDeAvance;
   int* caracterEntrante;//puntero al carácter entrante
   int longitudCaracterEntrante;   
   int posicionCaracterActual;//posición en la EEPROM del último carácter
   //leído   
   int propietarioActualColumna[6][2]={255,1,255,1,255,1,255,1,255,1,255,1};//en una animación, posición en la eeprom 
   //e índice de la columna dentro del carácter
   //del siguiente caracter que ocupará cada columna de zonaTemporal
   unsigned int longitudMensaje;
   //Apagar ojos
   output_low(PIN_C1);
   output_low(PIN_C2);
   if(salirConSoplido){
      enable_interrupts(INT_AD); 
      clear_interrupt(INT_AD);
      conversorOcupado=1;
      read_adc(ADC_START_ONLY);
   }
   if (tipo){              
      if(parametro>9){
         write_eeprom(7,((int)(parametro/10)));   
         delay_ms(20);                  
      }else{
         write_eeprom(7,250);         
         delay_ms(20);
      }
      write_eeprom(8,parametro-((int)(parametro/10))*10);         
      delay_ms(20);
      parametro=6; 
   }
   longitudMensaje=read_eeprom(parametro);   
   posicionCaracterActual=parametro;
   do{
      contador++;
      //Actualizar animación
      if(contador % ((int16)(VELOCIDAD_TEXTO/PROPORCION_ANIMACION_AVANCE))==0){
         actualizarVisualizacion=1;
         for(i=0;i<6;i++){
            j=read_eeprom(propietarioActualColumna[i][0]);            
            if(j!=255){//es una columna animada
               if(zonaTemporal[indiceZonaTemporalActiva][i]>128){
                  sentidoDeAvance=1;
               }else{
                  sentidoDeAvance=0;
               }               
               j=((zonaTemporal[indiceZonaTemporalActiva][i])<128?read_eeprom(propietarioActualColumna[i][0]-1):read_eeprom(propietarioActualColumna[i][0]+1));            
               switch(j){
                  case 251: //animacion yo-yo                         
                        if (sentidoDeAvance){//Va hacia la derecha                           
                           propietarioActualColumna[i][0]-=1;                           
                        }else{//va hacia la izquierda
                           propietarioActualColumna[i][0]+=1;
                        }
                        sentidoDeAvance=!sentidoDeAvance;
                     break;
                  case 252: //animacion diente de sierra                  
                     while(read_eeprom(propietarioActualColumna[i][0])!=252){
                        propietarioActualColumna[i][0]--;
                     }
                     break;
                  default:                  
                     if(sentidoDeAvance){
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]+1;
                     }else{
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]-1;
                     }
               }
               //Actualizar columnas en zona temporal
               //Cuidadito con el bit más significativo para mantener el sentido
               //de la animación
               j=(caracter[read_eeprom(propietarioActualColumna[i][0])])[propietarioActualColumna[i][1]];
               if(sentidoDeAvance){
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j+128;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }
               }else{
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j-128;
                  }                  
               }
            }         
         }         
      }
      //Actualizar avance
      if(contador>=VELOCIDAD_TEXTO){ 
         if(!stopActivado){
            actualizarVisualizacion=1;         
            if(columnasRestantes==0){
               if(longitudMensaje>0){
                  longitudMensaje--;
                  posicionCaracterActual++;
                  j=read_eeprom(posicionCaracterActual);
                  if(j>=240){
                     //gestión de caracteres reservados
                     switch (j){
                        case 247:
                           mostrarInstantaneamente=1;
                           stopActivado=1;
                           continue;
                           break;
                        case 248:
                           longitudMensaje=read_eeprom(parametro);   
                           posicionCaracterActual=parametro;
                           continue;
                           break;
                        case 249:                  
                           incluirEspacioSufijo=0;
                           continue;
                           break;
                        case 250:                                                      
                           continue;
                           break;
                        case 251:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 252:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 253:
                           contador=1;
                           continue;
                           break;
                        case 254:
                           longitudMensaje=0;
                           stopActivado=1;
                           continue;
                           break;                  
                     }
                  }else{                  
                     caracterEntrante=caracter[j];
                     columnasRestantes=0;
                     //Averiguar el número de columnas del carácter                        
                     while(!((caracterEntrante[columnasRestantes])&128)){
                        columnasRestantes++;               
                     };
                     columnasRestantes++;
                     longitudCaracterEntrante=columnasRestantes;
                  }                       
               }else{ 
                  if(salirConSoplido){
                     disable_interrupts(INT_AD);       
                  }
                  return;               
               }
            }
            if(columnasRestantes>0){
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               } 
               if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes];               
               }else{
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes]-128;                                 
                  //Para evitar interferencias con el sentido de la animación
               }
               if(siguienteCaracterEsAnimado){ 
                  propietarioActualColumna[5][1]=longitudCaracterEntrante-columnasRestantes;
                  if(columnasRestantes==longitudCaracterEntrante){
                     propietarioActualColumna[5][0]=posicionCaracterActual;                  
                  }else{
                     propietarioActualColumna[5][0]=propietarioActualColumna[4][0];                  
                  }
                  if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                     zonaTemporal[indiceZonaTemporalActiva][5]=(caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]];               
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][5]=((caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]])-128;
                     //Para evitar interferencias con el sentido de la animación
                  }                                    
                  //Se debe sumar 128 si la animación está actualmente
                  //avanzando hacia la derecha, es decir, si la columna entrante
                  //es la primera de la animación (todas las animaciones comienzan
                  //hacia la derecha), o si la columna entrante es posterior a la
                  //primera y la columna anterior es >=128
                  //No puede haber caracteres animados de una sola columna
                  if(propietarioActualColumna[5][1]==0){
                     zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                  }else{
                     if(zonaTemporal[indiceZonaTemporalActiva][4]>=128){
                        zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                     }
                  }
               }else{
                  propietarioActualColumna[5][0]=255;
               }
               contador=1;
               columnasRestantes--;    
            }
            if(columnasRestantes==-1){
               columnasRestantes=0;
               incluirEspacioSufijo=0;
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               }
               zonaTemporal[indiceZonaTemporalActiva][5]=0; 
               propietarioActualColumna[5][0]=255;
               contador=1;
            }
            if(columnasRestantes==0){
               if (incluirEspacioSufijo==1){
                  columnasRestantes=-1;
               }else{
                  if(siguienteCaracterEsAnimado){                        
                     siguienteCaracterEsAnimado=0;                     
                     //Avanzar posicionCaracterActual
                     while(read_eeprom(posicionCaracterActual)!=251 && read_eeprom(posicionCaracterActual)!=252){                        
                        posicionCaracterActual++;
                     }
                  }                  
                  incluirEspacioSufijo=1;
               }
            }         
         }else{
            contador=1;
            if(mostrarInstantaneamente){
               stopActivado=0;
               mostrarInstantaneamente=0;
               posicionCaracterActual++;
               i=read_eeprom(posicionCaracterActual);
               caracterEntrante=caracter[i];
               for(j=0;j<6;j++){              
                  zonaTemporal[indiceZonaTemporalActiva][j]=caracterEntrante[j];
                  if(caracterEntrante[j]>=128){
                     zonaTemporal[indiceZonaTemporalActiva][j]-=128;
                  }
                  propietarioActualColumna[j][0]=255;
               }
            }
         }
      }
      //Actualizar visualizacion
      if (actualizarVisualizacion){
         cara=zonaTemporal[indiceZonaTemporalActiva];
         while(cara!=caraEnVisualizacion){
         }
         actualizarVisualizacion=0;         
         indiceZonaTemporalActiva=!indiceZonaTemporalActiva;            
         for(j=0;j<6;j++){
            zonaTemporal[indiceZonaTemporalActiva][j]=zonaTemporal[!indiceZonaTemporalActiva][j];
         }
      }
      
      //¿Detectar soplido?            
      if(salirConSoplido){         
         if(!salirSoloFinal || (salirSoloFinal && longitudMensaje==0 && columnasRestantes==0)){
            if(!conversorOcupado){
               conversorOcupado=1;
               j = read_adc(ADC_READ_ONLY);               
               read_adc(ADC_START_ONLY);
               if(atenuacionUmbralSoplido){
                 j+=30;
               }
               if (j>UMBRAL_SOPLIDO){
                  disable_interrupts(INT_AD);
                  return;
               }         
            }         
         }
      }
      //Detectar salida
      if(modoFuncionamiento){
         return;
      }
      //Detectar reset
      if(resetear){
         j=read_eeprom(1);
         write_eeprom(0,j);
         delay_ms(40);      
         reset_cpu();
      }
   }while(true);   
}
void main() {      
   unsigned int8 entradausb;
   unsigned int8 value, max;
   int comodin, comodin2;
   int16 comodin3, comodin4;
   int16 ciclosParaDormirse=UMBRAL_DORMIRSE;
   int modoCara=0;   
   unsigned int8 supremo=80;
   signed int caraActiva=0;   
   signed int8 acumuladorParpadeo;
   unsigned int32 periodo, muestra;     
   int bostezo[5][6]={0,8,40,104,8,0,0,8,44,108,8,0,0,12,42,106,12,0,0,14,41,105,14,0,0,15,41,105,15,0};  
         
   //caras del modo nariz aguileña
   int cara1[6]={0,4,108,44,4,0};                                       
   int cara2[6]={0,4,110,46,4};                                        
   int cara3[6]={0,6,106,42,6,0};   
   int cara4[6]={0,7,105,41,7,0};                    
   int cara5[6]={0,14,105,41,14,0};                                        
   int cara6[6]={12,10,105,41,10,12};                                    
   int cara7[6]={14,9,105,41,9,14};                                      
   int cara8[6]={15,9,105,41,9,15};                    
   //caras del modo nariz chata
   int cara9[6]={0,8,88,88,8,0};
   int cara10[6]={0,8,84,84,8,0};
   int cara11[6]={0,12,82,82,12,0};
   int cara12[6]={0,14,81,81,14,0};
   int cara13[6]={0,30,81,81,30,0};
   int cara14[6]={12,18,81,81,18,12};
   int cara15[6]={14,17,81,81,17,14};
   int cara16[6]={31,17,81,81,17,31};
   //caras del modo sin nariz
   int cara17[6]={8,8,8,8,8,8};
   int cara18[6]={28,20,20,20,20,28};
   int cara19[6]={62,34,34,34,34,62};
   int cara20[6]={127,65,65,65,65,127};
   //caras del modo luciano
   int cara21[6]={0,0,0,0,0,0};
   int cara22[6]={0,1,1,1,1,0};
   int cara23[6]={1,2,2,2,2,1};
   int cara24[6]={3,4,5,4,5,3};
   int cara25[6]={7,8,10,9,10,7};
   int cara26[6]={15,16,20,18,20,15};
   int cara27[6]={30,33,41,37,41,30};
   int cara28[6]={60,66,82,74,82,60};
   int const *caras[4][8]={cara1,cara2,cara3,cara4,cara5,cara6,cara7,cara8,
                           cara9,cara10,cara11,cara12,cara13,cara14,cara15,cara16,
                           cara17,cara17,cara18,cara18,cara19,cara19,cara20,cara20,
                           cara21,cara22,cara23,cara24,cara25,cara26,cara27,cara28};
                           
                           
   if(!input(PIN_B1)){
      usb_cdc_init();
      usb_init();
      output_low(PIN_C1);
      output_high(PIN_C2);
      while(!usb_cdc_connected()) {      
         delay_ms(200);
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);
      }
      do{
         usb_task();     
         if (usb_enumerated()) {
            printf(usb_cdc_putc, "PICTENGU");
            break;
         }
      }while (TRUE); 
      //Enviar contenido eeprom           
      output_high(PIN_C1);
      output_high(PIN_C2);
      entradausb=get_int_usb();         
      if(entradausb==246){
         delay_ms(1000);
         for(comodin3=0;comodin3<=255;comodin3++){             
            value=read_eeprom(comodin3);
            delay_ms(20);                     
            printf(usb_cdc_putc,"%c",value);      
         }
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);                   
      }
      comodin3=0;
      do{
         usb_task();
         if(usb_enumerated()){
            entradausb=get_int_usb(); 
            if(entradausb!=246){
               write_eeprom(comodin3,entradausb);
               delay_ms(20);  
               comodin3++;
            }else{
               break;
            }
         }
      }while(true);       
   }     
   
   setup_adc_ports(PIN_B0);
   setup_adc(ADC_CLOCK_DIV_64 ); 
   set_adc_channel(12);
   ext_int_edge(1,H_TO_L);
   setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
   setup_timer_0(RTCC_8_BIT|RTCC_DIV_128);
   set_timer0(PRECARGA_TIMER);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_AD);   
   clear_interrupt(INT_AD);    
   enable_interrupts(INT_EXT1);   
   clear_interrupt(INT_EXT1);
   enable_interrupts(INT_TIMER1);   
   clear_interrupt(INT_TIMER1);
   enable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT1);
        
   columnaActual=5;
   output_low(PIN_C1);
   output_low(PIN_C2);
   
   //Modo 1: dormido
   cara=bostezo[0];
   caraEnVisualizacion=cara;
   
   
   value=0;
   conversorOcupado=1;
   read_adc(ADC_START_ONLY);   
   while(value<UMBRAL_SOPLIDO-30){
      if(!conversorOcupado){
         conversorOcupado=1;
         value = read_adc(ADC_READ_ONLY);
         read_adc(ADC_START_ONLY);         
      }
   }   
   disable_interrupts(INT_AD);       
   
   //Modo 2: despertar: abre un ojo, luego el otro, luego bosteza
   //y pestañea 3 veces consecutivas
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   set_pwm2_duty(0);
   for(comodin=0;comodin<40;comodin++){        
      set_pwm1_duty(comodin);      
      delay_ms(30);
   }
   for(comodin=0;comodin<40;comodin++){             
      set_pwm2_duty(comodin);
      delay_ms(30);
   }   
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);
   output_low(PIN_C1);
   output_low(PIN_C2);
   for (comodin=0;comodin<5;comodin++){
      cara=bostezo[comodin];
      delay_ms(150);
   }
   delay_ms(1000);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   for (comodin=4;comodin>0;comodin--){//Con >= falla ¿por qué?
      cara=bostezo[comodin];   
      set_pwm1_duty((4-comodin)*10); 
      set_pwm2_duty((4-comodin)*10); 
      delay_ms(150);
   }
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);   
   for(comodin=1;comodin<=3;comodin++){
      output_low(PIN_C1);
      output_low(PIN_C2);
      delay_ms(300);
      output_high(PIN_C1);
      output_high(PIN_C2);
      delay_ms(300);
   }
   //Si en el primer byte de la memoria hay un valor distinto de 00...
   //comienza el juego del apagado de velas...
   //en caso contrario salta directamente al modo 3   
   comodin=read_eeprom(0);
   delay_ms(20);
   if(comodin!=0){
      write_eeprom(0,0);
      delay_ms(20);
      write_eeprom(1,comodin);
      delay_ms(20);      
      mostrarTexto(0,19,0,0,0,0);
      for(comodin2=1;comodin2<=comodin;comodin2++){         
         mostrarTexto(1,comodin2,1,1,0,1);
         cara=caracter66;
         delay_ms(500);
      }      
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
   }
   
   //Modo 3: Wilson
   modoFuncionamiento=1;
   output_high(PIN_C1);
   output_high(PIN_C2);  
   cara=cara1;
   caraEnVisualizacion=cara1;
   acumuladorParpadeo=0; 
   muestra=0;
   periodo=VELOCIDAD_GESTICULACION;   
   max=0;   
   enable_interrupts(INT_AD); 
   clear_interrupt(INT_AD);
   enable_interrupts(INT_EXT1);
   clear_interrupt(INT_EXT1);    

   conversorOcupado=1;
   read_adc(ADC_START_ONLY);
   
   do{
      if(modoFuncionamiento){      
         muestra++;
         if(!conversorOcupado){
            conversorOcupado=1;
            value = read_adc(ADC_READ_ONLY);
            read_adc(ADC_START_ONLY);            
            if(value>max){
               max=value;
            }
         }
         if(muestra==periodo){
            if(acumuladorParpadeo>0){
               output_high(PIN_C1);
               output_high(PIN_C2);
            }
            if(max>UMBRAL_SOPLIDO){//Soplido
               cara=cara21;
               if (modoCara<3){
                  modoCara++;
               }else{
                  modoCara=0;
               }
               output_low(PIN_C1);
               output_low(PIN_C2);
               for(comodin2=7;comodin2>0;comodin2--){
                  cara=caras[modoCara][comodin2];
                  delay_ms(100);
               }
               output_high(PIN_C1);
               output_high(PIN_C2);
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>supremo){
               caraActiva=7;
               acumuladorParpadeo+=8;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)6/7*supremo){
               caraActiva=6;                  
               acumuladorParpadeo+=7;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)5/7*supremo){
               caraActiva=5;
               acumuladorParpadeo+=6;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)4/7*supremo){
               caraActiva=4;
               acumuladorParpadeo+=5;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)3/7*supremo){
               caraActiva=3;
               acumuladorParpadeo+=4;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)2/7*supremo){
               caraActiva=2;
               acumuladorParpadeo+=3;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)1/7*supremo){
               caraActiva=1;
               acumuladorParpadeo+=2;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else{
               caraActiva=0;
               acumuladorParpadeo+=1;
               ciclosParaDormirse--;
            }

            cara=caras[modoCara][caraActiva];
            if(max>supremo+UMBRAL_AUDICION){
               supremo=max-UMBRAL_AUDICION;
            }else{
               if(supremo>7*UMBRAL_AUDICION){
                  supremo--;
               }
            }
            if(acumuladorParpadeo>=UMBRAL_PARPADEO){
               output_low(PIN_C1);
               output_low(PIN_C2);
               acumuladorParpadeo=-1;
            }
            //printf(usb_cdc_putc, "\r\nSupremo=%6.0w",supremo );
            //printf(usb_cdc_putc, "\r\nCociente=%6.4f",(float)1/7*supremo );
            muestra=0;
            max=0;            
         }            
      }else{
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
      }
      if(resetear||ciclosParaDormirse==0){
         if(ciclosParaDormirse){
            comodin=read_eeprom(1);
            write_eeprom(0,comodin);
            delay_ms(40);     
         }
         reset_cpu();
      }
   }while (TRUE);      
}
```
lo que claro, si es aqui no se donde tendria que ponerlo..
saludos


----------



## soopy_46 (Sep 27, 2010)

vale, ahora ya se que es para el pic, por lo que he ido leyendo.. lo que no se si necesitaria algo mas para el ordenador, si alguien me puedecontestar porfavor, le estaria super agradecido ya que como he dicho esto lo tengo que tener para el lunes como mucho. gracias de antemano


----------



## soopy_46 (Sep 27, 2010)

vale muchas gracias por contestar..
que programa me aconsejarian para poder programar en C y poder juntar las programaciones adjuntas arriba? ES ESO LO QUE TENGO QUE HACER? es algo tan simple como eso.. no pido mas..
esque quizas vaya a comprar el conversor y luego resulte que el programa no deje entrar..
ayudadme porfavor... tengo hasta el dia 4 de octubre

tambien me gustaria que me dijerais si hay algun error porque lo estoy intentando pasar a .hex con el PCWHD pero me salen muchos errores en los siguientes codigos:


```
int const * caracter[84] ={caracter0,caracter1,caracter2,caracter3,caracter4,caracter5,
                    caracter6,caracter7,caracter8,caracter9,caracter10,caracter11,
                    caracter12,caracter13,caracter14,caracter15,caracter16,caracter17,
                    caracter18,caracter19,caracter20,caracter21,caracter22,caracter23,
                    caracter24,caracter25,caracter26,caracter27,caracter28,caracter29,
                    caracter30,caracter31,caracter32,caracter33,caracter34,caracter35,
                    caracter36,caracter37,caracter38,caracter39,caracter40,caracter41,
                    caracter42,caracter43,caracter44,caracter45,caracter46,caracter47,
                    caracter48,caracter49,caracter50,caracter51,caracter52,caracter53,
                    caracter54,caracter55,caracter56,caracter57,caracter58,caracter59,
                    caracter60,caracter61,caracter62,caracter63,caracter64,caracter65,
                    caracter66,caracter67,caracter68,caracter69,caracter70,caracter71,
                    caracter72,caracter73,caracter74,caracter75,caracter76,caracter77,
                    caracter78,caracter79,caracter80,caracter81,caracter82,caracter83};
```
 

```
void int mostrarTexto (int1 tipo, int parametro, int1 salirConSoplido, int1 atenuacionUmbralSoplido,int1 salirConBoton, int1 salirSoloFinal){
```
gracias de verdad, recordad que no se de programacion en C solo se basic  y esto no se como solucionarlo...


----------



## seaarg (Sep 27, 2010)

Le diste una leida a este tema?
https://www.forosdeelectronica.com/f24/control-dispositivos-traves-modulo-usb-pic18f2550-17458/

Quiza alli hay algo que te sirva. Es todo lo que te podria decir al respecto, espero que te ayude en algo.


----------



## Soopy46 (Sep 28, 2010)

gracias por contestarme y siento por haberme puesto como me puse pero no me conseguia conectar el pic y ya no sabia que mas hacer...por cierto alguien sabria decirme cuales son los errores que me daba el programa y que programa me aconsejariais que usara..?graciassalu2


----------



## seaarg (Sep 28, 2010)

void int mostrarTexto

La function o no devuelve nada (void) o devuelve int, no pueden ser ambas.

Lo de arriba puede ser que caracter0,caracter1 no sean constantes declaradas y como variables sean inexistentes.

Si no pones aqui que errores te da la compilacion va a ser dificil que te podamos ayudar


----------



## soopy_46 (Sep 28, 2010)

buenas, alguien me podrian decir otro compilador? porque quizas sea problema de que algunas variables no las reconozca, poorque esta programacion ya la tengo en .hex y no da problemas excepto en lo dle usb por eso quiero cambiarlo y ahora no puedo..
luego mas tarde digo los errores que me da


----------



## soopy_46 (Sep 28, 2010)

Recuerdo la programacion en el pic18F2455


```
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// PIC_Tengu_v1.c                                                  ////
////                                                                 ////
//// Autor: jfmateos2                                                ////
//// Contacto: jfmateos@lycos.es                                     ////
//// Madrid, abril 2008                                              ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////

#include <18F2455.h>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN, CCP2C1
#device ADC=8
#use delay(clock=48000000)
#include <stdlib.h>
#include ".\include\usb_cdc.h"
#rom int8 0xf00000={5,0,0,0,0,0,//0-->5 (edad,copiaEdad,usos futuros,...)
12,250,1,249,251,60,61,62,63,64,65,251,254,//6-->18 (animacion: edad-vela)
29,29,25,26,21,10,48,26,10,28,10,48,10,26,10,16,10,28,48,21,10,29,48,32,14,21,10,29,48,48,//19-->48
202,17,10,35,48,27,31,18,14,23,48,26,18,14,23,29,10,48,27,31,14,48,29,25,21,25,48,31,23,48,21,
25,12,25,48,12,14,21,14,11,28,10,28,18,10,48,27,31,14,48,12,31,22,26,21,14,48,10,24,25,29,
38,48,35,48,27,31,14,48,17,10,35,48,27,31,14,48,10,26,28,25,32,14,12,17,10,28,48,26,25,28,
27,31,14,48,23,31,23,12,10,48,29,14,48,32,25,21,32,14,28,10,48,10,48,29,14,28,48,30,10,23,
48,19,25,32,14,23,38,48,10,31,23,27,31,14,48,30,10,22,26,25,12,25,48,23,31,23,12,10,48,29,
14,48,17,10,48,29,18,13,25,48,30,10,23,48,32,18,14,19,25,38,48,10,31,23,48,10,29,18,38,48,
15,14,21,18,36,48,12,31,22,26,21,14,10,24,25,29,48,10,21,22,31,37}//49-->251

#define PRECARGA_TIMER 0
#define UMBRAL_PARPADEO 100 //Max=128.Está afectado por VELOCIDAD_GESTICULACION
#define VELOCIDAD_GESTICULACION 20000
#define UMBRAL_SOPLIDO 90
#define VELOCIDAD_TEXTO 4500
#define PROPORCION_ANIMACION_AVANCE 2 
#define UMBRAL_AUDICION 3
#define UMBRAL_DORMIRSE 5000

unsigned int8 i;
unsigned int8  columnaActual=5;
int1 conversorOcupado=0;
int1 modoFuncionamiento;
int1 botonPulsado=0;
int1 resetear=0;
int16 ciclosTimer1;

int filas[7]={PIN_C0,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7};
int *cara, *caraEnVisualizacion;

//Atención, la longitud de cada array siguiente está codificada en el propio
//array, porque como cada columna sólo utiliza 7 bits he aprovechado
//el octavo para codificar la longitud.
//Numeros
int caracter0[3]={31,17,31+128};//0
int caracter1[3]={9,31,1+128};//1
int caracter2[3]={19,21,9+128};//2
int caracter3[3]={17,21,26+128};//3
int caracter4[3]={6,10,31+128};//4
int caracter5[3]={29,21,18+128};//5
int caracter6[3]={15,21,22+128};//6
int caracter7[3]={16,23,24+128};//7
int caracter8[3]={31,21,31+128};//8
int caracter9[3]={28,20,31+128};//9
//Letras mayúsculas
int caracter10[3]={15,20,15+128};//A
int caracter11[3]={31,21,10+128};//B
int caracter12[3]={14,17,10+128};//C
int caracter13[3]={31,17,14+128};//D
int caracter14[3]={31,21,17+128};//E
int caracter15[3]={31,20,16+128};//F
int caracter16[3]={14,17,23+128};//G
int caracter17[3]={31,4,31+128};//H
int caracter18[3]={17,31,17+128};//I
int caracter19[3]={2,17,31+128};//J
int caracter20[3]={31,12,19+128};//K
int caracter21[3]={31,1,1+128};//L
int caracter22[5]={31,8,4,8,31+128};//M   
int caracter23[5]={31,8,4,2,31+128};//N
int caracter24[5]={31,72,68,66,31+128};//Ñ
int caracter25[3]={14,17,14+128};//O
int caracter26[3]={31,20,8+128};//P
int caracter27[4]={31,17,19,31+128};//Q
int caracter28[3]={31,20,11+128};//R
int caracter29[3]={9,21,18+128};//S
int caracter30[3]={16,31,16+128};//T
int caracter31[3]={31,1,31+128};//U   
int caracter32[3]={30,3,30+128};//V
int caracter33[5]={31,2,4,2,31+128};//W
int caracter34[3]={27,4,27+128};//X
int caracter35[3]={24,7,24+128};//Y
int caracter36[3]={19,21,25+128};//Z
//Signos de puntuacion
int caracter37[2]={3,3+128};//.
int caracter38[2]={1,6+128};//,
int caracter39[1]={10+128};//:
int caracter40[2]={1,10+128};//;
int caracter41[1]={95+128};//¡
int caracter42[1]={125+128};//!
int caracter43[3]={14,81,2+128};//¿
int caracter44[3]={32,69,56+128};//?
int caracter45[2]={16,96+128};//´
int caracter46[2]={62,65+128};//(
int caracter47[2]={65,62+128};//)
int caracter48[2]={0,0+128};// (espacio)
//Caracteres especiales
int caracter49[5]={2,21,23,17,14+128};//@
int caracter50[3]={50,107,38+128};//$
int caracter51[5]={20,62,85,65,34+128};//€
//Signos matemáticos
int caracter52[3]={4,14,4+128};//+
int caracter53[3]={4,4,4+128};//-
int caracter54[3]={10,4,10+128};//*
int caracter55[3]={3,4,24+128};///
int caracter56[3]={19,4,25+128};//%
int caracter57[3]={4,10,17+128};//<
int caracter58[3]={17,10,4+128};//>
int caracter59[3]={10,10,10+128};//=
//Velas
int caracter60[6]={3,9,29,61,57,3+128};
int caracter61[6]={3,9,29,61,121,3+128};
int caracter62[6]={3,9,61,125,25,3+128};
int caracter63[6]={3,25,125,61,9,3+128};
int caracter64[6]={3,121,61,29,9,3+128};
int caracter65[6]={3,57,61,29,9,3+128};
int caracter66[6]={3,1,1,1,1,3+128};//vela apagada
//French
int caracter67[3]={47,74,15+128};//Á
int caracter68[3]={15,74,47+128};//À
int caracter69[3]={47,74,47+128};//Â
int caracter70[3]={63,85,17+128};//É
int caracter71[3]={31,85,49+128};//È
int caracter72[3]={63,85,49+128};//Ê
int caracter73[3]={95,21,81+128};//Ë
int caracter74[3]={41,79,9+128};//Í
int caracter75[3]={41,79,41+128};//Î
int caracter76[3]={81,31,81+128};//Ï
int caracter77[3]={38,73,6+128};//Ó
int caracter78[3]={38,73,38+128};//Ô
int caracter79[3]={47,65,15+128};//Ú
int caracter80[3]={15,47,65+128};//Ù
int caracter81[3]={47,65,47+128};//Û
int caracter82[3]={95,1,95+128};//Ü
int caracter83[3]={125,70,68+128};//Ç


//Caracteres reservados a partir del 240 (incluido)
//caracter246 -->Final de cadena transmitida por USB
//caracter247 -->Visualización inmediata del caracter siguiente (sin arrastre)
//caracter248 -->Volver al principio
//caracter249 -->Quitar espacio sufijo en caracter siguiente
//caracter250 -->Saltar a siguiente caracter
//caracter251 -->Inicio y final de animacion yo-yo
//caracter252 -->Inicio y final de animacion diente de sierra
//caracter253 -->Pausa corta/saltarse un avance
//caracter254 -->Stop
//caracter255 -->Nulo (se usa en animaciones)

int const * caracter[84]={caracter0,caracter1,caracter2,caracter3,caracter4,caracter5,
                    caracter6,caracter7,caracter8,caracter9,caracter10,caracter11,
                    caracter12,caracter13,caracter14,caracter15,caracter16,caracter17,
                    caracter18,caracter19,caracter20,caracter21,caracter22,caracter23,
                    caracter24,caracter25,caracter26,caracter27,caracter28,caracter29,
                    caracter30,caracter31,caracter32,caracter33,caracter34,caracter35,
                    caracter36,caracter37,caracter38,caracter39,caracter40,caracter41,
                    caracter42,caracter43,caracter44,caracter45,caracter46,caracter47,
                    caracter48,caracter49,caracter50,caracter51,caracter52,caracter53,
                    caracter54,caracter55,caracter56,caracter57,caracter58,caracter59,
                    caracter60,caracter61,caracter62,caracter63,caracter64,caracter65,
                    caracter66,caracter67,caracter68,caracter69,caracter70,caracter71,
                    caracter72,caracter73,caracter74,caracter75,caracter76,caracter77,
                    caracter78,caracter79,caracter80,caracter81,caracter82,caracter83};

#INT_EXT1
void int1_handler(){
   if(!botonPulsado){
      botonPulsado=1;
      modoFuncionamiento=!modoFuncionamiento;
      ciclosTimer1=400;               
      ext_int_edge(1,L_TO_H);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
      set_timer1(0);
   }else{      
      botonPulsado=0;      
      setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
      ext_int_edge(1,H_TO_L);     
      
   }   
}

#INT_TIMER1
void timer1_handler(){   
   if(--ciclosTimer1==0){         
      resetear=1;
   }   
}

#INT_AD
void ad_handler(){
   conversorOcupado=0;
}

#INT_TIMER0
void tmr_handler() {    
      //Apagar
      output_a(0);
      //Cambiar de columna
      if (columnaActual==5){
         columnaActual=0;
         if(caraEnVisualizacion!=cara){
            caraEnVisualizacion=cara;
         }
      }else{
         columnaActual++;
      } 
      //Preparar filas
      for(i=0;i<7;i++){
         output_bit(filas[i],*(caraEnVisualizacion+columnaActual)&(64>>i));
      }
      //Encender columna
      output_a(1<<columnaActual);      
      set_timer0(PRECARGA_TIMER);
}

void int mostrarTexto (int1 tipo, int parametro, int1 salirConSoplido, int1 atenuacionUmbralSoplido,int1 salirConBoton, int1 salirSoloFinal){
   unsigned int i,j;
   int16 contador=1;
   signed int columnasRestantes=0;//columnas que aún quedan 
   //por visualizar del caracterEntrante   
   int zonaTemporal[2][6]={0,0,0,0,0,0,0,0,0,0,0,0};//aquí se monta lo que se va a visualizan 
   //antes de pasárselo a *cara
   //si el bit más significativo es 1 el avance dentro de la animación es hacia
   //la derecha, y si es 0 el avance es hacia la izquierda (animaciones yo-yo).
   //Para que una columna sea animada, siguientePropietarioColumna debe contener
   //un valor distinto de 255
   int1 indiceZonaTemporalActiva=0;
   int1 incluirEspacioSufijo=1; 
   int1 actualizarVisualizacion=0;
   int1 mostrarInstantaneamente=0;
   int1 stopActivado=0;
   int1 siguienteCaracterEsAnimado=0;
   int1 sentidoDeAvance;
   int* caracterEntrante;//puntero al carácter entrante
   int longitudCaracterEntrante;   
   int posicionCaracterActual;//posición en la EEPROM del último carácter
   //leído   
   int propietarioActualColumna[6][2]={255,1,255,1,255,1,255,1,255,1,255,1};//en una animación, posición en la eeprom 
   //e índice de la columna dentro del carácter
   //del siguiente caracter que ocupará cada columna de zonaTemporal
   unsigned int longitudMensaje;
   //Apagar ojos
   output_low(PIN_C1);
   output_low(PIN_C2);
   if(salirConSoplido){
      enable_interrupts(INT_AD); 
      clear_interrupt(INT_AD);
      conversorOcupado=1;
      read_adc(ADC_START_ONLY);
   }
   if (tipo){              
      if(parametro>9){
         write_eeprom(7,((int)(parametro/10)));   
         delay_ms(20);                  
      }else{
         write_eeprom(7,250);         
         delay_ms(20);
      }
      write_eeprom(8,parametro-((int)(parametro/10))*10);         
      delay_ms(20);
      parametro=6; 
   }
   longitudMensaje=read_eeprom(parametro);   
   posicionCaracterActual=parametro;
   do{
      contador++;
      //Actualizar animación
      if(contador % ((int16)(VELOCIDAD_TEXTO/PROPORCION_ANIMACION_AVANCE))==0){
         actualizarVisualizacion=1;
         for(i=0;i<6;i++){
            j=read_eeprom(propietarioActualColumna[i][0]);            
            if(j!=255){//es una columna animada
               if(zonaTemporal[indiceZonaTemporalActiva][i]>128){
                  sentidoDeAvance=1;
               }else{
                  sentidoDeAvance=0;
               }               
               j=((zonaTemporal[indiceZonaTemporalActiva][i])<128?read_eeprom(propietarioActualColumna[i][0]-1):read_eeprom(propietarioActualColumna[i][0]+1));            
               switch(j){
                  case 251: //animacion yo-yo                         
                        if (sentidoDeAvance){//Va hacia la derecha                           
                           propietarioActualColumna[i][0]-=1;                           
                        }else{//va hacia la izquierda
                           propietarioActualColumna[i][0]+=1;
                        }
                        sentidoDeAvance=!sentidoDeAvance;
                     break;
                  case 252: //animacion diente de sierra                  
                     while(read_eeprom(propietarioActualColumna[i][0])!=252){
                        propietarioActualColumna[i][0]--;
                     }
                     break;
                  default:                  
                     if(sentidoDeAvance){
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]+1;
                     }else{
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]-1;
                     }
               }
               //Actualizar columnas en zona temporal
               //Cuidadito con el bit más significativo para mantener el sentido
               //de la animación
               j=(caracter[read_eeprom(propietarioActualColumna[i][0])])[propietarioActualColumna[i][1]];
               if(sentidoDeAvance){
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j+128;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }
               }else{
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j-128;
                  }                  
               }
            }         
         }         
      }
      //Actualizar avance
      if(contador>=VELOCIDAD_TEXTO){ 
         if(!stopActivado){
            actualizarVisualizacion=1;         
            if(columnasRestantes==0){
               if(longitudMensaje>0){
                  longitudMensaje--;
                  posicionCaracterActual++;
                  j=read_eeprom(posicionCaracterActual);
                  if(j>=240){
                     //gestión de caracteres reservados
                     switch (j){
                        case 247:
                           mostrarInstantaneamente=1;
                           stopActivado=1;
                           continue;
                           break;
                        case 248:
                           longitudMensaje=read_eeprom(parametro);   
                           posicionCaracterActual=parametro;
                           continue;
                           break;
                        case 249:                  
                           incluirEspacioSufijo=0;
                           continue;
                           break;
                        case 250:                                                      
                           continue;
                           break;
                        case 251:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 252:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 253:
                           contador=1;
                           continue;
                           break;
                        case 254:
                           longitudMensaje=0;
                           stopActivado=1;
                           continue;
                           break;                  
                     }
                  }else{                  
                     caracterEntrante=caracter[j];
                     columnasRestantes=0;
                     //Averiguar el número de columnas del carácter                        
                     while(!((caracterEntrante[columnasRestantes])&128)){
                        columnasRestantes++;               
                     };
                     columnasRestantes++;
                     longitudCaracterEntrante=columnasRestantes;
                  }                       
               }else{ 
                  if(salirConSoplido){
                     disable_interrupts(INT_AD);       
                  }
                  return;               
               }
            }
            if(columnasRestantes>0){
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               } 
               if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes];               
               }else{
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes]-128;                                 
                  //Para evitar interferencias con el sentido de la animación
               }
               if(siguienteCaracterEsAnimado){ 
                  propietarioActualColumna[5][1]=longitudCaracterEntrante-columnasRestantes;
                  if(columnasRestantes==longitudCaracterEntrante){
                     propietarioActualColumna[5][0]=posicionCaracterActual;                  
                  }else{
                     propietarioActualColumna[5][0]=propietarioActualColumna[4][0];                  
                  }
                  if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                     zonaTemporal[indiceZonaTemporalActiva][5]=(caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]];               
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][5]=((caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]])-128;
                     //Para evitar interferencias con el sentido de la animación
                  }                                    
                  //Se debe sumar 128 si la animación está actualmente
                  //avanzando hacia la derecha, es decir, si la columna entrante
                  //es la primera de la animación (todas las animaciones comienzan
                  //hacia la derecha), o si la columna entrante es posterior a la
                  //primera y la columna anterior es >=128
                  //No puede haber caracteres animados de una sola columna
                  if(propietarioActualColumna[5][1]==0){
                     zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                  }else{
                     if(zonaTemporal[indiceZonaTemporalActiva][4]>=128){
                        zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                     }
                  }
               }else{
                  propietarioActualColumna[5][0]=255;
               }
               contador=1;
               columnasRestantes--;    
            }
            if(columnasRestantes==-1){
               columnasRestantes=0;
               incluirEspacioSufijo=0;
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               }
               zonaTemporal[indiceZonaTemporalActiva][5]=0; 
               propietarioActualColumna[5][0]=255;
               contador=1;
            }
            if(columnasRestantes==0){
               if (incluirEspacioSufijo==1){
                  columnasRestantes=-1;
               }else{
                  if(siguienteCaracterEsAnimado){                        
                     siguienteCaracterEsAnimado=0;                     
                     //Avanzar posicionCaracterActual
                     while(read_eeprom(posicionCaracterActual)!=251 && read_eeprom(posicionCaracterActual)!=252){                        
                        posicionCaracterActual++;
                     }
                  }                  
                  incluirEspacioSufijo=1;
               }
            }         
         }else{
            contador=1;
            if(mostrarInstantaneamente){
               stopActivado=0;
               mostrarInstantaneamente=0;
               posicionCaracterActual++;
               i=read_eeprom(posicionCaracterActual);
               caracterEntrante=caracter[i];
               for(j=0;j<6;j++){              
                  zonaTemporal[indiceZonaTemporalActiva][j]=caracterEntrante[j];
                  if(caracterEntrante[j]>=128){
                     zonaTemporal[indiceZonaTemporalActiva][j]-=128;
                  }
                  propietarioActualColumna[j][0]=255;
               }
            }
         }
      }
      //Actualizar visualizacion
      if (actualizarVisualizacion){
         cara=zonaTemporal[indiceZonaTemporalActiva];
         while(cara!=caraEnVisualizacion){
         }
         actualizarVisualizacion=0;         
         indiceZonaTemporalActiva=!indiceZonaTemporalActiva;            
         for(j=0;j<6;j++){
            zonaTemporal[indiceZonaTemporalActiva][j]=zonaTemporal[!indiceZonaTemporalActiva][j];
         }
      }
      
      //¿Detectar soplido?            
      if(salirConSoplido){         
         if(!salirSoloFinal || (salirSoloFinal && longitudMensaje==0 && columnasRestantes==0)){
            if(!conversorOcupado){
               conversorOcupado=1;
               j = read_adc(ADC_READ_ONLY);               
               read_adc(ADC_START_ONLY);
               if(atenuacionUmbralSoplido){
                 j+=30;
               }
               if (j>UMBRAL_SOPLIDO){
                  disable_interrupts(INT_AD);
                  return;
               }         
            }         
         }
      }
      //Detectar salida
      if(modoFuncionamiento){
         return;
      }
      //Detectar reset
      if(resetear){
         j=read_eeprom(1);
         write_eeprom(0,j);
         delay_ms(40);      
         reset_cpu();
      }
   }while(true);   
}
void main() {      
   unsigned int8 entradausb;
   unsigned int8 value, max;
   int comodin, comodin2;
   int16 comodin3, comodin4;
   int16 ciclosParaDormirse=UMBRAL_DORMIRSE;
   int modoCara=0;   
   unsigned int8 supremo=80;
   signed int caraActiva=0;   
   signed int8 acumuladorParpadeo;
   unsigned int32 periodo, muestra;     
   int bostezo[5][6]={0,8,40,104,8,0,0,8,44,108,8,0,0,12,42,106,12,0,0,14,41,105,14,0,0,15,41,105,15,0};  
         
   //caras del modo nariz aguileña
   int cara1[6]={0,4,108,44,4,0};                                       
   int cara2[6]={0,4,110,46,4};                                        
   int cara3[6]={0,6,106,42,6,0};   
   int cara4[6]={0,7,105,41,7,0};                    
   int cara5[6]={0,14,105,41,14,0};                                        
   int cara6[6]={12,10,105,41,10,12};                                    
   int cara7[6]={14,9,105,41,9,14};                                      
   int cara8[6]={15,9,105,41,9,15};                    
   //caras del modo nariz chata
   int cara9[6]={0,8,88,88,8,0};
   int cara10[6]={0,8,84,84,8,0};
   int cara11[6]={0,12,82,82,12,0};
   int cara12[6]={0,14,81,81,14,0};
   int cara13[6]={0,30,81,81,30,0};
   int cara14[6]={12,18,81,81,18,12};
   int cara15[6]={14,17,81,81,17,14};
   int cara16[6]={31,17,81,81,17,31};
   //caras del modo sin nariz
   int cara17[6]={8,8,8,8,8,8};
   int cara18[6]={28,20,20,20,20,28};
   int cara19[6]={62,34,34,34,34,62};
   int cara20[6]={127,65,65,65,65,127};
   //caras del modo luciano
   int cara21[6]={0,0,0,0,0,0};
   int cara22[6]={0,1,1,1,1,0};
   int cara23[6]={1,2,2,2,2,1};
   int cara24[6]={3,4,5,4,5,3};
   int cara25[6]={7,8,10,9,10,7};
   int cara26[6]={15,16,20,18,20,15};
   int cara27[6]={30,33,41,37,41,30};
   int cara28[6]={60,66,82,74,82,60};
   int const *caras[4][8]={cara1,cara2,cara3,cara4,cara5,cara6,cara7,cara8,
                           cara9,cara10,cara11,cara12,cara13,cara14,cara15,cara16,
                           cara17,cara17,cara18,cara18,cara19,cara19,cara20,cara20,
                           cara21,cara22,cara23,cara24,cara25,cara26,cara27,cara28};
                           
                           
   if(!input(PIN_B1)){
      usb_cdc_init();
      usb_init();
      output_low(PIN_C1);
      output_high(PIN_C2);
      while(!usb_cdc_connected()) {      
         delay_ms(200);
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);
      }
      do{
         usb_task();     
         if (usb_enumerated()) {
            printf(usb_cdc_putc, "PICTENGU");
            break;
         }
      }while (TRUE); 
      //Enviar contenido eeprom           
      output_high(PIN_C1);
      output_high(PIN_C2);
      entradausb=get_int_usb();         
      if(entradausb==246){
         delay_ms(1000);
         for(comodin3=0;comodin3<=255;comodin3++){             
            value=read_eeprom(comodin3);
            delay_ms(20);                     
            printf(usb_cdc_putc,"%c",value);      
         }
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);                   
      }
      comodin3=0;
      do{
         usb_task();
         if(usb_enumerated()){
            entradausb=get_int_usb(); 
            if(entradausb!=246){
               write_eeprom(comodin3,entradausb);
               delay_ms(20);  
               comodin3++;
            }else{
               break;
            }
         }
      }while(true);       
   }     
   
   setup_adc_ports(PIN_B0);
   setup_adc(ADC_CLOCK_DIV_64 ); 
   set_adc_channel(12);
   ext_int_edge(1,H_TO_L);
   setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
   setup_timer_0(RTCC_8_BIT|RTCC_DIV_128);
   set_timer0(PRECARGA_TIMER);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_AD);   
   clear_interrupt(INT_AD);    
   enable_interrupts(INT_EXT1);   
   clear_interrupt(INT_EXT1);
   enable_interrupts(INT_TIMER1);   
   clear_interrupt(INT_TIMER1);
   enable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT1);
        
   columnaActual=5;
   output_low(PIN_C1);
   output_low(PIN_C2);
   
   //Modo 1: dormido
   cara=bostezo[0];
   caraEnVisualizacion=cara;
   
   
   value=0;
   conversorOcupado=1;
   read_adc(ADC_START_ONLY);   
   while(value<UMBRAL_SOPLIDO-30){
      if(!conversorOcupado){
         conversorOcupado=1;
         value = read_adc(ADC_READ_ONLY);
         read_adc(ADC_START_ONLY);         
      }
   }   
   disable_interrupts(INT_AD);       
   
   //Modo 2: despertar: abre un ojo, luego el otro, luego bosteza
   //y pestañea 3 veces consecutivas
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   set_pwm2_duty(0);
   for(comodin=0;comodin<40;comodin++){        
      set_pwm1_duty(comodin);      
      delay_ms(30);
   }
   for(comodin=0;comodin<40;comodin++){             
      set_pwm2_duty(comodin);
      delay_ms(30);
   }   
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);
   output_low(PIN_C1);
   output_low(PIN_C2);
   for (comodin=0;comodin<5;comodin++){
      cara=bostezo[comodin];
      delay_ms(150);
   }
   delay_ms(1000);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   for (comodin=4;comodin>0;comodin--){//Con >= falla ¿por qué?
      cara=bostezo[comodin];   
      set_pwm1_duty((4-comodin)*10); 
      set_pwm2_duty((4-comodin)*10); 
      delay_ms(150);
   }
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);   
   for(comodin=1;comodin<=3;comodin++){
      output_low(PIN_C1);
      output_low(PIN_C2);
      delay_ms(300);
      output_high(PIN_C1);
      output_high(PIN_C2);
      delay_ms(300);
   }
   //Si en el primer byte de la memoria hay un valor distinto de 00...
   //comienza el juego del apagado de velas...
   //en caso contrario salta directamente al modo 3   
   comodin=read_eeprom(0);
   delay_ms(20);
   if(comodin!=0){
      write_eeprom(0,0);
      delay_ms(20);
      write_eeprom(1,comodin);
      delay_ms(20);      
      mostrarTexto(0,19,0,0,0,0);
      for(comodin2=1;comodin2<=comodin;comodin2++){         
         mostrarTexto(1,comodin2,1,1,0,1);
         cara=caracter66;
         delay_ms(500);
      }      
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
   }
   
   //Modo 3: Wilson
   modoFuncionamiento=1;
   output_high(PIN_C1);
   output_high(PIN_C2);  
   cara=cara1;
   caraEnVisualizacion=cara1;
   acumuladorParpadeo=0; 
   muestra=0;
   periodo=VELOCIDAD_GESTICULACION;   
   max=0;   
   enable_interrupts(INT_AD); 
   clear_interrupt(INT_AD);
   enable_interrupts(INT_EXT1);
   clear_interrupt(INT_EXT1);    

   conversorOcupado=1;
   read_adc(ADC_START_ONLY);
   
   do{
      if(modoFuncionamiento){      
         muestra++;
         if(!conversorOcupado){
            conversorOcupado=1;
            value = read_adc(ADC_READ_ONLY);
            read_adc(ADC_START_ONLY);            
            if(value>max){
               max=value;
            }
         }
         if(muestra==periodo){
            if(acumuladorParpadeo>0){
               output_high(PIN_C1);
               output_high(PIN_C2);
            }
            if(max>UMBRAL_SOPLIDO){//Soplido
               cara=cara21;
               if (modoCara<3){
                  modoCara++;
               }else{
                  modoCara=0;
               }
               output_low(PIN_C1);
               output_low(PIN_C2);
               for(comodin2=7;comodin2>0;comodin2--){
                  cara=caras[modoCara][comodin2];
                  delay_ms(100);
               }
               output_high(PIN_C1);
               output_high(PIN_C2);
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>supremo){
               caraActiva=7;
               acumuladorParpadeo+=8;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)6/7*supremo){
               caraActiva=6;                  
               acumuladorParpadeo+=7;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)5/7*supremo){
               caraActiva=5;
               acumuladorParpadeo+=6;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)4/7*supremo){
               caraActiva=4;
               acumuladorParpadeo+=5;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)3/7*supremo){
               caraActiva=3;
               acumuladorParpadeo+=4;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)2/7*supremo){
               caraActiva=2;
               acumuladorParpadeo+=3;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)1/7*supremo){
               caraActiva=1;
               acumuladorParpadeo+=2;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else{
               caraActiva=0;
               acumuladorParpadeo+=1;
               ciclosParaDormirse--;
            }

            cara=caras[modoCara][caraActiva];
            if(max>supremo+UMBRAL_AUDICION){
               supremo=max-UMBRAL_AUDICION;
            }else{
               if(supremo>7*UMBRAL_AUDICION){
                  supremo--;
               }
            }
            if(acumuladorParpadeo>=UMBRAL_PARPADEO){
               output_low(PIN_C1);
               output_low(PIN_C2);
               acumuladorParpadeo=-1;
            }
            //printf(usb_cdc_putc, "\r\nSupremo=%6.0w",supremo );
            //printf(usb_cdc_putc, "\r\nCociente=%6.4f",(float)1/7*supremo );
            muestra=0;
            max=0;            
         }            
      }else{
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
      }
      if(resetear||ciclosParaDormirse==0){
         if(ciclosParaDormirse){
            comodin=read_eeprom(1);
            write_eeprom(0,comodin);
            delay_ms(40);     
         }
         reset_cpu();
      }
   }while (TRUE);      
}
```
 
y los errores que me daba en las instrucciones que he pasado antes son las siguiente:
***Error 28 "PIC_Tengu_v1.c" Line 157(13,14): Expecting an identifier

luego en todos los "caracter" que hay me salta el mismo error y me envia el cursor al principio de la palabra.. el error que me da es el siguiente:
***Error 48 "PIC_Tengu_v1.c" Line 157(27,36: Expecting a (


aun que yo sigo pensando que es el mismo programa, que necesite una extension para entender estos caracteres, igual que con el microcodestudio necesito el PBP242 para que pueda compilar en basic. alguien me puede decir algun programa compilador en CCS C que me pudiera entender toda la programacion?
saludos

Recuerdo la programacion en el pic18F2455


```
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// PIC_Tengu_v1.c                                                  ////
////                                                                 ////
//// Autor: jfmateos2                                                ////
//// Contacto: jfmateos@lycos.es                                     ////
//// Madrid, abril 2008                                              ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////

#include <18F2455.h>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN, CCP2C1
#device ADC=8
#use delay(clock=48000000)
#include <stdlib.h>
#include ".\include\usb_cdc.h"
#rom int8 0xf00000={5,0,0,0,0,0,//0-->5 (edad,copiaEdad,usos futuros,...)
12,250,1,249,251,60,61,62,63,64,65,251,254,//6-->18 (animacion: edad-vela)
29,29,25,26,21,10,48,26,10,28,10,48,10,26,10,16,10,28,48,21,10,29,48,32,14,21,10,29,48,48,//19-->48
202,17,10,35,48,27,31,18,14,23,48,26,18,14,23,29,10,48,27,31,14,48,29,25,21,25,48,31,23,48,21,
25,12,25,48,12,14,21,14,11,28,10,28,18,10,48,27,31,14,48,12,31,22,26,21,14,48,10,24,25,29,
38,48,35,48,27,31,14,48,17,10,35,48,27,31,14,48,10,26,28,25,32,14,12,17,10,28,48,26,25,28,
27,31,14,48,23,31,23,12,10,48,29,14,48,32,25,21,32,14,28,10,48,10,48,29,14,28,48,30,10,23,
48,19,25,32,14,23,38,48,10,31,23,27,31,14,48,30,10,22,26,25,12,25,48,23,31,23,12,10,48,29,
14,48,17,10,48,29,18,13,25,48,30,10,23,48,32,18,14,19,25,38,48,10,31,23,48,10,29,18,38,48,
15,14,21,18,36,48,12,31,22,26,21,14,10,24,25,29,48,10,21,22,31,37}//49-->251

#define PRECARGA_TIMER 0
#define UMBRAL_PARPADEO 100 //Max=128.Está afectado por VELOCIDAD_GESTICULACION
#define VELOCIDAD_GESTICULACION 20000
#define UMBRAL_SOPLIDO 90
#define VELOCIDAD_TEXTO 4500
#define PROPORCION_ANIMACION_AVANCE 2 
#define UMBRAL_AUDICION 3
#define UMBRAL_DORMIRSE 5000

unsigned int8 i;
unsigned int8  columnaActual=5;
int1 conversorOcupado=0;
int1 modoFuncionamiento;
int1 botonPulsado=0;
int1 resetear=0;
int16 ciclosTimer1;

int filas[7]={PIN_C0,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7};
int *cara, *caraEnVisualizacion;

//Atención, la longitud de cada array siguiente está codificada en el propio
//array, porque como cada columna sólo utiliza 7 bits he aprovechado
//el octavo para codificar la longitud.
//Numeros
int caracter0[3]={31,17,31+128};//0
int caracter1[3]={9,31,1+128};//1
int caracter2[3]={19,21,9+128};//2
int caracter3[3]={17,21,26+128};//3
int caracter4[3]={6,10,31+128};//4
int caracter5[3]={29,21,18+128};//5
int caracter6[3]={15,21,22+128};//6
int caracter7[3]={16,23,24+128};//7
int caracter8[3]={31,21,31+128};//8
int caracter9[3]={28,20,31+128};//9
//Letras mayúsculas
int caracter10[3]={15,20,15+128};//A
int caracter11[3]={31,21,10+128};//B
int caracter12[3]={14,17,10+128};//C
int caracter13[3]={31,17,14+128};//D
int caracter14[3]={31,21,17+128};//E
int caracter15[3]={31,20,16+128};//F
int caracter16[3]={14,17,23+128};//G
int caracter17[3]={31,4,31+128};//H
int caracter18[3]={17,31,17+128};//I
int caracter19[3]={2,17,31+128};//J
int caracter20[3]={31,12,19+128};//K
int caracter21[3]={31,1,1+128};//L
int caracter22[5]={31,8,4,8,31+128};//M   
int caracter23[5]={31,8,4,2,31+128};//N
int caracter24[5]={31,72,68,66,31+128};//Ñ
int caracter25[3]={14,17,14+128};//O
int caracter26[3]={31,20,8+128};//P
int caracter27[4]={31,17,19,31+128};//Q
int caracter28[3]={31,20,11+128};//R
int caracter29[3]={9,21,18+128};//S
int caracter30[3]={16,31,16+128};//T
int caracter31[3]={31,1,31+128};//U   
int caracter32[3]={30,3,30+128};//V
int caracter33[5]={31,2,4,2,31+128};//W
int caracter34[3]={27,4,27+128};//X
int caracter35[3]={24,7,24+128};//Y
int caracter36[3]={19,21,25+128};//Z
//Signos de puntuacion
int caracter37[2]={3,3+128};//.
int caracter38[2]={1,6+128};//,
int caracter39[1]={10+128};//:
int caracter40[2]={1,10+128};//;
int caracter41[1]={95+128};//¡
int caracter42[1]={125+128};//!
int caracter43[3]={14,81,2+128};//¿
int caracter44[3]={32,69,56+128};//?
int caracter45[2]={16,96+128};//´
int caracter46[2]={62,65+128};//(
int caracter47[2]={65,62+128};//)
int caracter48[2]={0,0+128};// (espacio)
//Caracteres especiales
int caracter49[5]={2,21,23,17,14+128};//@
int caracter50[3]={50,107,38+128};//$
int caracter51[5]={20,62,85,65,34+128};//€
//Signos matemáticos
int caracter52[3]={4,14,4+128};//+
int caracter53[3]={4,4,4+128};//-
int caracter54[3]={10,4,10+128};//*
int caracter55[3]={3,4,24+128};///
int caracter56[3]={19,4,25+128};//%
int caracter57[3]={4,10,17+128};//<
int caracter58[3]={17,10,4+128};//>
int caracter59[3]={10,10,10+128};//=
//Velas
int caracter60[6]={3,9,29,61,57,3+128};
int caracter61[6]={3,9,29,61,121,3+128};
int caracter62[6]={3,9,61,125,25,3+128};
int caracter63[6]={3,25,125,61,9,3+128};
int caracter64[6]={3,121,61,29,9,3+128};
int caracter65[6]={3,57,61,29,9,3+128};
int caracter66[6]={3,1,1,1,1,3+128};//vela apagada
//French
int caracter67[3]={47,74,15+128};//Á
int caracter68[3]={15,74,47+128};//À
int caracter69[3]={47,74,47+128};//Â
int caracter70[3]={63,85,17+128};//É
int caracter71[3]={31,85,49+128};//È
int caracter72[3]={63,85,49+128};//Ê
int caracter73[3]={95,21,81+128};//Ë
int caracter74[3]={41,79,9+128};//Í
int caracter75[3]={41,79,41+128};//Î
int caracter76[3]={81,31,81+128};//Ï
int caracter77[3]={38,73,6+128};//Ó
int caracter78[3]={38,73,38+128};//Ô
int caracter79[3]={47,65,15+128};//Ú
int caracter80[3]={15,47,65+128};//Ù
int caracter81[3]={47,65,47+128};//Û
int caracter82[3]={95,1,95+128};//Ü
int caracter83[3]={125,70,68+128};//Ç


//Caracteres reservados a partir del 240 (incluido)
//caracter246 -->Final de cadena transmitida por USB
//caracter247 -->Visualización inmediata del caracter siguiente (sin arrastre)
//caracter248 -->Volver al principio
//caracter249 -->Quitar espacio sufijo en caracter siguiente
//caracter250 -->Saltar a siguiente caracter
//caracter251 -->Inicio y final de animacion yo-yo
//caracter252 -->Inicio y final de animacion diente de sierra
//caracter253 -->Pausa corta/saltarse un avance
//caracter254 -->Stop
//caracter255 -->Nulo (se usa en animaciones)

int const * caracter[84]={caracter0,caracter1,caracter2,caracter3,caracter4,caracter5,
                    caracter6,caracter7,caracter8,caracter9,caracter10,caracter11,
                    caracter12,caracter13,caracter14,caracter15,caracter16,caracter17,
                    caracter18,caracter19,caracter20,caracter21,caracter22,caracter23,
                    caracter24,caracter25,caracter26,caracter27,caracter28,caracter29,
                    caracter30,caracter31,caracter32,caracter33,caracter34,caracter35,
                    caracter36,caracter37,caracter38,caracter39,caracter40,caracter41,
                    caracter42,caracter43,caracter44,caracter45,caracter46,caracter47,
                    caracter48,caracter49,caracter50,caracter51,caracter52,caracter53,
                    caracter54,caracter55,caracter56,caracter57,caracter58,caracter59,
                    caracter60,caracter61,caracter62,caracter63,caracter64,caracter65,
                    caracter66,caracter67,caracter68,caracter69,caracter70,caracter71,
                    caracter72,caracter73,caracter74,caracter75,caracter76,caracter77,
                    caracter78,caracter79,caracter80,caracter81,caracter82,caracter83};

#INT_EXT1
void int1_handler(){
   if(!botonPulsado){
      botonPulsado=1;
      modoFuncionamiento=!modoFuncionamiento;
      ciclosTimer1=400;               
      ext_int_edge(1,L_TO_H);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
      set_timer1(0);
   }else{      
      botonPulsado=0;      
      setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
      ext_int_edge(1,H_TO_L);     
      
   }   
}

#INT_TIMER1
void timer1_handler(){   
   if(--ciclosTimer1==0){         
      resetear=1;
   }   
}

#INT_AD
void ad_handler(){
   conversorOcupado=0;
}

#INT_TIMER0
void tmr_handler() {    
      //Apagar
      output_a(0);
      //Cambiar de columna
      if (columnaActual==5){
         columnaActual=0;
         if(caraEnVisualizacion!=cara){
            caraEnVisualizacion=cara;
         }
      }else{
         columnaActual++;
      } 
      //Preparar filas
      for(i=0;i<7;i++){
         output_bit(filas[i],*(caraEnVisualizacion+columnaActual)&(64>>i));
      }
      //Encender columna
      output_a(1<<columnaActual);      
      set_timer0(PRECARGA_TIMER);
}

void int mostrarTexto (int1 tipo, int parametro, int1 salirConSoplido, int1 atenuacionUmbralSoplido,int1 salirConBoton, int1 salirSoloFinal){
   unsigned int i,j;
   int16 contador=1;
   signed int columnasRestantes=0;//columnas que aún quedan 
   //por visualizar del caracterEntrante   
   int zonaTemporal[2][6]={0,0,0,0,0,0,0,0,0,0,0,0};//aquí se monta lo que se va a visualizan 
   //antes de pasárselo a *cara
   //si el bit más significativo es 1 el avance dentro de la animación es hacia
   //la derecha, y si es 0 el avance es hacia la izquierda (animaciones yo-yo).
   //Para que una columna sea animada, siguientePropietarioColumna debe contener
   //un valor distinto de 255
   int1 indiceZonaTemporalActiva=0;
   int1 incluirEspacioSufijo=1; 
   int1 actualizarVisualizacion=0;
   int1 mostrarInstantaneamente=0;
   int1 stopActivado=0;
   int1 siguienteCaracterEsAnimado=0;
   int1 sentidoDeAvance;
   int* caracterEntrante;//puntero al carácter entrante
   int longitudCaracterEntrante;   
   int posicionCaracterActual;//posición en la EEPROM del último carácter
   //leído   
   int propietarioActualColumna[6][2]={255,1,255,1,255,1,255,1,255,1,255,1};//en una animación, posición en la eeprom 
   //e índice de la columna dentro del carácter
   //del siguiente caracter que ocupará cada columna de zonaTemporal
   unsigned int longitudMensaje;
   //Apagar ojos
   output_low(PIN_C1);
   output_low(PIN_C2);
   if(salirConSoplido){
      enable_interrupts(INT_AD); 
      clear_interrupt(INT_AD);
      conversorOcupado=1;
      read_adc(ADC_START_ONLY);
   }
   if (tipo){              
      if(parametro>9){
         write_eeprom(7,((int)(parametro/10)));   
         delay_ms(20);                  
      }else{
         write_eeprom(7,250);         
         delay_ms(20);
      }
      write_eeprom(8,parametro-((int)(parametro/10))*10);         
      delay_ms(20);
      parametro=6; 
   }
   longitudMensaje=read_eeprom(parametro);   
   posicionCaracterActual=parametro;
   do{
      contador++;
      //Actualizar animación
      if(contador % ((int16)(VELOCIDAD_TEXTO/PROPORCION_ANIMACION_AVANCE))==0){
         actualizarVisualizacion=1;
         for(i=0;i<6;i++){
            j=read_eeprom(propietarioActualColumna[i][0]);            
            if(j!=255){//es una columna animada
               if(zonaTemporal[indiceZonaTemporalActiva][i]>128){
                  sentidoDeAvance=1;
               }else{
                  sentidoDeAvance=0;
               }               
               j=((zonaTemporal[indiceZonaTemporalActiva][i])<128?read_eeprom(propietarioActualColumna[i][0]-1):read_eeprom(propietarioActualColumna[i][0]+1));            
               switch(j){
                  case 251: //animacion yo-yo                         
                        if (sentidoDeAvance){//Va hacia la derecha                           
                           propietarioActualColumna[i][0]-=1;                           
                        }else{//va hacia la izquierda
                           propietarioActualColumna[i][0]+=1;
                        }
                        sentidoDeAvance=!sentidoDeAvance;
                     break;
                  case 252: //animacion diente de sierra                  
                     while(read_eeprom(propietarioActualColumna[i][0])!=252){
                        propietarioActualColumna[i][0]--;
                     }
                     break;
                  default:                  
                     if(sentidoDeAvance){
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]+1;
                     }else{
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]-1;
                     }
               }
               //Actualizar columnas en zona temporal
               //Cuidadito con el bit más significativo para mantener el sentido
               //de la animación
               j=(caracter[read_eeprom(propietarioActualColumna[i][0])])[propietarioActualColumna[i][1]];
               if(sentidoDeAvance){
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j+128;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }
               }else{
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j-128;
                  }                  
               }
            }         
         }         
      }
      //Actualizar avance
      if(contador>=VELOCIDAD_TEXTO){ 
         if(!stopActivado){
            actualizarVisualizacion=1;         
            if(columnasRestantes==0){
               if(longitudMensaje>0){
                  longitudMensaje--;
                  posicionCaracterActual++;
                  j=read_eeprom(posicionCaracterActual);
                  if(j>=240){
                     //gestión de caracteres reservados
                     switch (j){
                        case 247:
                           mostrarInstantaneamente=1;
                           stopActivado=1;
                           continue;
                           break;
                        case 248:
                           longitudMensaje=read_eeprom(parametro);   
                           posicionCaracterActual=parametro;
                           continue;
                           break;
                        case 249:                  
                           incluirEspacioSufijo=0;
                           continue;
                           break;
                        case 250:                                                      
                           continue;
                           break;
                        case 251:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 252:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 253:
                           contador=1;
                           continue;
                           break;
                        case 254:
                           longitudMensaje=0;
                           stopActivado=1;
                           continue;
                           break;                  
                     }
                  }else{                  
                     caracterEntrante=caracter[j];
                     columnasRestantes=0;
                     //Averiguar el número de columnas del carácter                        
                     while(!((caracterEntrante[columnasRestantes])&128)){
                        columnasRestantes++;               
                     };
                     columnasRestantes++;
                     longitudCaracterEntrante=columnasRestantes;
                  }                       
               }else{ 
                  if(salirConSoplido){
                     disable_interrupts(INT_AD);       
                  }
                  return;               
               }
            }
            if(columnasRestantes>0){
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               } 
               if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes];               
               }else{
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes]-128;                                 
                  //Para evitar interferencias con el sentido de la animación
               }
               if(siguienteCaracterEsAnimado){ 
                  propietarioActualColumna[5][1]=longitudCaracterEntrante-columnasRestantes;
                  if(columnasRestantes==longitudCaracterEntrante){
                     propietarioActualColumna[5][0]=posicionCaracterActual;                  
                  }else{
                     propietarioActualColumna[5][0]=propietarioActualColumna[4][0];                  
                  }
                  if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                     zonaTemporal[indiceZonaTemporalActiva][5]=(caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]];               
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][5]=((caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]])-128;
                     //Para evitar interferencias con el sentido de la animación
                  }                                    
                  //Se debe sumar 128 si la animación está actualmente
                  //avanzando hacia la derecha, es decir, si la columna entrante
                  //es la primera de la animación (todas las animaciones comienzan
                  //hacia la derecha), o si la columna entrante es posterior a la
                  //primera y la columna anterior es >=128
                  //No puede haber caracteres animados de una sola columna
                  if(propietarioActualColumna[5][1]==0){
                     zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                  }else{
                     if(zonaTemporal[indiceZonaTemporalActiva][4]>=128){
                        zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                     }
                  }
               }else{
                  propietarioActualColumna[5][0]=255;
               }
               contador=1;
               columnasRestantes--;    
            }
            if(columnasRestantes==-1){
               columnasRestantes=0;
               incluirEspacioSufijo=0;
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               }
               zonaTemporal[indiceZonaTemporalActiva][5]=0; 
               propietarioActualColumna[5][0]=255;
               contador=1;
            }
            if(columnasRestantes==0){
               if (incluirEspacioSufijo==1){
                  columnasRestantes=-1;
               }else{
                  if(siguienteCaracterEsAnimado){                        
                     siguienteCaracterEsAnimado=0;                     
                     //Avanzar posicionCaracterActual
                     while(read_eeprom(posicionCaracterActual)!=251 && read_eeprom(posicionCaracterActual)!=252){                        
                        posicionCaracterActual++;
                     }
                  }                  
                  incluirEspacioSufijo=1;
               }
            }         
         }else{
            contador=1;
            if(mostrarInstantaneamente){
               stopActivado=0;
               mostrarInstantaneamente=0;
               posicionCaracterActual++;
               i=read_eeprom(posicionCaracterActual);
               caracterEntrante=caracter[i];
               for(j=0;j<6;j++){              
                  zonaTemporal[indiceZonaTemporalActiva][j]=caracterEntrante[j];
                  if(caracterEntrante[j]>=128){
                     zonaTemporal[indiceZonaTemporalActiva][j]-=128;
                  }
                  propietarioActualColumna[j][0]=255;
               }
            }
         }
      }
      //Actualizar visualizacion
      if (actualizarVisualizacion){
         cara=zonaTemporal[indiceZonaTemporalActiva];
         while(cara!=caraEnVisualizacion){
         }
         actualizarVisualizacion=0;         
         indiceZonaTemporalActiva=!indiceZonaTemporalActiva;            
         for(j=0;j<6;j++){
            zonaTemporal[indiceZonaTemporalActiva][j]=zonaTemporal[!indiceZonaTemporalActiva][j];
         }
      }
      
      //¿Detectar soplido?            
      if(salirConSoplido){         
         if(!salirSoloFinal || (salirSoloFinal && longitudMensaje==0 && columnasRestantes==0)){
            if(!conversorOcupado){
               conversorOcupado=1;
               j = read_adc(ADC_READ_ONLY);               
               read_adc(ADC_START_ONLY);
               if(atenuacionUmbralSoplido){
                 j+=30;
               }
               if (j>UMBRAL_SOPLIDO){
                  disable_interrupts(INT_AD);
                  return;
               }         
            }         
         }
      }
      //Detectar salida
      if(modoFuncionamiento){
         return;
      }
      //Detectar reset
      if(resetear){
         j=read_eeprom(1);
         write_eeprom(0,j);
         delay_ms(40);      
         reset_cpu();
      }
   }while(true);   
}
void main() {      
   unsigned int8 entradausb;
   unsigned int8 value, max;
   int comodin, comodin2;
   int16 comodin3, comodin4;
   int16 ciclosParaDormirse=UMBRAL_DORMIRSE;
   int modoCara=0;   
   unsigned int8 supremo=80;
   signed int caraActiva=0;   
   signed int8 acumuladorParpadeo;
   unsigned int32 periodo, muestra;     
   int bostezo[5][6]={0,8,40,104,8,0,0,8,44,108,8,0,0,12,42,106,12,0,0,14,41,105,14,0,0,15,41,105,15,0};  
         
   //caras del modo nariz aguileña
   int cara1[6]={0,4,108,44,4,0};                                       
   int cara2[6]={0,4,110,46,4};                                        
   int cara3[6]={0,6,106,42,6,0};   
   int cara4[6]={0,7,105,41,7,0};                    
   int cara5[6]={0,14,105,41,14,0};                                        
   int cara6[6]={12,10,105,41,10,12};                                    
   int cara7[6]={14,9,105,41,9,14};                                      
   int cara8[6]={15,9,105,41,9,15};                    
   //caras del modo nariz chata
   int cara9[6]={0,8,88,88,8,0};
   int cara10[6]={0,8,84,84,8,0};
   int cara11[6]={0,12,82,82,12,0};
   int cara12[6]={0,14,81,81,14,0};
   int cara13[6]={0,30,81,81,30,0};
   int cara14[6]={12,18,81,81,18,12};
   int cara15[6]={14,17,81,81,17,14};
   int cara16[6]={31,17,81,81,17,31};
   //caras del modo sin nariz
   int cara17[6]={8,8,8,8,8,8};
   int cara18[6]={28,20,20,20,20,28};
   int cara19[6]={62,34,34,34,34,62};
   int cara20[6]={127,65,65,65,65,127};
   //caras del modo luciano
   int cara21[6]={0,0,0,0,0,0};
   int cara22[6]={0,1,1,1,1,0};
   int cara23[6]={1,2,2,2,2,1};
   int cara24[6]={3,4,5,4,5,3};
   int cara25[6]={7,8,10,9,10,7};
   int cara26[6]={15,16,20,18,20,15};
   int cara27[6]={30,33,41,37,41,30};
   int cara28[6]={60,66,82,74,82,60};
   int const *caras[4][8]={cara1,cara2,cara3,cara4,cara5,cara6,cara7,cara8,
                           cara9,cara10,cara11,cara12,cara13,cara14,cara15,cara16,
                           cara17,cara17,cara18,cara18,cara19,cara19,cara20,cara20,
                           cara21,cara22,cara23,cara24,cara25,cara26,cara27,cara28};
                           
                           
   if(!input(PIN_B1)){
      usb_cdc_init();
      usb_init();
      output_low(PIN_C1);
      output_high(PIN_C2);
      while(!usb_cdc_connected()) {      
         delay_ms(200);
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);
      }
      do{
         usb_task();     
         if (usb_enumerated()) {
            printf(usb_cdc_putc, "PICTENGU");
            break;
         }
      }while (TRUE); 
      //Enviar contenido eeprom           
      output_high(PIN_C1);
      output_high(PIN_C2);
      entradausb=get_int_usb();         
      if(entradausb==246){
         delay_ms(1000);
         for(comodin3=0;comodin3<=255;comodin3++){             
            value=read_eeprom(comodin3);
            delay_ms(20);                     
            printf(usb_cdc_putc,"%c",value);      
         }
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);                   
      }
      comodin3=0;
      do{
         usb_task();
         if(usb_enumerated()){
            entradausb=get_int_usb(); 
            if(entradausb!=246){
               write_eeprom(comodin3,entradausb);
               delay_ms(20);  
               comodin3++;
            }else{
               break;
            }
         }
      }while(true);       
   }     
   
   setup_adc_ports(PIN_B0);
   setup_adc(ADC_CLOCK_DIV_64 ); 
   set_adc_channel(12);
   ext_int_edge(1,H_TO_L);
   setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
   setup_timer_0(RTCC_8_BIT|RTCC_DIV_128);
   set_timer0(PRECARGA_TIMER);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_AD);   
   clear_interrupt(INT_AD);    
   enable_interrupts(INT_EXT1);   
   clear_interrupt(INT_EXT1);
   enable_interrupts(INT_TIMER1);   
   clear_interrupt(INT_TIMER1);
   enable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT1);
        
   columnaActual=5;
   output_low(PIN_C1);
   output_low(PIN_C2);
   
   //Modo 1: dormido
   cara=bostezo[0];
   caraEnVisualizacion=cara;
   
   
   value=0;
   conversorOcupado=1;
   read_adc(ADC_START_ONLY);   
   while(value<UMBRAL_SOPLIDO-30){
      if(!conversorOcupado){
         conversorOcupado=1;
         value = read_adc(ADC_READ_ONLY);
         read_adc(ADC_START_ONLY);         
      }
   }   
   disable_interrupts(INT_AD);       
   
   //Modo 2: despertar: abre un ojo, luego el otro, luego bosteza
   //y pestañea 3 veces consecutivas
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   set_pwm2_duty(0);
   for(comodin=0;comodin<40;comodin++){        
      set_pwm1_duty(comodin);      
      delay_ms(30);
   }
   for(comodin=0;comodin<40;comodin++){             
      set_pwm2_duty(comodin);
      delay_ms(30);
   }   
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);
   output_low(PIN_C1);
   output_low(PIN_C2);
   for (comodin=0;comodin<5;comodin++){
      cara=bostezo[comodin];
      delay_ms(150);
   }
   delay_ms(1000);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   for (comodin=4;comodin>0;comodin--){//Con >= falla ¿por qué?
      cara=bostezo[comodin];   
      set_pwm1_duty((4-comodin)*10); 
      set_pwm2_duty((4-comodin)*10); 
      delay_ms(150);
   }
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);   
   for(comodin=1;comodin<=3;comodin++){
      output_low(PIN_C1);
      output_low(PIN_C2);
      delay_ms(300);
      output_high(PIN_C1);
      output_high(PIN_C2);
      delay_ms(300);
   }
   //Si en el primer byte de la memoria hay un valor distinto de 00...
   //comienza el juego del apagado de velas...
   //en caso contrario salta directamente al modo 3   
   comodin=read_eeprom(0);
   delay_ms(20);
   if(comodin!=0){
      write_eeprom(0,0);
      delay_ms(20);
      write_eeprom(1,comodin);
      delay_ms(20);      
      mostrarTexto(0,19,0,0,0,0);
      for(comodin2=1;comodin2<=comodin;comodin2++){         
         mostrarTexto(1,comodin2,1,1,0,1);
         cara=caracter66;
         delay_ms(500);
      }      
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
   }
   
   //Modo 3: Wilson
   modoFuncionamiento=1;
   output_high(PIN_C1);
   output_high(PIN_C2);  
   cara=cara1;
   caraEnVisualizacion=cara1;
   acumuladorParpadeo=0; 
   muestra=0;
   periodo=VELOCIDAD_GESTICULACION;   
   max=0;   
   enable_interrupts(INT_AD); 
   clear_interrupt(INT_AD);
   enable_interrupts(INT_EXT1);
   clear_interrupt(INT_EXT1);    

   conversorOcupado=1;
   read_adc(ADC_START_ONLY);
   
   do{
      if(modoFuncionamiento){      
         muestra++;
         if(!conversorOcupado){
            conversorOcupado=1;
            value = read_adc(ADC_READ_ONLY);
            read_adc(ADC_START_ONLY);            
            if(value>max){
               max=value;
            }
         }
         if(muestra==periodo){
            if(acumuladorParpadeo>0){
               output_high(PIN_C1);
               output_high(PIN_C2);
            }
            if(max>UMBRAL_SOPLIDO){//Soplido
               cara=cara21;
               if (modoCara<3){
                  modoCara++;
               }else{
                  modoCara=0;
               }
               output_low(PIN_C1);
               output_low(PIN_C2);
               for(comodin2=7;comodin2>0;comodin2--){
                  cara=caras[modoCara][comodin2];
                  delay_ms(100);
               }
               output_high(PIN_C1);
               output_high(PIN_C2);
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>supremo){
               caraActiva=7;
               acumuladorParpadeo+=8;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)6/7*supremo){
               caraActiva=6;                  
               acumuladorParpadeo+=7;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)5/7*supremo){
               caraActiva=5;
               acumuladorParpadeo+=6;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)4/7*supremo){
               caraActiva=4;
               acumuladorParpadeo+=5;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)3/7*supremo){
               caraActiva=3;
               acumuladorParpadeo+=4;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)2/7*supremo){
               caraActiva=2;
               acumuladorParpadeo+=3;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)1/7*supremo){
               caraActiva=1;
               acumuladorParpadeo+=2;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else{
               caraActiva=0;
               acumuladorParpadeo+=1;
               ciclosParaDormirse--;
            }

            cara=caras[modoCara][caraActiva];
            if(max>supremo+UMBRAL_AUDICION){
               supremo=max-UMBRAL_AUDICION;
            }else{
               if(supremo>7*UMBRAL_AUDICION){
                  supremo--;
               }
            }
            if(acumuladorParpadeo>=UMBRAL_PARPADEO){
               output_low(PIN_C1);
               output_low(PIN_C2);
               acumuladorParpadeo=-1;
            }
            //printf(usb_cdc_putc, "\r\nSupremo=%6.0w",supremo );
            //printf(usb_cdc_putc, "\r\nCociente=%6.4f",(float)1/7*supremo );
            muestra=0;
            max=0;            
         }            
      }else{
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
      }
      if(resetear||ciclosParaDormirse==0){
         if(ciclosParaDormirse){
            comodin=read_eeprom(1);
            write_eeprom(0,comodin);
            delay_ms(40);     
         }
         reset_cpu();
      }
   }while (TRUE);      
}
```
 
y los errores que me daba en las instrucciones que he pasado antes son las siguiente:
***Error 28 "PIC_Tengu_v1.c" Line 157(13,14): Expecting an identifier

luego en todos los "caracter" que hay me salta el mismo error y me envia el cursor al principio de la palabra.. el error que me da es el siguiente:
***Error 48 "PIC_Tengu_v1.c" Line 157(27,36: Expecting a (


aun que yo sigo pensando que es el mismo programa, que necesite una extension para entender estos caracteres, igual que con el microcodestudio necesito el PBP242 para que pueda compilar en basic. alguien me puede decir algun programa compilador en CCS C que me pudiera entender toda la programacion?
saludos


----------



## lubeck (Sep 28, 2010)

Hola soopy

no te la compliques...
porque siempre quieren empezar por correr y luego gatear...

consigue el microstudio... es el editor
consigue el PBP246 comiplador de basic
consigue el MPASM compilador de ASM
consigue el HID ... generador de codigo PBP y VisualBasic o C o java (Easy HID Wizard asistente)

con eso te lo cocina en gran parte el codigo...


----------



## soopy_46 (Sep 28, 2010)

pero pbp 246 no es para basic? yo lo que quiero es el codigo CCS C y solo tengo que unir dos programaciones... si fuera en BASIC ya me las hubiera arreglado porque entiendo suficiente para hacerlo... el problema esque de CCS C no se programar por eso pido ayuda para que alguien me ayude a acabar el programa del pic con lo del usb (y el cdc) solo pediria eso o almenos el .hex
gracias y sigo buscando..


----------



## lubeck (Sep 28, 2010)

> yo lo que quiero es el codigo CCS C y solo tengo que unir dos programaciones... si fuera en BASIC ya me las hubiera arreglado porque entiendo suficiente para hacerlo...


ok... yo solo decia.. 
esperemos que  alguien te lo haga...


----------



## soopy_46 (Sep 28, 2010)

> ok... yo solo decia..
> esperemos que alguien te lo haga...


jeje
tampoco pido que nadie me lo haga jeje
lo que me refiero es que alguien me pudiera ayudar con esto y que me lo dijera para asi aprender que hacer en estas situaciones
gracias por contestar y.. lubeck espero k no te lo hubieras tomado mal :S


----------



## lubeck (Sep 28, 2010)

> lubeck espero k no te lo hubieras tomado mal


Claro que no... para nada...
lo que se me hace es muy complejo que empieces de esa manera... no digo que no se pueda... yo tambien estoy empezando con el usb y no se ve sencillo en C ni en ASM... con el basic estoy captando el procedimiento, pero cada uno tiene sus metodos...
igual te deseo suerte...


----------



## soopy_46 (Sep 28, 2010)

jeje gracias 
mira te cuento yo hice este circuito porque vi que tambien estaba el programa en .hex y digo bien asi lo podre tener bien para el lunes 4 pero resulta que no tiene escrito lo que capta el usb y lo que yo pedia era si alguien podia copiarlo en el programa del pic que estan arriba solo es copiar ya que a mi no me deja y sino que alguien me ayudara con eso de los caracteres.

buenas noches


----------



## soopy_46 (Sep 29, 2010)

alguien me podria contestar a algo tan simple como "como incluir las dos programaciones porfavoooooor" gracias...

valeee, por fin he encontrado un posible error:


```
#include ".\include\usb_cdc.h"
```
 
quizas pudiera ser de esto no? porque para encontrar la inclusion o como se diga en el lenguaje, tendria que ser "C:\Documents and Settings\ y donde este el archivo.. no? o si ya estaba el .hex hecho tendria que estar.
el problema esque si voy a compilador y lo pongo bien, luego me da el error ese de los caracteres que me interesaria que alguien me ayudara a solucionar.
utilizo el PCWHD

saludos buenas tardes


----------



## lubeck (Sep 29, 2010)

> quizas pudiera ser de esto no? porque para encontrar la inclusion o como se diga en el lenguaje, tendria que ser "C:\Documents and Settings\ y donde este el archivo.. no?


mi hermano... creo que ya entendi que es lo que necesitas...

se llaman librerias...
en lugar de cambiar la ruta que a lo mejor puede funcionar...mejor copia las librerias que necesitas en donde estan las demas... y listo... jejejej...

sube todo en un zip  o rar para intentarlo yo...

saludos...


----------



## soopy_46 (Sep 29, 2010)

no he acabado de entender, me podrias explicar de otra forma porfavor?
y tu que programa utilizas?


----------



## lubeck (Sep 29, 2010)

> no he acabado de entender, me podrias explicar de otra forma porfavor?


Ok en C tienes el programa principal... tiene extencion .C el archivo...
y las librerias que son complementos del programa principal tienen extencion .h al compilarlo incluye  la libreria en el principal... pero tiene que encontrarla en algun directorio y creo que ahi esta tu problema... pero solo estoy adivinando si subes todos los archivos para intentarlo te podría dar mi opinión de como lo hagas...
los .c y los .h


> y tu que programa utilizas?



estoy utilizando en C el CCS C PCW o no tengo idea de como se llame tiene muchos pseudonimos jejeje...

es este..


----------



## soopy_46 (Sep 29, 2010)

vale ahora te subo los dos archivos y.. el programa es el mismo que utilizo yo jeje, lo que no se si necesita algun plugin o alguna cosa de estas..
adjunto los archivos que dispongo y que he visto que necesita:

Dentro del rar hay un archivo .txt llamado "los archivos"  y te dice que son cada uno...
espero respuestas, saludoos


----------



## lubeck (Sep 29, 2010)

y cual es el problema???
si lo compila... lo descomprimi en el escritorio, le quite las rutas que pusiste... y listo...
tira un monton de advertencias pero ningun error... 
mira...


----------



## soopy_46 (Sep 29, 2010)

pues dime como lo has hecho o pasame el archivo .hex que te salga.. porque a mi me tira los siguientes errores:


----------



## lubeck (Sep 29, 2010)

no has de tener bien instaldo el ccs...
alguna libreria le falta o que se yo... jejej..
ahi te va la carpeta....


----------



## soopy_46 (Sep 29, 2010)

sigue sin detectarlo.. eso porque?
te he adjuntado tambien el  readme que contenia el rar, para que vieras que tengo que hacer... he instalado tambien el MCHPFSUSB_Setup.EXE que es el PICDEM FS USB Demo Tool. hasta aqui bien el problema es en esta parte: "_Al conectar PIC-Tengu al PC manteniendo pulsado su botón, los ojos empezarán a 
parpadear intermitentemente y el PC notificará que ha detectado un elemento de hardware
nuevo; en ese momento indicaremos que queremos especificar el driver manualmente y
seleccionaremos el archivo mchpcdc.inf_." pero claro me da eso de que no se reconoce el dispositivo y no se como poner eso de que utilice como driver eso...
mira: 

quizás el rxtxSerial.dll de la carpeta softwareWindows tendria que estar en otro sitio?
quieres que intente pasarte los archivos que contiene la carpeta todo el rar de pic tengu?

aah y teoricamente ahora lo unico que tenia que hacer es poner el hex tal cual al pic no? o se tenia que hacer algo?
porque si el fallo viene de eso.. no se podria poner directamente el codigo de usb en el del pic y aunque quedara algo mas extenso lo tendria seguro..
o no es posible? (esque no se nada de CCS C solo basic y algunas cosas si que se que hacer)

saludos


----------



## lubeck (Sep 29, 2010)

> quizás el rxtxSerial.dll de la carpeta softwareWindows tendria que estar en otro sitio?



No tengo ni la mas remota idea...

pero intenta esto... copia esa libreria rxtxserial.dll a la carpeta c:\windows\system32
y con la ventana de comandos "Inicio->ejecutar" pon en el cuadro de dialogo regsvr32 rxtxserial.dll eso es para registrarla...



> aah y teoricamente ahora lo unico que tenia que hacer es poner el hex tal cual al pic no? o se tenia que hacer algo?



si grabalo solo el archivo hex y fijate que el oscilador sea el correcto...
es que no tengo ni idea de que estas haciendo


----------



## soopy_46 (Sep 29, 2010)

mira este es el proyecto:




 si lo ves enterlo quizas puedas entenderlo
y he hecho eso de registrarlo y mira:

no habia pensado en mirar lo del oscilador
como puedo mirar esto en winpic800
el oscilador es el cristal?


----------



## lubeck (Sep 29, 2010)

> no habia pensado en mirar lo del oscilador
> como puedo mirar esto en winpic800
> el oscilador es el cristal?



tienes algún esquema???
subelo a ver si te puedo ayudar... si no esta en proteus hasta ahi puedo ayudarte...


----------



## soopy_46 (Sep 29, 2010)

vale te adjunto el esquema
debo decirte que ahora si que va, si lo conecto sin pulsar el boton, se queda en el estado dormido (del cual no despierta) no se si sera porque esta mal puesto el potenciometro, o porque no es de un mega.. o sino puede ser por la capsula electret. y si lo conecto al pc lo detecta como pic tengu
lo que no se es como buscar el archivo que me pide el readme que no se si habras leido pero decia que en el momento de instalar digera manualmente y seleccionara un archivo pero.. no se como buscarlo
gracias por tu ayuda de verdad
si lo abres en el v0 encontraras los esquematicos, y archivos de proteus
en el v1 lo que te pasé antes
y en el v2 creo que era una variacion en la placa


----------



## lubeck (Sep 29, 2010)

> o que no se es como buscar el archivo que me pide el readme que no se si habras leido pero decia que en el momento de instalar digera manualmente y seleccionara un archivo pero.. no se como buscarlo



pon la mas informacion que puedas... no entiendo recuerda que yo no estoy haciendo el proyecto... tu llevas mas estudiandolo...

en el archivo pictengu v1 esta un sofware de windows ya lo instalaste o ejecutaste... esa es la interface por otro lado para que no batalles el hardware armalo exactamente como lo indica el esquema... no es lo mismo juana que chana...


----------



## soopy_46 (Sep 29, 2010)

a que te refieres con eso de que no me batalle el harware y que lo arme exactamente como lo indica el esquema?
ahora no estoy en casa, luego te explico toda la informacion que sepa sobre el tengu.. pero si lees el readme que hay adjunto, te dice a que me refiero, y antes he dejado el nombre exacto de programa para que supierais a cual me referia :O
hasta luego
saludos

pd: la interface a cual programa te refieres? en esos rar que he pasado falta un programa que no he pasado porque pesa mas de lo que me deja colgar el foro... y lo de la variacion de la placa la hizo el propio creador.

por cierto eso de registrar en system32, como debo hacerlo?


----------



## lubeck (Sep 29, 2010)

> a que te refieres con eso de que no me batalle el harware y que lo arme exactamente como lo indica el esquema?


tu pusiste...


> no se si sera porque esta mal puesto el potenciometro, o porque no es de un mega.. o sino puede ser por la capsula electret. y si lo conecto al pc lo detecta como pic tengu





> a interface a cual programa te refieres?


pic_tengu.exe ese es el programa que hace la interface (comunicacion) del pic con el pc



> por cierto eso de registrar en system32, como debo hacerlo?


si no encontro el punto de entrada, probablemete no se necesite registrar pero si ponlo en la subcarpeta system32 del directorio windows para que lo localice...



> he instalado tambien el MCHPFSUSB_Setup.EXE que es el PICDEM FS USB Demo Tool.


este es el que dices que pesa mucho y no haz subido verdad....

estoy confundido es serial o usb... y que tiene que ver con un conversor???


----------



## soopy_46 (Sep 29, 2010)

aun me sigo preguntando que deben ser estos dos archivos...
estoy buscando algun programa para intentar abrirlos pero no creo que lo haya..

pero ya consigo conectar el pictengu al ordenador, el el pic_tengu_exe ya lo reconoce, lo unico que pasa esque se queda todo el rato en Espere mientras se obtienen los datos de PIC-Tengu
no se.. en la carpeta lib de la carpeta de softwareWindows (donde se encuentra el ejecutable) hay unos archivos .java que no me deja abrir, puede ser por eso? que esten bloqueados o que les falte algo? :O
saludos y buenas noches

tambien añado que no me detecta el micro... puede ser en el codigo? que porcierto lo paso para que se vea:



```
//¿Detectar soplido?            
      if(salirConSoplido){         
         if(!salirSoloFinal || (salirSoloFinal && longitudMensaje==0 && columnasRestantes==0)){
            if(!conversorOcupado){
               conversorOcupado=1;
               j = read_adc(ADC_READ_ONLY);               
               read_adc(ADC_START_ONLY);
               if(atenuacionUmbralSoplido){
                 j+=30;
               }
               if (j>UMBRAL_SOPLIDO){
                  disable_interrupts(INT_AD);
                  return;
               }         
            }         
         }
      }
      //Detectar salida
      if(modoFuncionamiento){
         return;
      }
      //Detectar reset
      if(resetear){
         j=read_eeprom(1);
         write_eeprom(0,j);
         delay_ms(40);      
         reset_cpu();
      }
   }while(true);
```
tambien os pasaria el archivo diciendo donde esta cada termino que dice soplido, para ver si hay algun error, o sino os paso el .txt y luego dar a edicion luego buscar y en buscar teclear soplido e ir viendo si tiene algun problema

saludos y gracias de antemano


----------



## lubeck (Sep 29, 2010)

soopy...
no creo que el codigo este mal...
el cristal de cuanto lo pusiste???



> hay unos archivos .java que no me deja abrir, puede ser por eso? que esten bloqueados o que les falte algo?



esos archivos de los que hablas son el codigo fuente del ejecutable pic_tengu.exe
pero como ya tienes el ejecutable no los requieres si no vas a hacer modificaciones en la estructura...
necesitas el java que viene en el visual studio de microsoft o similar para abrirlos...



> aun me sigo preguntando que deben ser estos dos archivos...
> estoy buscando algun programa para intentar abrirlos pero no creo que lo haya..


cuales dos archivos lo .h???
son las librerias que requiere el .C... al compilarlo los incluye en el hex y no los requiere mas...


----------



## soopy_46 (Sep 30, 2010)

no no lo de los dos archivos son unos que son .bak que tienen el mismo nombre que los del CDC

si el codigo no esta mal...
porque no hace efecto al micro?


----------



## lubeck (Sep 30, 2010)

> no no lo de los dos archivos son unos que son .bak que tienen el mismo nombre que los del CDC


los .bak son copias de los originales que se usan como respaldo
 menos se ocupan... a menos que pierdas los originales...


> porque no hace efecto al micro?


ni idea....
que oscilador de cristal usas.... de cuantos mherz???


----------



## soopy_46 (Sep 30, 2010)

mmm el cristal es de 4 Mhz, como decia la presentacion y no se que mas puede faltarme, si me quieres pedir informacion... quizas sea del winpic800, por ejemplo desde que cambie la configuracion, he hecho grandes avances, como por ejemplo hacer que el ordenador me lo reconozca... 
si necesitas que te de mas datos sobre el circuito, pidemelos y yo te los doy, incluso si hay alguna cosa sobre la configuracion de programacion del pic18F2455 en el winpic que deba saber, dimelo.

Gracias por todo, de verdad 

mmm si yo pongo el programa, segun la teoria lo que haré sera poder entrar en la EEPROM y escribir los mensajes y la informacion que se le puede poner segun el video (edad, mensaje y esas cosas) hay alguna forma de poder escribir ese texto, programandolo?
es que.. almenos que no se conecta al ordenador.. que pueda almenos escribir lo que necesito.
ahora me metere con el micro
saludos

buenas, buscando por internet he encontrado esto:

http://www.ucontrol.com.ar/revista/0004/ucontrol_revista_0004.pdf

en la página 7 explica el pictengu segun ucontrol, y es por jfmateos asi que es lo mismo... el problema esque dice que se sigue explicando en la siguiente revista, pero no he encontrado siguientes... si alguien la tubiera.. quizas me podria ayudar 
saludos buenas noches


----------



## soopy_46 (Sep 30, 2010)

bueno.. no hay mucho interes por el tema creo yo.. pero bueno.. ya mirare de hacer de otro modo o algo..`porque bueno.. tambien podria hacer una matriz de leds... no se.. 7x32 o algo asi.. pero estaria bien conseguir hacerlo con reconocimiento de teclado ps2 lo que eso ya se excede de mis limites


----------



## soopy_46 (Oct 2, 2010)

me da igual lo que me has dichoo ahora mismo porque se que algun error tiene que tener en el codigo...
dice:
si pic tengu no tiene ninguna orden ni por el micro ni por boton, ni por pc en 5 minutos, se apaga
y no lo hace..
pic tengu reconoce los sonidos del micro
no consigo despertarlo ya que no detecta el micro (ERROR EN EL CODIGO)
no se consiguen pasar nunca los datos al pc (ERROR EN EL CODIGO)
y cual es el problema a esto?
que yo no se programacion en C solo se basic y para ayudarme con esto necesito pediros ayuda..
saludos y buenas tardes...


----------



## lubeck (Oct 2, 2010)

> me da igual lo que me has dichoo ahora mismo porque se que algun error tiene que tener en el codigo...



mmm.. pero no te molestes ni te desesperes... y procura ser mas amable no cuesta nada..



> y cual es el problema a esto?



hay miles de razones por el que no se comunica con el pc, entre unas de ellas es que creo pones un ocilador de 4mhz y el codigo indica otro si mal no recuerdo...
estas utilizando un conversor usb-rs232 si entiendo bien y no creo que este diseñado para eso...
el por que creo que el código esta bien, es porque no genera ningún error ademas de que si fue probado difícilmente puede cambiarse solo, 
ahora bien si estas seguro de que el código esta mal y ese proyecto se basa  en eso... desechalo y hazlo en basic se puede hacer lo mismo pero muchísimo mas fácil... 
honestamente te digo que muy es muy difícil que alguien... incluyéndome.. se ponga a revisarlo... a menos que este super interesado en el mismo proyecto...


----------



## soopy_46 (Oct 2, 2010)

ok ok lo entiendo...
y si, utilizo un cristal de 4Mhz y lo del conversor no.. simplemente con el codigo ese que miramos, hace que lo detecte el programa del ordenador como puerto COM1 pero no es otra cosa..
y l del oscilador... me podrias decir, si no te importa, cual necesitaria?


```
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// PIC_Tengu_v1.c                                                  ////
////                                                                 ////
//// Autor: jfmateos2                                                ////
//// Contacto: [EMAIL="jfmateos@lycos.es"]jfmateos@lycos.es[/EMAIL]                                     ////
//// Madrid, abril 2008                                              ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
#include <18F2455.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN, CCP2C1
#device ADC=8
#use delay(clock=48000000)
#include <stdlib.h>
#include ".\include\usb_cdc.h"
#rom int8 0xf00000={5,0,0,0,0,0,//0-->5 (edad,copiaEdad,usos futuros,...)
12,250,1,249,251,60,61,62,63,64,65,251,254,//6-->18 (animacion: edad-vela)
29,29,25,26,21,10,48,26,10,28,10,48,10,26,10,16,10,28,48,21,10,29,48,32,14,21,10,29,48,48,//19-->48
202,17,10,35,48,27,31,18,14,23,48,26,18,14,23,29,10,48,27,31,14,48,29,25,21,25,48,31,23,48,21,
25,12,25,48,12,14,21,14,11,28,10,28,18,10,48,27,31,14,48,12,31,22,26,21,14,48,10,24,25,29,
38,48,35,48,27,31,14,48,17,10,35,48,27,31,14,48,10,26,28,25,32,14,12,17,10,28,48,26,25,28,
27,31,14,48,23,31,23,12,10,48,29,14,48,32,25,21,32,14,28,10,48,10,48,29,14,28,48,30,10,23,
48,19,25,32,14,23,38,48,10,31,23,27,31,14,48,30,10,22,26,25,12,25,48,23,31,23,12,10,48,29,
14,48,17,10,48,29,18,13,25,48,30,10,23,48,32,18,14,19,25,38,48,10,31,23,48,10,29,18,38,48,
15,14,21,18,36,48,12,31,22,26,21,14,10,24,25,29,48,10,21,22,31,37}//49-->251
#define PRECARGA_TIMER 0
#define UMBRAL_PARPADEO 100 //Max=128.Está afectado por VELOCIDAD_GESTICULACION
#define VELOCIDAD_GESTICULACION 20000
#define UMBRAL_SOPLIDO 90
#define VELOCIDAD_TEXTO 4500
#define PROPORCION_ANIMACION_AVANCE 2 
#define UMBRAL_AUDICION 3
#define UMBRAL_DORMIRSE 5000
unsigned int8 i;
unsigned int8  columnaActual=5;
int1 conversorOcupado=0;
int1 modoFuncionamiento;
int1 botonPulsado=0;
int1 resetear=0;
int16 ciclosTimer1;
int filas[7]={PIN_C0,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7};
int *cara, *caraEnVisualizacion;
//Atención, la longitud de cada array siguiente está codificada en el propio
//array, porque como cada columna sólo utiliza 7 bits he aprovechado
//el octavo para codificar la longitud.
//Numeros
int caracter0[3]={31,17,31+128};//0
int caracter1[3]={9,31,1+128};//1
int caracter2[3]={19,21,9+128};//2
int caracter3[3]={17,21,26+128};//3
int caracter4[3]={6,10,31+128};//4
int caracter5[3]={29,21,18+128};//5
int caracter6[3]={15,21,22+128};//6
int caracter7[3]={16,23,24+128};//7
int caracter8[3]={31,21,31+128};//8
int caracter9[3]={28,20,31+128};//9
//Letras mayúsculas
int caracter10[3]={15,20,15+128};//A
int caracter11[3]={31,21,10+128};//B
int caracter12[3]={14,17,10+128};//C
int caracter13[3]={31,17,14+128};//D
int caracter14[3]={31,21,17+128};//E
int caracter15[3]={31,20,16+128};//F
int caracter16[3]={14,17,23+128};//G
int caracter17[3]={31,4,31+128};//H
int caracter18[3]={17,31,17+128};//I
int caracter19[3]={2,17,31+128};//J
int caracter20[3]={31,12,19+128};//K
int caracter21[3]={31,1,1+128};//L
int caracter22[5]={31,8,4,8,31+128};//M   
int caracter23[5]={31,8,4,2,31+128};//N
int caracter24[5]={31,72,68,66,31+128};//Ñ
int caracter25[3]={14,17,14+128};//O
int caracter26[3]={31,20,8+128};//P
int caracter27[4]={31,17,19,31+128};//Q
int caracter28[3]={31,20,11+128};//R
int caracter29[3]={9,21,18+128};//S
int caracter30[3]={16,31,16+128};//T
int caracter31[3]={31,1,31+128};//U   
int caracter32[3]={30,3,30+128};//V
int caracter33[5]={31,2,4,2,31+128};//W
int caracter34[3]={27,4,27+128};//X
int caracter35[3]={24,7,24+128};//Y
int caracter36[3]={19,21,25+128};//Z
//Signos de puntuacion
int caracter37[2]={3,3+128};//.
int caracter38[2]={1,6+128};//,
int caracter39[1]={10+128};//:
int caracter40[2]={1,10+128};//;
int caracter41[1]={95+128};//¡
int caracter42[1]={125+128};//!
int caracter43[3]={14,81,2+128};//¿
int caracter44[3]={32,69,56+128};//?
int caracter45[2]={16,96+128};//´
int caracter46[2]={62,65+128};//(
int caracter47[2]={65,62+128};//)
int caracter48[2]={0,0+128};// (espacio)
//Caracteres especiales
int caracter49[5]={2,21,23,17,14+128};//@
int caracter50[3]={50,107,38+128};//$
int caracter51[5]={20,62,85,65,34+128};//€
//Signos matemáticos
int caracter52[3]={4,14,4+128};//+
int caracter53[3]={4,4,4+128};//-
int caracter54[3]={10,4,10+128};//*
int caracter55[3]={3,4,24+128};///
int caracter56[3]={19,4,25+128};//%
int caracter57[3]={4,10,17+128};//<
int caracter58[3]={17,10,4+128};//>
int caracter59[3]={10,10,10+128};//=
//Velas
int caracter60[6]={3,9,29,61,57,3+128};
int caracter61[6]={3,9,29,61,121,3+128};
int caracter62[6]={3,9,61,125,25,3+128};
int caracter63[6]={3,25,125,61,9,3+128};
int caracter64[6]={3,121,61,29,9,3+128};
int caracter65[6]={3,57,61,29,9,3+128};
int caracter66[6]={3,1,1,1,1,3+128};//vela apagada
//French
int caracter67[3]={47,74,15+128};//Á
int caracter68[3]={15,74,47+128};//À
int caracter69[3]={47,74,47+128};//Â
int caracter70[3]={63,85,17+128};//É
int caracter71[3]={31,85,49+128};//È
int caracter72[3]={63,85,49+128};//Ê
int caracter73[3]={95,21,81+128};//Ë
int caracter74[3]={41,79,9+128};//Í
int caracter75[3]={41,79,41+128};//Î
int caracter76[3]={81,31,81+128};//Ï
int caracter77[3]={38,73,6+128};//Ó
int caracter78[3]={38,73,38+128};//Ô
int caracter79[3]={47,65,15+128};//Ú
int caracter80[3]={15,47,65+128};//Ù
int caracter81[3]={47,65,47+128};//Û
int caracter82[3]={95,1,95+128};//Ü
int caracter83[3]={125,70,68+128};//Ç

//Caracteres reservados a partir del 240 (incluido)
//caracter246 -->Final de cadena transmitida por USB
//caracter247 -->Visualización inmediata del caracter siguiente (sin arrastre)
//caracter248 -->Volver al principio
//caracter249 -->Quitar espacio sufijo en caracter siguiente
//caracter250 -->Saltar a siguiente caracter
//caracter251 -->Inicio y final de animacion yo-yo
//caracter252 -->Inicio y final de animacion diente de sierra
//caracter253 -->Pausa corta/saltarse un avance
//caracter254 -->Stop
//caracter255 -->Nulo (se usa en animaciones)
int const * caracter[84]={caracter0,caracter1,caracter2,caracter3,caracter4,caracter5,
                    caracter6,caracter7,caracter8,caracter9,caracter10,caracter11,
                    caracter12,caracter13,caracter14,caracter15,caracter16,caracter17,
                    caracter18,caracter19,caracter20,caracter21,caracter22,caracter23,
                    caracter24,caracter25,caracter26,caracter27,caracter28,caracter29,
                    caracter30,caracter31,caracter32,caracter33,caracter34,caracter35,
                    caracter36,caracter37,caracter38,caracter39,caracter40,caracter41,
                    caracter42,caracter43,caracter44,caracter45,caracter46,caracter47,
                    caracter48,caracter49,caracter50,caracter51,caracter52,caracter53,
                    caracter54,caracter55,caracter56,caracter57,caracter58,caracter59,
                    caracter60,caracter61,caracter62,caracter63,caracter64,caracter65,
                    caracter66,caracter67,caracter68,caracter69,caracter70,caracter71,
                    caracter72,caracter73,caracter74,caracter75,caracter76,caracter77,
                    caracter78,caracter79,caracter80,caracter81,caracter82,caracter83};
#INT_EXT1
void int1_handler(){
   if(!botonPulsado){
      botonPulsado=1;
      modoFuncionamiento=!modoFuncionamiento;
      ciclosTimer1=400;               
      ext_int_edge(1,L_TO_H);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
      set_timer1(0);
   }else{      
      botonPulsado=0;      
      setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
      ext_int_edge(1,H_TO_L);     
      
   }   
}
#INT_TIMER1
void timer1_handler(){   
   if(--ciclosTimer1==0){         
      resetear=1;
   }   
}
#INT_AD
void ad_handler(){
   conversorOcupado=0;
}
#INT_TIMER0
void tmr_handler() {    
      //Apagar
      output_a(0);
      //Cambiar de columna
      if (columnaActual==5){
         columnaActual=0;
         if(caraEnVisualizacion!=cara){
            caraEnVisualizacion=cara;
         }
      }else{
         columnaActual++;
      } 
      //Preparar filas
      for(i=0;i<7;i++){
         output_bit(filas[i],*(caraEnVisualizacion+columnaActual)&(64>>i));
      }
      //Encender columna
      output_a(1<<columnaActual);      
      set_timer0(PRECARGA_TIMER);
}
void int mostrarTexto (int1 tipo, int parametro, int1 salirConSoplido, int1 atenuacionUmbralSoplido,int1 salirConBoton, int1 salirSoloFinal){
   unsigned int i,j;
   int16 contador=1;
   signed int columnasRestantes=0;//columnas que aún quedan 
   //por visualizar del caracterEntrante   
   int zonaTemporal[2][6]={0,0,0,0,0,0,0,0,0,0,0,0};//aquí se monta lo que se va a visualizan 
   //antes de pasárselo a *cara
   //si el bit más significativo es 1 el avance dentro de la animación es hacia
   //la derecha, y si es 0 el avance es hacia la izquierda (animaciones yo-yo).
   //Para que una columna sea animada, siguientePropietarioColumna debe contener
   //un valor distinto de 255
   int1 indiceZonaTemporalActiva=0;
   int1 incluirEspacioSufijo=1; 
   int1 actualizarVisualizacion=0;
   int1 mostrarInstantaneamente=0;
   int1 stopActivado=0;
   int1 siguienteCaracterEsAnimado=0;
   int1 sentidoDeAvance;
   int* caracterEntrante;//puntero al carácter entrante
   int longitudCaracterEntrante;   
   int posicionCaracterActual;//posición en la EEPROM del último carácter
   //leído   
   int propietarioActualColumna[6][2]={255,1,255,1,255,1,255,1,255,1,255,1};//en una animación, posición en la eeprom 
   //e índice de la columna dentro del carácter
   //del siguiente caracter que ocupará cada columna de zonaTemporal
   unsigned int longitudMensaje;
   //Apagar ojos
   output_low(PIN_C1);
   output_low(PIN_C2);
   if(salirConSoplido){
      enable_interrupts(INT_AD); 
      clear_interrupt(INT_AD);
      conversorOcupado=1;
      read_adc(ADC_START_ONLY);
   }
   if (tipo){              
      if(parametro>9){
         write_eeprom(7,((int)(parametro/10)));   
         delay_ms(20);                  
      }else{
         write_eeprom(7,250);         
         delay_ms(20);
      }
      write_eeprom(8,parametro-((int)(parametro/10))*10);         
      delay_ms(20);
      parametro=6; 
   }
   longitudMensaje=read_eeprom(parametro);   
   posicionCaracterActual=parametro;
   do{
      contador++;
      //Actualizar animación
      if(contador % ((int16)(VELOCIDAD_TEXTO/PROPORCION_ANIMACION_AVANCE))==0){
         actualizarVisualizacion=1;
         for(i=0;i<6;i++){
            j=read_eeprom(propietarioActualColumna[i][0]);            
            if(j!=255){//es una columna animada
               if(zonaTemporal[indiceZonaTemporalActiva][i]>128){
                  sentidoDeAvance=1;
               }else{
                  sentidoDeAvance=0;
               }               
               j=((zonaTemporal[indiceZonaTemporalActiva][i])<128?read_eeprom(propietarioActualColumna[i][0]-1):read_eeprom(propietarioActualColumna[i][0]+1));            
               switch(j){
                  case 251: //animacion yo-yo                         
                        if (sentidoDeAvance){//Va hacia la derecha                           
                           propietarioActualColumna[i][0]-=1;                           
                        }else{//va hacia la izquierda
                           propietarioActualColumna[i][0]+=1;
                        }
                        sentidoDeAvance=!sentidoDeAvance;
                     break;
                  case 252: //animacion diente de sierra                  
                     while(read_eeprom(propietarioActualColumna[i][0])!=252){
                        propietarioActualColumna[i][0]--;
                     }
                     break;
                  default:                  
                     if(sentidoDeAvance){
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]+1;
                     }else{
                        propietarioActualColumna[i][0]=propietarioActualColumna[i][0]-1;
                     }
               }
               //Actualizar columnas en zona temporal
               //Cuidadito con el bit más significativo para mantener el sentido
               //de la animación
               j=(caracter[read_eeprom(propietarioActualColumna[i][0])])[propietarioActualColumna[i][1]];
               if(sentidoDeAvance){
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j+128;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }
               }else{
                  if(j<128){
                     zonaTemporal[indiceZonaTemporalActiva][i]=j;
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][i]=j-128;
                  }                  
               }
            }         
         }         
      }
      //Actualizar avance
      if(contador>=VELOCIDAD_TEXTO){ 
         if(!stopActivado){
            actualizarVisualizacion=1;         
            if(columnasRestantes==0){
               if(longitudMensaje>0){
                  longitudMensaje--;
                  posicionCaracterActual++;
                  j=read_eeprom(posicionCaracterActual);
                  if(j>=240){
                     //gestión de caracteres reservados
                     switch (j){
                        case 247:
                           mostrarInstantaneamente=1;
                           stopActivado=1;
                           continue;
                           break;
                        case 248:
                           longitudMensaje=read_eeprom(parametro);   
                           posicionCaracterActual=parametro;
                           continue;
                           break;
                        case 249:                  
                           incluirEspacioSufijo=0;
                           continue;
                           break;
                        case 250:                                                      
                           continue;
                           break;
                        case 251:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 252:
                           siguienteCaracterEsAnimado=1;
                           continue;
                           break;
                        case 253:
                           contador=1;
                           continue;
                           break;
                        case 254:
                           longitudMensaje=0;
                           stopActivado=1;
                           continue;
                           break;                  
                     }
                  }else{                  
                     caracterEntrante=caracter[j];
                     columnasRestantes=0;
                     //Averiguar el número de columnas del carácter                        
                     while(!((caracterEntrante[columnasRestantes])&128)){
                        columnasRestantes++;               
                     };
                     columnasRestantes++;
                     longitudCaracterEntrante=columnasRestantes;
                  }                       
               }else{ 
                  if(salirConSoplido){
                     disable_interrupts(INT_AD);       
                  }
                  return;               
               }
            }
            if(columnasRestantes>0){
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               } 
               if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes];               
               }else{
                  zonaTemporal[indiceZonaTemporalActiva][5]=caracterEntrante[longitudCaracterEntrante-columnasRestantes]-128;                                 
                  //Para evitar interferencias con el sentido de la animación
               }
               if(siguienteCaracterEsAnimado){ 
                  propietarioActualColumna[5][1]=longitudCaracterEntrante-columnasRestantes;
                  if(columnasRestantes==longitudCaracterEntrante){
                     propietarioActualColumna[5][0]=posicionCaracterActual;                  
                  }else{
                     propietarioActualColumna[5][0]=propietarioActualColumna[4][0];                  
                  }
                  if(caracterEntrante[longitudCaracterEntrante-columnasRestantes]<128){
                     zonaTemporal[indiceZonaTemporalActiva][5]=(caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]];               
                  }else{
                     zonaTemporal[indiceZonaTemporalActiva][5]=((caracter[read_eeprom(propietarioActualColumna[5][0])])[propietarioActualColumna[5][1]])-128;
                     //Para evitar interferencias con el sentido de la animación
                  }                                    
                  //Se debe sumar 128 si la animación está actualmente
                  //avanzando hacia la derecha, es decir, si la columna entrante
                  //es la primera de la animación (todas las animaciones comienzan
                  //hacia la derecha), o si la columna entrante es posterior a la
                  //primera y la columna anterior es >=128
                  //No puede haber caracteres animados de una sola columna
                  if(propietarioActualColumna[5][1]==0){
                     zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                  }else{
                     if(zonaTemporal[indiceZonaTemporalActiva][4]>=128){
                        zonaTemporal[indiceZonaTemporalActiva][5]+=128;
                     }
                  }
               }else{
                  propietarioActualColumna[5][0]=255;
               }
               contador=1;
               columnasRestantes--;    
            }
            if(columnasRestantes==-1){
               columnasRestantes=0;
               incluirEspacioSufijo=0;
               for(i=0;i<5;i++){
                  zonaTemporal[indiceZonaTemporalActiva][i]=zonaTemporal[indiceZonaTemporalActiva][i+1];
                  propietarioActualColumna[i][0]=propietarioActualColumna[i+1][0];
                  propietarioActualColumna[i][1]=propietarioActualColumna[i+1][1];
               }
               zonaTemporal[indiceZonaTemporalActiva][5]=0; 
               propietarioActualColumna[5][0]=255;
               contador=1;
            }
            if(columnasRestantes==0){
               if (incluirEspacioSufijo==1){
                  columnasRestantes=-1;
               }else{
                  if(siguienteCaracterEsAnimado){                        
                     siguienteCaracterEsAnimado=0;                     
                     //Avanzar posicionCaracterActual
                     while(read_eeprom(posicionCaracterActual)!=251 && read_eeprom(posicionCaracterActual)!=252){                        
                        posicionCaracterActual++;
                     }
                  }                  
                  incluirEspacioSufijo=1;
               }
            }         
         }else{
            contador=1;
            if(mostrarInstantaneamente){
               stopActivado=0;
               mostrarInstantaneamente=0;
               posicionCaracterActual++;
               i=read_eeprom(posicionCaracterActual);
               caracterEntrante=caracter[i];
               for(j=0;j<6;j++){              
                  zonaTemporal[indiceZonaTemporalActiva][j]=caracterEntrante[j];
                  if(caracterEntrante[j]>=128){
                     zonaTemporal[indiceZonaTemporalActiva][j]-=128;
                  }
                  propietarioActualColumna[j][0]=255;
               }
            }
         }
      }
      //Actualizar visualizacion
      if (actualizarVisualizacion){
         cara=zonaTemporal[indiceZonaTemporalActiva];
         while(cara!=caraEnVisualizacion){
         }
         actualizarVisualizacion=0;         
         indiceZonaTemporalActiva=!indiceZonaTemporalActiva;            
         for(j=0;j<6;j++){
            zonaTemporal[indiceZonaTemporalActiva][j]=zonaTemporal[!indiceZonaTemporalActiva][j];
         }
      }
      
      //¿Detectar soplido?            
      if(salirConSoplido){         
         if(!salirSoloFinal || (salirSoloFinal && longitudMensaje==0 && columnasRestantes==0)){
            if(!conversorOcupado){
               conversorOcupado=1;
               j = read_adc(ADC_READ_ONLY);               
               read_adc(ADC_START_ONLY);
               if(atenuacionUmbralSoplido){
                 j+=30;
               }
               if (j>UMBRAL_SOPLIDO){
                  disable_interrupts(INT_AD);
                  return;
               }         
            }         
         }
      }
      //Detectar salida
      if(modoFuncionamiento){
         return;
      }
      //Detectar reset
      if(resetear){
         j=read_eeprom(1);
         write_eeprom(0,j);
         delay_ms(40);      
         reset_cpu();
      }
   }while(true);   
}
void main() {      
   unsigned int8 entradausb;
   unsigned int8 value, max;
   int comodin, comodin2;
   int16 comodin3, comodin4;
   int16 ciclosParaDormirse=UMBRAL_DORMIRSE;
   int modoCara=0;   
   unsigned int8 supremo=80;
   signed int caraActiva=0;   
   signed int8 acumuladorParpadeo;
   unsigned int32 periodo, muestra;     
   int bostezo[5][6]={0,8,40,104,8,0,0,8,44,108,8,0,0,12,42,106,12,0,0,14,41,105,14,0,0,15,41,105,15,0};  
         
   //caras del modo nariz aguileña
   int cara1[6]={0,4,108,44,4,0};                                       
   int cara2[6]={0,4,110,46,4};                                        
   int cara3[6]={0,6,106,42,6,0};   
   int cara4[6]={0,7,105,41,7,0};                    
   int cara5[6]={0,14,105,41,14,0};                                        
   int cara6[6]={12,10,105,41,10,12};                                    
   int cara7[6]={14,9,105,41,9,14};                                      
   int cara8[6]={15,9,105,41,9,15};                    
   //caras del modo nariz chata
   int cara9[6]={0,8,88,88,8,0};
   int cara10[6]={0,8,84,84,8,0};
   int cara11[6]={0,12,82,82,12,0};
   int cara12[6]={0,14,81,81,14,0};
   int cara13[6]={0,30,81,81,30,0};
   int cara14[6]={12,18,81,81,18,12};
   int cara15[6]={14,17,81,81,17,14};
   int cara16[6]={31,17,81,81,17,31};
   //caras del modo sin nariz
   int cara17[6]={8,8,8,8,8,8};
   int cara18[6]={28,20,20,20,20,28};
   int cara19[6]={62,34,34,34,34,62};
   int cara20[6]={127,65,65,65,65,127};
   //caras del modo luciano
   int cara21[6]={0,0,0,0,0,0};
   int cara22[6]={0,1,1,1,1,0};
   int cara23[6]={1,2,2,2,2,1};
   int cara24[6]={3,4,5,4,5,3};
   int cara25[6]={7,8,10,9,10,7};
   int cara26[6]={15,16,20,18,20,15};
   int cara27[6]={30,33,41,37,41,30};
   int cara28[6]={60,66,82,74,82,60};
   int const *caras[4][8]={cara1,cara2,cara3,cara4,cara5,cara6,cara7,cara8,
                           cara9,cara10,cara11,cara12,cara13,cara14,cara15,cara16,
                           cara17,cara17,cara18,cara18,cara19,cara19,cara20,cara20,
                           cara21,cara22,cara23,cara24,cara25,cara26,cara27,cara28};
                           
                           
   if(!input(PIN_B1)){
      usb_cdc_init();
      usb_init();
      output_low(PIN_C1);
      output_high(PIN_C2);
      while(!usb_cdc_connected()) {      
         delay_ms(200);
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);
      }
      do{
         usb_task();     
         if (usb_enumerated()) {
            printf(usb_cdc_putc, "PICTENGU");
            break;
         }
      }while (TRUE); 
      //Enviar contenido eeprom           
      output_high(PIN_C1);
      output_high(PIN_C2);
      entradausb=get_int_usb();         
      if(entradausb==246){
         delay_ms(1000);
         for(comodin3=0;comodin3<=255;comodin3++){             
            value=read_eeprom(comodin3);
            delay_ms(20);                     
            printf(usb_cdc_putc,"%c",value);      
         }
         output_toggle(PIN_C1);
         output_toggle(PIN_C2);                   
      }
      comodin3=0;
      do{
         usb_task();
         if(usb_enumerated()){
            entradausb=get_int_usb(); 
            if(entradausb!=246){
               write_eeprom(comodin3,entradausb);
               delay_ms(20);  
               comodin3++;
            }else{
               break;
            }
         }
      }while(true);       
   }     
   
   setup_adc_ports(PIN_B0);
   setup_adc(ADC_CLOCK_DIV_64 ); 
   set_adc_channel(12);
   ext_int_edge(1,H_TO_L);
   setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
   setup_timer_0(RTCC_8_BIT|RTCC_DIV_128);
   set_timer0(PRECARGA_TIMER);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_AD);   
   clear_interrupt(INT_AD);    
   enable_interrupts(INT_EXT1);   
   clear_interrupt(INT_EXT1);
   enable_interrupts(INT_TIMER1);   
   clear_interrupt(INT_TIMER1);
   enable_interrupts(GLOBAL);
   disable_interrupts(INT_EXT1);
        
   columnaActual=5;
   output_low(PIN_C1);
   output_low(PIN_C2);
   
   //Modo 1: dormido
   cara=bostezo[0];
   caraEnVisualizacion=cara;
   
   
   value=0;
   conversorOcupado=1;
   read_adc(ADC_START_ONLY);   
   while(value<UMBRAL_SOPLIDO-30){
      if(!conversorOcupado){
         conversorOcupado=1;
         value = read_adc(ADC_READ_ONLY);
         read_adc(ADC_START_ONLY);         
      }
   }   
   disable_interrupts(INT_AD);       
   
   //Modo 2: despertar: abre un ojo, luego el otro, luego bosteza
   //y pestañea 3 veces consecutivas
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   set_pwm2_duty(0);
   for(comodin=0;comodin<40;comodin++){        
      set_pwm1_duty(comodin);      
      delay_ms(30);
   }
   for(comodin=0;comodin<40;comodin++){             
      set_pwm2_duty(comodin);
      delay_ms(30);
   }   
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);
   output_low(PIN_C1);
   output_low(PIN_C2);
   for (comodin=0;comodin<5;comodin++){
      cara=bostezo[comodin];
      delay_ms(150);
   }
   delay_ms(1000);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_16, 255, 16);
   for (comodin=4;comodin>0;comodin--){//Con >= falla ¿por qué?
      cara=bostezo[comodin];   
      set_pwm1_duty((4-comodin)*10); 
      set_pwm2_duty((4-comodin)*10); 
      delay_ms(150);
   }
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_timer_2(T2_DISABLED, 255, 16);   
   for(comodin=1;comodin<=3;comodin++){
      output_low(PIN_C1);
      output_low(PIN_C2);
      delay_ms(300);
      output_high(PIN_C1);
      output_high(PIN_C2);
      delay_ms(300);
   }
   //Si en el primer byte de la memoria hay un valor distinto de 00...
   //comienza el juego del apagado de velas...
   //en caso contrario salta directamente al modo 3   
   comodin=read_eeprom(0);
   delay_ms(20);
   if(comodin!=0){
      write_eeprom(0,0);
      delay_ms(20);
      write_eeprom(1,comodin);
      delay_ms(20);      
      mostrarTexto(0,19,0,0,0,0);
      for(comodin2=1;comodin2<=comodin;comodin2++){         
         mostrarTexto(1,comodin2,1,1,0,1);
         cara=caracter66;
         delay_ms(500);
      }      
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
   }
   
   //Modo 3: Wilson
   modoFuncionamiento=1;
   output_high(PIN_C1);
   output_high(PIN_C2);  
   cara=cara1;
   caraEnVisualizacion=cara1;
   acumuladorParpadeo=0; 
   muestra=0;
   periodo=VELOCIDAD_GESTICULACION;   
   max=0;   
   enable_interrupts(INT_AD); 
   clear_interrupt(INT_AD);
   enable_interrupts(INT_EXT1);
   clear_interrupt(INT_EXT1);    
   conversorOcupado=1;
   read_adc(ADC_START_ONLY);
   
   do{
      if(modoFuncionamiento){      
         muestra++;
         if(!conversorOcupado){
            conversorOcupado=1;
            value = read_adc(ADC_READ_ONLY);
            read_adc(ADC_START_ONLY);            
            if(value>max){
               max=value;
            }
         }
         if(muestra==periodo){
            if(acumuladorParpadeo>0){
               output_high(PIN_C1);
               output_high(PIN_C2);
            }
            if(max>UMBRAL_SOPLIDO){//Soplido
               cara=cara21;
               if (modoCara<3){
                  modoCara++;
               }else{
                  modoCara=0;
               }
               output_low(PIN_C1);
               output_low(PIN_C2);
               for(comodin2=7;comodin2>0;comodin2--){
                  cara=caras[modoCara][comodin2];
                  delay_ms(100);
               }
               output_high(PIN_C1);
               output_high(PIN_C2);
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>supremo){
               caraActiva=7;
               acumuladorParpadeo+=8;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)6/7*supremo){
               caraActiva=6;                  
               acumuladorParpadeo+=7;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)5/7*supremo){
               caraActiva=5;
               acumuladorParpadeo+=6;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)4/7*supremo){
               caraActiva=4;
               acumuladorParpadeo+=5;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)3/7*supremo){
               caraActiva=3;
               acumuladorParpadeo+=4;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)2/7*supremo){
               caraActiva=2;
               acumuladorParpadeo+=3;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else if(max>(float)1/7*supremo){
               caraActiva=1;
               acumuladorParpadeo+=2;
               ciclosParaDormirse=UMBRAL_DORMIRSE;
            }else{
               caraActiva=0;
               acumuladorParpadeo+=1;
               ciclosParaDormirse--;
            }
            cara=caras[modoCara][caraActiva];
            if(max>supremo+UMBRAL_AUDICION){
               supremo=max-UMBRAL_AUDICION;
            }else{
               if(supremo>7*UMBRAL_AUDICION){
                  supremo--;
               }
            }
            if(acumuladorParpadeo>=UMBRAL_PARPADEO){
               output_low(PIN_C1);
               output_low(PIN_C2);
               acumuladorParpadeo=-1;
            }
            //printf(usb_cdc_putc, "\r\nSupremo=%6.0w",supremo );
            //printf(usb_cdc_putc, "\r\nCociente=%6.4f",(float)1/7*supremo );
            muestra=0;
            max=0;            
         }            
      }else{
      comodin3=read_eeprom(19);
      delay_ms(20);      
      mostrarTexto(0,20+comodin3,0,0,0,0);
      }
      if(resetear||ciclosParaDormirse==0){
         if(ciclosParaDormirse){
            comodin=read_eeprom(1);
            write_eeprom(0,comodin);
            delay_ms(40);     
         }
         reset_cpu();
      }
   }while (TRUE);      
}
```
 
saludos y buenas tardes


----------



## lubeck (Oct 2, 2010)

mira lo estoy revizando pero no lo encuentro...
en lo que me baso es esto..

#*fuses HSPLL,*NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN, CCP2C1
 el hspll es para un high speed oscilator y uno de 4mhz creeme que no lo es...


----------



## soopy_46 (Oct 2, 2010)

y esto?

#use delay(clock=48000000)
si es eso, que serian 48Mhz? esque sobre el calculo de osciladores no se mucho..

saludos y buenas  tardes


----------



## lubeck (Oct 2, 2010)

eso me sospecho que es de 48mhz pero me gustaria confirmarlo...


----------



## soopy_46 (Oct 2, 2010)

mmm vale.. okey gracias, ahora tambien mirare a ver si encuentro algo..
sino.. el lunes a por un oscilador de 48mhz.. jeje
variaria mucho mucho del precio de uno de 4mhz por ejemplo?

no se si te servira de mucho pero cuando yo abro el archivo .hex en el winpic800 la configuracion predeterminada que se me pone es esta:


----------



## lubeck (Oct 2, 2010)

> variaria mucho mucho del precio de uno de 4mhz por ejemplo?


ni idea....
dejame seguir revizando y verificar que si sea ese de 48mhz


----------



## soopy_46 (Oct 2, 2010)

puede ser por eso alguno de los errores que tiene? 
no captar sonido
no conectar con pc (y extraer o añadir informacion a la eeprom)
etc?


----------



## lubeck (Oct 2, 2010)

> puede ser por eso alguno de los errores que tiene?
> no captar sonido
> no conectar con pc (y extraer o añadir informacion a la eeprom)
> etc?



por supuesto que si...
imagina que tu mente esta programda para una velocidad de 48mhz y tu escuchas a una velocidad de 4mhz como imaginas que escucharias?


----------



## soopy_46 (Oct 2, 2010)

mmm tambien es verdad jeje
gracias pues, entonces que hago?
compro un oscilador de 48Mhz ?

porque no habria el caso (por hacer la prueva) de hacer el clock con un 555 y un pic16f628a o algo al estilo? luego la cosa seria que mandara la señal por dos de las patillas, provar que funciona bien, y en ese caso el lunes comprar el oscilador, sino, ya paso directamente a lo del lunes jeje

acabo de leer esto:
http://www.ucontrol.com.ar/forosmf/explicaciones-y-consultas-tecnicas/mhz-de-pic16-y-pic18/



> Se que en un PIC16 Si metes un crista de 4MHz funcionará a 4MHz, si metes 20MHz funcionará a 20MHz. Me pareció leer hace tiempo que los PIC18 no es así.
> 
> En PIC18 puedes poner 8MHz y son 8MHz, si pones 20MHz son 20MHz, ahora si quieres que el PIC18 funcione a 48MHz tienes que poner el crista de 20MHz y no 48MHz.
> 
> ¿Es cierto?


 escrito en el link


----------



## lubeck (Oct 2, 2010)

> gracias pues, entonces que hago?
> compro un oscilador de 48Mhz ?



estoy un 90% seguro que si es uno de 48Mhz y que esa es la razon mas posible del poque no esta funcionando... y tomando en cuenta que puede haber otros problemas pero eso ya seria analizarlo despues...

djejeje.. editaste tu mensaje ya estoy en duda de los 20Mhz....



> porque no habria el caso (por hacer la prueva) de hacer el clock con un 555 y un pic16f628a o algo al estilo? luego la cosa seria que mandara la señal por dos de las patillas, provar que funciona bien, y en ese caso el lunes comprar el oscilador, sino, ya paso directamente a lo del lunes jeje


un 555 no llega a esas frecuencias si mal no recuerdo llegan a 2 mhz o 4mhz como maximo revizalo...


----------



## soopy_46 (Oct 2, 2010)

y con el pic? tampoco seguramente verdad?
luego en la configuracion del winpic800 cuando hago la configuracion, me deja hasta 48Mhz pero si lo leo entero dice lo siguiente:
Divided by 12 (48Mhz input)  Esto en Oscilator Selection
Divided by  5 (20Mhz input) este claro esta que es de 20

y la configuracion del vbor, el cpu system clock, y el watchdog, cuales tendrian que ser?


----------



## lubeck (Oct 2, 2010)

> y con el pic? tampoco seguramente verdad?


no tampoco... 

mira ahorita estoy un poco ocupado... dejame verificar bien eso si es de 20 o 48 u otro...

los fuses tengo entendido son para que ya no le tengas que mover a nada en el winpic800 y si el winpic marca 20mhz puede ser ese el cristal....
estuve buscando informacion en los documentos que me enviaste pero al parecer en ningun lado dice de cuanto es... 

dame un par de horas porfa....


----------



## soopy_46 (Oct 2, 2010)

okay, ningun problema


----------



## ByAxel (Oct 2, 2010)

Hola, estaba leyendo el hilo, parece que tienen una confusión sobre los fuses del PIC18... 
revisen este link Consiguiendo 4 Mhz para los 48 Mhz necesarios en los PIC's con USB 2.0 para configurar bien el oscilador...

*soopy_46*, configurar el oscilador con el WinPic800 también es valido pero ten en cuenta al compilador CCS cuya directiva #use delay() es usada para calcular tiempos (usados comúnmente en las instrucciones de delay) pero no configura nada del oscilador...

El módulo del oscilador para PIC's con USB tiene la posibilidad de hacer trabajar la CPU a una velocidad distinta al del módulo del USB (revisen el datasheet) y cuando configuren los fuses, revisen que la velocidad para el CPU sea la misma que pongan en #use delay() para los cálculos del CCS...

Sobre eso hay más info por acá Control de dispositivos a través del módulo USB del PIC18F2550

saludos.


----------



## soopy_46 (Oct 2, 2010)

ya pero teoricamente sobre el codigo no tendria porque cambiar ahora nada, ya que el codigo ya esta hecho para que funcione... el problema esque no he visto ni el valor delo osc. (por eso hemos pensado en el de 20/48mhz y lo unico que falla respecto al ordenador es el winpic800 que no se exactamente que configurarle pero..
me leere los dos link que has puesto y ya luego miro si me sirve.
saludos

pd. lo del winpic800 y el codigo lo digo por lo que ha dicho antes lubeck que los fuses pueden configurar el winpic (esque no se de otra manera de decirlo.. :S) entonces me sale con esa configuracion


----------



## ByAxel (Oct 2, 2010)

No uso el WinPIC800 asi que de una imagen e resaltado en rojo lo importante para el USB...
- Si usas un cristal de 20Mhz el oscilador debe ser HS, HS used by USB
- Divided by 5 para que obtengan los 48Mhz necesarios para el USB.
- CPU System Clock > No divide. Para que el CPU corra a 48Mhz y en el CCS #use delay(48Mhz).
- USB PLL y VREGEN.

saludos


----------



## lubeck (Oct 2, 2010)

Igual yo te agradezco el apoyo ByAxel.. estaba un poco confundido


----------



## soopy_46 (Oct 2, 2010)

entonces.. hago..?
lo de la configuracion.. creo que la tengo clara pero.. entonces tengo que cambiar algo a la programacion?
saludos

y que oscilador uso?


----------



## lubeck (Oct 2, 2010)

> y que oscilador uso?


compra uno de 20mhz

los fuses del ccs configuran automaticamente al winpic800


----------



## soopy_46 (Oct 2, 2010)

ok
ara que recuerdo.. eso de hacer con el pic 16f628a un oscilador lo he dicho porque un dia creo haber leido algo de eso o quizas recuerde mal, que es lo mas seguro..
bueno pues, el lunes de buena mañana voy a por el oscilador y cuento que tal me ha ido

saludos y buenas noches


----------



## soopy_46 (Oct 3, 2010)

en el hipotetico caso de que no funcionara con el cristal de 20Mhz y seria un problema grande verdad?..
bueno.. creo que si que podra ir, eso espero.. y muchas gracias a los que me habeis ayudado con esto 
saludos y buenas tardes


----------



## soopy_46 (Oct 4, 2010)

... pequeñas grandes noticias.. y malas..no consigo hacer que vaya.. algo creo que se debe al winpic...

me podriais decir cual es la configuracion de la tabla que adjunto?


saludos buenas tardes


----------



## lubeck (Oct 4, 2010)

ya le pusiste el oscilador de 20Mhz???
hizo algo diferente.... que?


----------



## soopy_46 (Oct 4, 2010)

ah porcierto, el oscilador es de 20Mhz como quedamos al final..

ups
no hace nada nuevo.. tampoco reacciona al micro..
porcierto.. el programa ese, el pic_tengu.exe, podria abrirlo de algun modo? osea poder ver los codigos?


----------



## lubeck (Oct 4, 2010)

> me podriais decir cual es la configuracion de la tabla que adjunto?


ya intentaste sin cambiarle nada???
el archivo hex lo configura al cargarlo...


----------



## soopy_46 (Oct 4, 2010)

si
sin cambiar nada tambien falla... :S


----------



## lubeck (Oct 4, 2010)

Que pic usas y que archivo hex le estas grabando....
trae uno  para el 2455  y otro para el 2550


----------



## soopy_46 (Oct 4, 2010)

grabo en un pic18f2455 el archivo .hex del 2455


----------



## lubeck (Oct 4, 2010)

> porcierto.. el programa ese, el pic_tengu.exe, podria abrirlo de algun modo? osea poder ver los codigos?


necesitas java... uno viene en el visual studio , pero los codigos que trae no se para que version es,,,


----------



## soopy_46 (Oct 4, 2010)

mmm... aun asi.. hay el v0 que este solo hace la funcion de hablar.. y este no necesita conectarse al programa.. y tampoco va..
por cierto, con el JDK (o algo asi no recuerdo bien..) lo podria mirar?

puede ser que no este bien la placa?


----------



## lubeck (Oct 4, 2010)

> por cierto, con el JDK (o algo asi no recuerdo bien..) lo podria mirar?


pues podrias intentarlo... yo Java nunca lo he usado... y desconozco con que version se hizo...

que estas poniendo un parlante o un microfono electrec...?

por fin corrobore y si lleva un cristal de 20mhz... dale en propiedades del micro en el archivo de proteus y ahi dice de 20mhz...


----------



## soopy_46 (Oct 4, 2010)

creo que ya se que le pasa.. la placa esta mal.. ahora os paso el archivo de pcb wizard y el esquema que llevaba la carpeta (recuerdo que esta hecha con proteus y no estan ni los positivos ni los negativos de los componentes)

en la carpeta pictengu dos placas, estan los esquemas de la placa de leds y la del pic, la que me interesa es la del pic, y luego en pdf el esquema normal.. el que venia con la carpeta


----------



## lubeck (Oct 4, 2010)

Lo primero que noto es que el uln esta diferente al esquema original, deberias darle una buena revizada...


----------



## soopy_46 (Oct 4, 2010)

ya pero al uln no le pasa nada ya que por lo que he visto funciona bien y en su buena direccion

y añado que acabo de mirar una a una las pistas y van a sus correspondientes pines


----------



## lubeck (Oct 4, 2010)

Yo ya hice el simulado en proteus y el micro si funciona si hace el barrido de los leds, pero es obvio que la señal del micro no funciona...
yo me voy por la tarjeta amigo... algo anda mal...


----------



## soopy_46 (Oct 4, 2010)

> pero es obvio que la señal del micro no funciona...


a que te refieres?
he mirado todas una a una las pistas en la placa (que no se tocara ninguna entre si) y en el pcbwizard, y todo bien..


----------



## lubeck (Oct 4, 2010)

> a que te refieres?
> he mirado todas una a una las pistas en la placa (que no se tocara ninguna entre si) y en el pcbwizard, y todo bien..


oohh  a que no puedo simular el microfono... perdon 

me refiero a que el microfono sea correcto o el potenciometro este ajustado, la fuente sea la correcta etc etc, en general los problemas comunes del hardware...


----------



## soopy_46 (Oct 4, 2010)

entonces ya.. que mas me queda probar?

no hay otro tipo de simulador con el que pueda mirar lo del microfono?
puede ser tambien que el lm358 no este bien?


----------



## soopy_46 (Oct 4, 2010)

por fin consigo que hacer vaya

debo pedirte las gracias lubeck, ya que sin tus ayudas y consejos no hubiera conseguido hacer que esto funcionara... ya que me he encontrado con problemas que no me imaginaba que fueran a suceder...
por eso pido gracias por ayudarme a acabar este proyecto, almenos ubn 90% (que ahora me falta lo de conectar al pc) que tengo que cambiar lo de los condensadores.. espero que sea eso
saludos y buenas noches

PD. Cuando este 100% acabado colgare un video

corrijo una cosa, "Porfin HEMOS conseguido hacer que vaya"


----------



## philoupat6283 (Dic 22, 2014)

Hola
Buenos días soopi.
Yo repite el Proyecto pictengu y tengo el mismo problema que les con error cuando compilo a la línea 158 luego siguiente y 224. Cómo le hiciste para compilar él tiene allí tú él un error. Gracias


----------

