I'm searching UART code for pic18f65k40, but i haven't found yet.
Could anyone please provide a sample code to transmit a single character using pic18f65k40 uart.
This is the driver from my neolight theatre lighting controller. It is for a PIC18F14K22, but should be close enough to give you a start. This board also bit bangs the extremely fast protocol for the World Semi LEDs, hence the comment about timing.
/* Neolight board optional UART support. The UART is used as an
alternative to contact closures to trigger effects, and can be used
to download completely arbitrary patterns to the LEDS.
NOTE that during a write to the LEDs there are NO cycles left over
to operate the UART, so it does not work during updates. The
protocol reflects this.
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "neolight.h"
/* Baud rate calculation */
#define brgh 1 /* Use high rate mode */
#if brgh
#define divisor 4
#else
#define divisor 64
#endif
/* Macros to compute baud rate setup at compile time */
#define spbrg ( ( (long) Fosc ) / ( (long) divisor * (long) ( baud_rate ) ) - 1 )
#define spbrgl ( spbrg & 0xFF )
#define spbrgh ( ( spbrg >> 8 ) & 0xFF )
/* Turn on the UART and set baud rate */
void uart_setup ()
{
RCSTAbits . SPEN = 1 ;
BAUDCONbits . BRG16 = 1 ;
TXSTAbits . TXEN = 1 ;
TXSTAbits . BRGH = brgh ;
RCSTAbits . CREN = 1 ;
SPBRG = spbrgl ;
SPBRGH = spbrgh ;
}
/* Send data to UART */
void uart_send ( unsigned char * buffer, int count )
{
int n ;
for ( n = 0; n < count; n++ )
{
while ( !TXSTAbits . TRMT ) ;
TXREG = buffer [ n ] ;
}
}
/* Receive from UART, return -1 if no char */
int uart_receive ()
{
if ( RCSTAbits . OERR )
{
RCSTAbits . CREN = 0 ;
RCSTAbits . CREN = 1 ;
}
if ( PIR1bits . RCIF )
return RCREG ;
else
return -1 ;
}
void Setup_UART(void)
{
TX1STA = 0b00100100;
RC1STA = 0b00010000;
BAUDCON1 = 0b00001000;
SP1BRGL = xxx; //Baudrate value, look at datasheet
SP1BRGH = xxx;
RCSTA1bits.SPEN = 1;
}
void Send_Byte(uint8_t Data)
{
while (!PIR3bits.TXIF);
TX1REG = Data;
}
This example works for the PIC1827k40. Please have a look at the datasheet for your controller.
Related
I am using a Microchip Pic24f board to receive 3 analog inputs from a accelerometer.
I am getting a signal for AN0 but for AN1 and AN2 there is a signal but the values are not right.
Here is the code where I initialize ADC.
void InitADC(int amask) {
AD1PCFG = 0xFFF8; // select AN0, AN1, AN2 as analog input
AD1CON1 = 0x00E0; // auto convert # end of sampling, Integer Data in.
AD1CON2 = 0x0000; // use MUXA, AVss and AVdd used as Vref
AD1CON3 = 0x1F01; // Tad = 2xTcy = 125ns. 31*Tad for conversion time.
AD1CSSL = 0; // no scanning required
AD1CHS=0;
AD1CHS=1;
AD1CHS=2;
AD1CON1bits.ADON = 1; // Turn on the ADC
} // InitADC
In the main():
TRISBbits.TRISB0 = 1;
TRISBbits.TRISB1 = 1;
TRISBbits.TRISB2 = 1;
I then read AD1PCFG = 0xFFFE; for each analog input in a different function.
The results of the inputs are read in by in that same function
return ADC1BUF0;
I am not sure if for the PIC24f if I need to use ADC1BUFx for each ANx analog input or if I can read the signals through just ADC1BUF0.
Also I do not know if I need to scan and for AD1CON2 the configuration needs to be different because of the multiple analog inputs being used.
I am fairly new to PIC24f and have searched everywhere for help and everything that I was able to try got me to get the signals to be read on the LCD but AN1 and AN2 data is not what it is supposed to be.
If anyone could help me that it would be appreciated.
This is an example that show how I implemented what is found in the Microchip family reference manual describing the type of ADC you may be using:
/*
* File: main.c
* Author: dan1138
* Target: PIC24FJ64GA002
* IDE: MPLABX v5.45
* Compiler: XC16 v1.61
*
* Description:
*
* Initialize the ADC to convert voltage levels present on AN0, AN1 and AN5
*
* Map UART1 with TXD on RB0 and RXD on RB1.
* Map UART2 with TXD on RB8 and RXD on RB8.
*
* Initialize UART2 at 9600 baud and hook to printf.
*
* Created on March 11, 2021, 1:46 PM
*
* See: https://stackoverflow.com/questions/66552251/i-do-not-know-if-i-am-initializing-adc-correctly-for-pic24f
*
* PIC24FJ64GA002
* +-----------------:_:-----------------+
* ICD_VPP -> : 1 MCLR VDD 28 : <- 3v3
* <> : 2 RA0/RP26/AN0 VSS 27 : <- GND
* <> : 3 RA1/RP27/AN1 AN9 /RP15/RB15 26 : <> LED4
* ICD_PGD <> : 4 RB0/PGD1/AN2 AN10/RP14/RB14 25 : <> LED5
* ICD_PGC <> : 5 RB1/PGC1/AN3 AN11/RP13/RB13 24 : <> LED6
* <> : 6 RB2/RP2/AN4 AN12/RP12/RB12 23 : <> LED7
* POT <> : 7 RB3/RP3/AN5 RP11/RB11 22 : <>
* GND -> : 8 VSS RP10/RB10 21 : <>
* 7.3728MHz <> : 9 RA2/OSCI VCAP 20 : <- 10uF
* 7.3728MHz <> : 10 RA3/OSCO VSS 19 : <- GND
* <> : 11 RB4/SOSC RP9 /RB9 18 : <> RXD
* <> : 12 RA4/SOSC RP8 /RB8 17 : <> TXD
* 3v3 -> : 13 VDD INT0/ RP7 /RB7 16 : <>
* SW1 <> : 14 RB5/RP5 RP6 /RB6 15 : <>
* +-------------------------------------+
* DIP-28
*
*/
// CONFIG2
#pragma config POSCMOD = NONE // Primary Oscillator Select (Primary oscillator disabled)
#pragma config I2C1SEL = PRI // I2C1 Pin Location Select (Use default SCL1/SDA1 pins)
#pragma config IOL1WAY = OFF // IOLOCK Protection (IOLOCK may be changed via unlocking seq)
#pragma config OSCIOFNC = ON // Primary Oscillator Output Function (OSC2/CLKO/RC15 functions as port I/O (RC15))
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor (Clock switching and Fail-Safe Clock Monitor are disabled)
#pragma config FNOSC = FRCPLL // Oscillator Select (Fast RC Oscillator with PLL module (FRCPLL))
#pragma config SOSCSEL = SOSC // Sec Oscillator Select (Default Secondary Oscillator (SOSC))
#pragma config WUTSEL = LEG // Wake-up timer Select (Legacy Wake-up Timer)
#pragma config IESO = ON // Internal External Switch Over Mode (IESO mode (Two-Speed Start-up) enabled)
// CONFIG1
#pragma config WDTPS = PS32768 // Watchdog Timer Postscaler (1:32,768)
#pragma config FWPSA = PR128 // WDT Prescaler (Prescaler ratio of 1:128)
#pragma config WINDIS = ON // Watchdog Timer Window (Standard Watchdog Timer enabled,(Windowed-mode is disabled))
#pragma config FWDTEN = OFF // Watchdog Timer Enable (Watchdog Timer is disabled)
#pragma config ICS = PGx1 // Comm Channel Select (Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1)
#pragma config GWRP = OFF // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF // JTAG Port Enable (JTAG port is disabled)
#define FCY (16000000ul) // This define allows the delay macros to work
#include "xc.h"
#include <libpic30.h>
#include <stdio.h>
/* define map input pin numbers */
enum
{
RPI0 = 0, /* pin RB00 */ /* PGC1 */
RPI1, /* pin RB01 */ /* PGD1 */
RPI2, /* pin RB02 */
RPI3, /* pin RB03 */
RPI4, /* pin RB04 */
RPI5, /* pin RB05 */
RPI6, /* pin RB06 */
RPI7, /* pin RB07 */
RPI8, /* pin RB08 */
RPI9, /* pin RB09 */
RPI10, /* pin RB10 */
RPI11, /* pin RB11 */
RPI12, /* pin RB12 */
RPI13, /* pin RB13 */
RPI14, /* pin RB14 */
RPI15, /* pin RB15 */
RPI_NONE = 0x1f
};
/* define map output function numbers */
enum
{
RPO_NONE = 0,
RPO_C1OUT,
RPO_C2OUT,
RPO_U1TX,
RPO_U1RTS,
RPO_U2TX,
RPO_U2RTS,
RPO_SDO1,
RPO_SCK1OUT,
RPO_SS1OUT,
RPO_SDO2,
RPO_SCK2OUT,
RPO_SS2OUT,
RPO_OC1=18,
RPO_OC2,
RPO_OC3,
RPO_OC4,
RPO_OC5,
};
/* Initialize this PIC */
void
PIC_Init(
void
)
{
/*
** Disable all interrupt sources
*/
__builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */
IEC0 = 0;
IEC1 = 0;
IEC2 = 0;
IEC3 = 0;
IEC4 = 0;
__builtin_disi(0x0000); /* enable interrupts */
CLKDIV = 0x0000; /* set for default clock operations */
AD1PCFG = 0xffff; /* Set for digital I/O */
#ifdef AD1PCFGH
AD1PCFGH = 0xffff;
#endif
CMCON = 0x0000;
_NSTDIS = 1; /* disable interrupt nesting */
TRISA = 0xFFFF;
TRISB = 0xFFFF;
/* Unlock Registers */
__builtin_write_OSCCONL(OSCCON & ~_OSCCON_IOLOCK_MASK);
/* map inputs */
_INT1R = RPI_NONE; /* External Interrupt 1 */
_INT2R = RPI_NONE; /* External Interrupt 2 */
_T2CKR = RPI_NONE; /* Timer2 External Clock */
_T3CKR = RPI_NONE; /* Timer3 External Clock */
_T4CKR = RPI_NONE; /* Timer4 External Clock */
_T5CKR = RPI_NONE; /* Timer5 External Clock */
_IC1R = RPI_NONE; /* Input Capture 1 */
_IC2R = RPI_NONE; /* Input Capture 2 */
_IC3R = RPI_NONE; /* Input Capture 3 */
_IC4R = RPI_NONE; /* Input Capture 4 */
_IC5R = RPI_NONE; /* Input Capture 5 */
_OCFAR = RPI_NONE; /* Output Compare Fault A */
_OCFBR = RPI_NONE; /* Output Compare Fault B */
_U1RXR = RPI1; /* UART1 Receive */
_U1CTSR = RPI_NONE; /* UART1 Clear To Send */
_U2RXR = RPI9; /* UART2 Receive */
_U2CTSR = RPI_NONE; /* UART2 Clear To Send */
_SDI1R = RPI_NONE; /* SPI1 Data Input */
_SCK1R = RPI_NONE; /* SPI1 Clock Input */
_SS1R = RPI_NONE; /* SPI1 Slave Select Input */
_SDI2R = RPI_NONE; /* SPI2 Data Input */
_SCK2R = RPI_NONE; /* SPI2 Clock Input */
_SS2R = RPI_NONE; /* SPI2 Slave Select Input */
/* map outputs */
_RP0R = RPO_U1TX; /* U1 TXD */ /* pin RB00 */ /* PGC1 */
_RP1R = RPO_NONE; /* U1 RXD */ /* pin RB01 */ /* PGD1 */
_RP2R = RPO_NONE; /* pin RB02 */
_RP3R = RPO_NONE; /* pin RB03 */
_RP4R = RPO_NONE; /* pin RB04 */
_RP5R = RPO_NONE; /* pin RB05 */
_RP6R = RPO_NONE; /* pin RB06 */
_RP7R = RPO_NONE; /* pin RB07 */
_RP8R = RPO_U2TX; /* U2 TXD */ /* pin RB08 */
_RP9R = RPO_NONE; /* U2 RXD */ /* pin RB09 */
_RP10R = RPO_NONE; /* pin RB10 */
_RP11R = RPO_NONE; /* pin RB11 */
_RP12R = RPO_NONE; /* pin RB12 */
_RP13R = RPO_NONE; /* pin RB13 */
_RP14R = RPO_NONE; /* pin RB14 */
_RP15R = RPO_NONE; /* pin RB15 */
/* Lock Registers */
__builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK);
}
/*
* Initialize the ADC
*/
static const uint8_t Selector[] = {0x00,0x01,0x05};
void ADC_Init(void)
{
AD1PCFGbits.PCFG0 = 0; /* AN0/RA0 */
AD1PCFGbits.PCFG1 = 0; /* AN1/RA1 */
AD1PCFGbits.PCFG5 = 0; /* AN5/RB3 */
TRISAbits.TRISA0 = 1;
TRISAbits.TRISA1 = 1;
TRISBbits.TRISB3 = 1;
AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling and starts converting
AD1CHS = 0x0000; // default to channel 0
AD1CSSL = 0;
AD1CON3 = 0x0102; // Manual Sample, TAD = 3 TCY, Auto-Sample Time 1 TAD
AD1CON2 = 0;
AD1CON1bits.ADON = 1; // turn ADC ON
}
/*
* ADC Read channel
*/
uint16_t ADC_ReadChannel(uint16_t Index)
{
if(Index < sizeof(Selector))
{
AD1CHSbits.CH0SA = Selector[Index];
}
AD1CON1bits.SAMP = 1; // start sampling...
__delay_us(5); // Ensure the correct sampling time has elapsed before starting conversion.
AD1CON1bits.SAMP = 0; // start converting
for(;;)
{
if(AD1CON1bits.DONE) break; // conversion done?
}
return ADC1BUF0; // yes then get ADC value
}
/*
* Initialize UART2
*/
#define U2_BAUD 9600L
#define U2_BRGH_VALUE 0
#if U2_BRGH_VALUE
#define U2_BRGH_SCALE 4L
#else
#define U2_BRGH_SCALE 16L
#endif
#define U2_BRGREG (FCY/(U2_BRGH_SCALE * U2_BAUD)-1L)
#if U2_BRGREG > 65535
#error Cannot set up UART2 for the FCY and BAUDRATE. Correct values in init.h and uart.h files.
#endif
/*
** Check if baud error greater than 2.5 percent
*/
#define REAL_BAUDRATE ( FCY / ( U2_BRGH_SCALE * ( U2_BRGREG + 1L) ) )
#if (REAL_BAUDRATE > (U2_BAUD + (U2_BAUD * 25L) / 1000L)) || (REAL_BAUDRATE < (U2_BAUD - (U2_BAUD * 25L) / 1000L))
#error UART baudrate error greater than 2.5 percent for the FCY and U2_BAUD. Correct values in uart.c file.
#endif
#undef REAL_BAUDRATE
void UART2_Init(void)
{
_U2TXIE = 0;
_U2RXIE = 0;
_U2ERIE = 0;
_U2RXIP = 0b100;
_U2TXIP = 0b100;
_U2ERIP = 0b100;
U2MODE = 0;
U2STA = 0;
U2BRG = U2_BRGREG;
U2MODEbits.BRGH = U2_BRGH_VALUE;
U2MODEbits.UARTEN = 1;
U2STAbits.UTXEN = 1;
}
void UART2_Write(uint8_t txData)
{
while(U2STAbits.TRMT != 1);
U2TXREG = txData; // Write the data byte to the USART.
}
/*
* hook for printf
*/
int __attribute__((__section__(".libc.write"))) write(int handle, void *buffer, unsigned int len)
{
unsigned int i;
for (i = len; i; --i)
{
UART2_Write(*(char*)buffer++);
}
return(len);
}
/*
* Main Application
*/
int main(void)
{
uint16_t ADC_results[sizeof(Selector)];
uint16_t ADC_value;
uint16_t NewResults;
uint16_t Index;
PIC_Init();
ADC_Init();
UART2_Init();
printf("\r\nPIC24FJ64GA002 start, built on %s at %s\r\n", __DATE__, __TIME__);
/*
* Application loop
*/
NewResults = 1;
for(;;)
{
for(Index = 0; Index < sizeof(Selector); Index++)
{
ADC_value = ADC_ReadChannel(Index);
if (ADC_value != ADC_results[Index])
{
NewResults |= 1;
}
ADC_results[Index] = ADC_value;
}
if(NewResults)
{
NewResults = 0;
printf("Values");
for(Index = 0; Index < (sizeof(ADC_results)/sizeof(*ADC_results) ); Index++)
{
printf(" AN%1u = %5u", Selector[Index], ADC_results[Index]);
}
printf("\r\n");
}
}
return 0;
}
You do not provide enough information in your post to know which one of the 55 controllers you may actually be using.
I used the PIC24FJ64GA002 controller that I can find right now that has the ADC hardware you could be using.
I'm trying to capture images with XGetImage. Everything fine but I need to send the data to a module which expects an array of RGB quads. Calling XGetPixel for every pixel in the image is very slow (0.5 seconds on a i5 for 1440x900 resolution). I've looked up the XGetPixel source code in xlib and the reason is obvious, a lot of computations are done for each pixel.
Is there any efficient (or maybe completely different) way of doing this?
With the MIT Shared Memory Extension you can store an image in a shared memory area. This way you avoid going through the Xlib IPC channel when processing the image.
You can get or set the contents of a drawable with XShmGetImage and XShmPutImage respectively.
You can't resize the shared memory area, you have to destroy it and create a new one.
The next utility takes a screenshot, sets the alpha channel of all pixels to 0xFF and saves it to the specified file.
It assumes the pixels are 32 bits BGRA, you should handle all packed pixel formats.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <stdbool.h>
#include <png.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#define NAME "screenshot"
#define BPP 4
struct shmimage
{
XShmSegmentInfo shminfo ;
XImage * ximage ;
unsigned int * data ; // will point to the image's BGRA packed pixels
} ;
void initimage( struct shmimage * image )
{
image->ximage = NULL ;
image->shminfo.shmaddr = (char *) -1 ;
}
void destroyimage( Display * dsp, struct shmimage * image )
{
if( image->ximage )
{
XShmDetach( dsp, &image->shminfo ) ;
XDestroyImage( image->ximage ) ;
image->ximage = NULL ;
}
if( image->shminfo.shmaddr != ( char * ) -1 )
{
shmdt( image->shminfo.shmaddr ) ;
image->shminfo.shmaddr = ( char * ) -1 ;
}
}
int createimage( Display * dsp, struct shmimage * image, int width, int height )
{
// Create a shared memory area
image->shminfo.shmid = shmget( IPC_PRIVATE, width * height * BPP, IPC_CREAT | 0600 ) ;
if( image->shminfo.shmid == -1 )
{
perror( NAME ) ;
return false ;
}
// Map the shared memory segment into the address space of this process
image->shminfo.shmaddr = (char *) shmat( image->shminfo.shmid, 0, 0 ) ;
if( image->shminfo.shmaddr == (char *) -1 )
{
perror( NAME ) ;
return false ;
}
image->data = (unsigned int*) image->shminfo.shmaddr ;
image->shminfo.readOnly = false ;
// Mark the shared memory segment for removal
// It will be removed even if this program crashes
shmctl( image->shminfo.shmid, IPC_RMID, 0 ) ;
// Allocate the memory needed for the XImage structure
image->ximage = XShmCreateImage( dsp, XDefaultVisual( dsp, XDefaultScreen( dsp ) ),
DefaultDepth( dsp, XDefaultScreen( dsp ) ), ZPixmap, 0,
&image->shminfo, 0, 0 ) ;
if( !image->ximage )
{
destroyimage( dsp, image ) ;
printf( NAME ": could not allocate the XImage structure\n" ) ;
return false ;
}
image->ximage->data = (char *)image->data ;
image->ximage->width = width ;
image->ximage->height = height ;
// Ask the X server to attach the shared memory segment and sync
XShmAttach( dsp, &image->shminfo ) ;
XSync( dsp, false ) ;
return true ;
}
void getrootwindow( Display * dsp, struct shmimage * image )
{
XShmGetImage( dsp, XDefaultRootWindow( dsp ), image->ximage, 0, 0, AllPlanes ) ;
// This is how you access the image's BGRA packed pixels
// Lets set the alpha channel of each pixel to 0xff
int x, y ;
unsigned int * p = image->data ;
for( y = 0 ; y < image->ximage->height; ++y )
{
for( x = 0 ; x < image->ximage->width; ++x )
{
*p++ |= 0xff000000 ;
}
}
}
void initpngimage( png_image * pi, struct shmimage * image )
{
bzero( pi, sizeof( png_image ) ) ;
pi->version = PNG_IMAGE_VERSION ;
pi->width = image->ximage->width ;
pi->height = image->ximage->height ;
pi->format = PNG_FORMAT_BGRA ;
}
int savepng( struct shmimage * image, char * path )
{
FILE * f = fopen( path, "w" ) ;
if( !f )
{
perror( NAME ) ;
return false ;
}
png_image pi ;
initpngimage( &pi, image ) ;
unsigned int scanline = pi.width * BPP ;
if( !png_image_write_to_stdio( &pi, f, 0, image->data, scanline, NULL) )
{
fclose( f ) ;
printf( NAME ": could not save the png image\n" ) ;
return false ;
}
fclose( f ) ;
return true ;
}
int main( int argc, char * argv[] )
{
if( argc != 2 )
{
printf( "Usage:\n" ) ;
printf( " " NAME " file\n\n" ) ;
return 0 ;
}
Display * dsp = XOpenDisplay( NULL ) ;
if( !dsp )
{
printf( NAME ": could not open a connection to the X server\n" ) ;
return 1 ;
}
if( !XShmQueryExtension( dsp ) )
{
XCloseDisplay( dsp ) ;
printf( NAME ": the X server does not support the XSHM extension\n" ) ;
return 1 ;
}
int screen = XDefaultScreen( dsp ) ;
struct shmimage image ;
initimage( &image ) ;
if( !createimage( dsp, &image, XDisplayWidth( dsp, screen ), XDisplayHeight( dsp, screen ) ) )
{
XCloseDisplay( dsp ) ;
return 1 ;
}
getrootwindow( dsp, &image ) ;
if( !savepng( &image, argv[1] ) )
{
destroyimage( dsp, &image ) ;
XCloseDisplay( dsp ) ;
return 1 ;
}
destroyimage( dsp, &image ) ;
XCloseDisplay( dsp ) ;
return 0 ;
}
You can compile it like this:
gcc screenshot.c -o screenshot -std=c99 -I/usr/X11R6/include -I/usr/local/include -L/usr/X11R6/lib -L/usr/local/lib -lX11 -lXext -lpng
You can capture and save a screenshot like this:
screenshot screenshot.png
If you don't want to deal with the png library and you are not interested in taking a screenshot, delete initpngimage and savepng functions, plus the following lines:
#include <strings.h>
#include <png.h>
if( savepng( &image, argv[1] ) == FALSE )
{
destroyimage( dsp, &image ) ;
XCloseDisplay( dsp ) ;
return FALSE ;
}
And compile it like this:
gcc screenshot.c -o screenshot -std=c99 -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lXext
I need to interface to a PIC10 micro with some serial interface. Since these small devices lack hardware support for SPI I2C and UART a Software solution is inevitable.
However, since I need to preserve as much of the Programm memory to store (static) configuration and identify information to be retrieved via said interface, what would probably be the smallest solution?
I will need to program this in ASM since there seems no good C compiler for PIC10. However, this will be my first real encounter with ASM to speak of.
Try this download which contains code samples and says:
"Listed below are five PIC UART software routines to use with PIC microprocessors that have no hardware UART"
Link rot has broken the original link try this link.
In my opinion the xc8 compiler works pretty well, also for the PIC10.
Here is an example in C:
#include <xc.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
#define Baudrate 1200 //bps
#define OneBitDelay (1000000/Baudrate)
#define DataBitCount 8 // no parity, no flow control
#define UART_RX RA1 // UART RX pin
#define UART_TX RA0 // UART TX pin
#define UART_RX_DIR TRISA1 // UART RX pin direction register
#define UART_TX_DIR TRISA0 // UART TX pin direction register
//Function Declarations
void InitSoftUART(void);
unsigned char UART_Receive(void);
void UART_Transmit(const char);
__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF &
WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void main()
{
unsigned char ch = 0;
ANSELA = 0x00; // Set ports as digital I/O, not analog input
ADCON = 0x00; // Shut off the A/D Converter
FVRCON = 0x00; // Shut off the Voltage Reference
PORTA = 0x00; // Make all pins 0
InitSoftUART(); // Intialize Soft UART
InitSoftUART(); // Intialize Soft UART
while(1)
{
ch = UART_Receive(); // Receive a character from UART
UART_Transmit(ch); // Echo back that character
}
}
void InitSoftUART(void) // Initialize UART pins to proper values
{
UART_TX = 1; // TX pin is high in idle state
UART_RX_DIR = 1; // Input
UART_TX_DIR = 0; // Output
}
unsigned char UART_Receive(void)
{
// Pin Configurations
// GP1 is UART RX Pin
unsigned char DataValue = 0;
//wait for start bit
while(UART_RX==1);
__delay_us(OneBitDelay);
__delay_us(OneBitDelay/2); // Take sample value in the mid of bit duration
for ( unsigned char i = 0; i < DataBitCount; i++ )
{
if ( UART_RX == 1 ) //if received bit is high
{
DataValue += (1<<i);
}
__delay_us(OneBitDelay);
}
// Check for stop bit
if ( UART_RX == 1 ) //Stop bit should be high
{
__delay_us(OneBitDelay/2);
return DataValue;
}
else //some error occurred !
{
__delay_us(OneBitDelay/2);
return 0x000;
}
}
void UART_Transmit(const char DataValue)
{
/* Basic Logic
TX pin is usually high. A high to low bit is the starting bit and
a low to high bit is the ending bit. No parity bit. No flow control.
BitCount is the number of bits to transmit. Data is transmitted LSB first.
*/
// Send Start Bit
UART_TX = 0;
__delay_us(OneBitDelay);
for ( unsigned char i = 0; i < DataBitCount; i++ )
{
//Set Data pin according to the DataValue
if( ((DataValue>>i)&0x1) == 0x1 ) //if Bit is high
{
UART_TX = 1;
}
else //if Bit is low
{
UART_TX = 0;
}
__delay_us(OneBitDelay);
}
//Send Stop Bit
UART_TX = 1;
__delay_us(OneBitDelay);
}
Source for this code is the :Microchip forum
I am trying to print message on serial terminal from p89v664 using following code,
#include<P89V66x.H>
#include<stdio.h>
char putchar(char c) {
if (c == '\n') {
while (!TI);
TI = 0;
S0BUF = 0x0d;
}
TI = 0;
S0BUF = c;
while (!TI);
return c;
}
int printf(char*str) {
unsigned int cnt = 0;
while(*str != '\0')
{
putchar(*str);
cnt++;
str++;
}
}
void delay(unsigned int i) {
int d = 100;
for(;i!=0;i--) {
for(;d!=0;d--);
d = 100;
}
}
int main(void) {
/**Serial init*/
S0CON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
TH1 = 0xF6; /* TH1: reload value for 9600 baud */
TR1 = 1; /* TR1: timer 1 run */
TI = 1;
while(1) {
printf("Hello\n");
delay(300);
printf("Hello World\n");
delay(10000);
}
}
above program works fine till the time printf function definition in this program is not commented.
If printf function in above program is commented to use printf from standard library then junk characters are printed on serial console. (i used putty).
I used Keil uVision V4.14.4.0 compiler.
Is there anything missing?
I dont understand what is wrong with this program.
After some experiments i found that problem was with keil uVision4 evaluation version.
I compiled this code using sdcc and ran it and it worked. May be keil evaluation version's limitation was creating problem. Thank very much you Mellowcandle for all replies.
Edit:
#include <P89V66x.H>
#include<stdio.h>
void putchar(char c) {
TI = 0;
S0BUF = c;
if (c == '\n') {
while (!TI);
TI = 0;
S0BUF = 0x0d;
}
while (!TI);
}
int main(void) {
/**Serial init*/
unsigned short int c = 65334;
S0CON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
/**For 11.0592 crystal
value should TH = -3 or
TH1 = FD*/
TH1 = 0xF6; /* TH1: reload value for 9600 baud for
18 Mhz cyrstal */
TR1 = 1; /* TR1: timer 1 run */
while(1) {
printf("Hello %u\n", c);
delay(300);
printf("Hello World %u\n" ,c);
delay(10000);
}
}
command used to compile this code is,
sdcc {filename}
I have a list of N 64-bit integers whose bits represent small sets. Each integer has at most k bits set to 1. Given a bit mask, I would like to find the first element in the list that matches the mask, i.e. element & mask == element.
Example:
If my list is:
index abcdef
0 001100
1 001010
2 001000
3 000100
4 000010
5 000001
6 010000
7 100000
8 000000
and my mask is 111000, the first element matching the mask is at index 2.
Method 1:
Linear search through the entire list. This takes O(N) time and O(1) space.
Method 2:
Precompute a tree of all possible masks, and at each node keep the answer for that mask. This takes O(1) time for the query, but takes O(2^64) space.
Question:
How can I find the first element matching the mask faster than O(N), while still using a reasonable amount of space? I can afford to spend polynomial time in precomputation, because there will be a lot of queries. The key is that k is small. In my application, k <= 5 and N is in the thousands. The mask has many 1s; you can assume that it is drawn uniformly from the space of 64-bit integers.
Update:
Here is an example data set and a simple benchmark program that runs on Linux: http://up.thirld.com/binmask.tar.gz. For large.in, N=3779 and k=3. The first line is N, followed by N unsigned 64-bit ints representing the elements. Compile with make. Run with ./benchmark.e >large.out to create the true output, which you can then diff against. (Masks are generated randomly, but the random seed is fixed.) Then replace the find_first() function with your implementation.
The simple linear search is much faster than I expected. This is because k is small, and so for a random mask, a match is found very quickly on average.
A suffix tree (on bits) will do the trick, with the original priority at the leaf nodes:
000000 -> 8
1 -> 5
10 -> 4
100 -> 3
1000 -> 2
10 -> 1
100 -> 0
10000 -> 6
100000 -> 7
where if the bit is set in the mask, you search both arms, and if not, you search only the 0 arm; your answer is the minimum number you encounter at a leaf node.
You can improve this (marginally) by traversing the bits not in order but by maximum discriminability; in your example, note that 3 elements have bit 2 set, so you would create
2:0 0:0 1:0 3:0 4:0 5:0 -> 8
5:1 -> 5
4:1 5:0 -> 4
3:1 4:0 5:0 -> 3
1:1 3:0 4:0 5:0 -> 6
0:1 1:0 3:0 4:0 5:0 -> 7
2:1 0:0 1:0 3:0 4:0 5:0 -> 2
4:1 5:0 -> 1
3:1 4:0 5:0 -> 0
In your example mask this doesn't help (since you have to traverse both the bit2==0 and bit2==1 sides since your mask is set in bit 2), but on average it will improve the results (but at a cost of setup and more complex data structure). If some bits are much more likely to be set than others, this could be a huge win. If they're pretty close to random within the element list, then this doesn't help at all.
If you're stuck with essentially random bits set, you should get about (1-5/64)^32 benefit from the suffix tree approach on average (13x speedup), which might be better than the difference in efficiency due to using more complex operations (but don't count on it--bit masks are fast). If you have a nonrandom distribution of bits in your list, then you could do almost arbitrarily well.
This is the bitwise Kd-tree. It typically needs less than 64 visits per lookup operation. Currently, the selection of the bit (dimension) to pivot on is random.
#include <limits.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef unsigned long long Thing;
typedef unsigned long Number;
unsigned thing_ffs(Thing mask);
Thing rand_mask(unsigned bitcnt);
#define WANT_RANDOM 31
#define WANT_BITS 3
#define BITSPERTHING (CHAR_BIT*sizeof(Thing))
#define NONUMBER ((Number)-1)
struct node {
Thing value;
Number num;
Number nul;
Number one;
char pivot;
} *nodes = NULL;
unsigned nodecount=0;
unsigned itercount=0;
struct node * nodes_read( unsigned *sizp, char *filename);
Number *find_ptr_to_insert(Number *ptr, Thing value, Thing mask);
unsigned grab_matches(Number *result, Number num, Thing mask);
void initialise_stuff(void);
int main (int argc, char **argv)
{
Thing mask;
Number num;
unsigned idx;
srand (time(NULL));
nodes = nodes_read( &nodecount, argv[1]);
fprintf( stdout, "Nodecount=%u\n", nodecount );
initialise_stuff();
#if WANT_RANDOM
mask = nodes[nodecount/2].value | nodes[nodecount/3].value ;
#else
mask = 0x38;
#endif
fprintf( stdout, "\n#### Search mask=%llx\n", (unsigned long long) mask );
itercount = 0;
num = NONUMBER;
idx = grab_matches(&num,0, mask);
fprintf( stdout, "Itercount=%u\n", itercount );
fprintf(stdout, "KdTree search %16llx\n", (unsigned long long) mask );
fprintf(stdout, "Count=%u Result:\n", idx);
idx = num;
if (idx >= nodecount) idx = nodecount-1;
fprintf( stdout, "num=%4u Value=%16llx\n"
,(unsigned) nodes[idx].num
,(unsigned long long) nodes[idx].value
);
fprintf( stdout, "\nLinear search %16llx\n", (unsigned long long) mask );
for (idx = 0; idx < nodecount; idx++) {
if ((nodes[idx].value & mask) == nodes[idx].value) break;
}
fprintf(stdout, "Cnt=%u\n", idx);
if (idx >= nodecount) idx = nodecount-1;
fprintf(stdout, "Num=%4u Value=%16llx\n"
, (unsigned) nodes[idx].num
, (unsigned long long) nodes[idx].value );
return 0;
}
void initialise_stuff(void)
{
unsigned num;
Number root, *ptr;
root = 0;
for (num=0; num < nodecount; num++) {
nodes[num].num = num;
nodes[num].one = NONUMBER;
nodes[num].nul = NONUMBER;
nodes[num].pivot = -1;
}
nodes[num-1].value = 0; /* last node is guaranteed to match anything */
root = 0;
for (num=1; num < nodecount; num++) {
ptr = find_ptr_to_insert (&root, nodes[num].value, 0ull );
if (*ptr == NONUMBER) *ptr = num;
else fprintf(stderr, "Found %u for %u\n"
, (unsigned)*ptr, (unsigned) num );
}
}
Thing rand_mask(unsigned bitcnt)
{struct node * nodes_read( unsigned *sizp, char *filename)
{
struct node *ptr;
unsigned size,used;
FILE *fp;
if (!filename) {
size = (WANT_RANDOM+0) ? WANT_RANDOM : 9;
ptr = malloc (size * sizeof *ptr);
#if (!WANT_RANDOM)
ptr[0].value = 0x0c;
ptr[1].value = 0x0a;
ptr[2].value = 0x08;
ptr[3].value = 0x04;
ptr[4].value = 0x02;
ptr[5].value = 0x01;
ptr[6].value = 0x10;
ptr[7].value = 0x20;
ptr[8].value = 0x00;
#else
for (used=0; used < size; used++) {
ptr[used].value = rand_mask(WANT_BITS);
}
#endif /* WANT_RANDOM */
*sizp = size;
return ptr;
}
fp = fopen( filename, "r" );
if (!fp) return NULL;
fscanf(fp,"%u\n", &size );
fprintf(stderr, "Size=%u\n", size);
ptr = malloc (size * sizeof *ptr);
for (used = 0; used < size; used++) {
fscanf(fp,"%llu\n", &ptr[used].value );
}
fclose( fp );
*sizp = used;
return ptr;
}
Thing value = 0;
unsigned bit, cnt;
for (cnt=0; cnt < bitcnt; cnt++) {
bit = 54321*rand();
bit %= BITSPERTHING;
value |= 1ull << bit;
}
return value;
}
Number *find_ptr_to_insert(Number *ptr, Thing value, Thing done)
{
Number num=NONUMBER;
while ( *ptr != NONUMBER) {
Thing wrong;
num = *ptr;
wrong = (nodes[num].value ^ value) & ~done;
if (nodes[num].pivot < 0) { /* This node is terminal */
/* choose one of the wrong bits for a pivot .
** For this bit (nodevalue==1 && searchmask==0 )
*/
if (!wrong) wrong = ~done ;
nodes[num].pivot = thing_ffs( wrong );
}
ptr = (wrong & 1ull << nodes[num].pivot) ? &nodes[num].nul : &nodes[num].one;
/* Once this bit has been tested, it can be masked off. */
done |= 1ull << nodes[num].pivot ;
}
return ptr;
}
unsigned grab_matches(Number *result, Number num, Thing mask)
{
Thing wrong;
unsigned count;
for (count=0; num < *result; ) {
itercount++;
wrong = nodes[num].value & ~mask;
if (!wrong) { /* we have a match */
if (num < *result) { *result = num; count++; }
/* This is cheap pruning: the break will omit both subtrees from the results.
** But because we already have a result, and the subtrees have higher numbers
** than our current num, we can ignore them. */
break;
}
if (nodes[num].pivot < 0) { /* This node is terminal */
break;
}
if (mask & 1ull << nodes[num].pivot) {
/* avoid recursion if there is only one non-empty subtree */
if (nodes[num].nul >= *result) { num = nodes[num].one; continue; }
if (nodes[num].one >= *result) { num = nodes[num].nul; continue; }
count += grab_matches(result, nodes[num].nul, mask);
count += grab_matches(result, nodes[num].one, mask);
break;
}
mask |= 1ull << nodes[num].pivot;
num = (wrong & 1ull << nodes[num].pivot) ? nodes[num].nul : nodes[num].one;
}
return count;
}
unsigned thing_ffs(Thing mask)
{
unsigned bit;
#if 1
if (!mask) return (unsigned)-1;
for ( bit=random() % BITSPERTHING; 1 ; bit += 5, bit %= BITSPERTHING) {
if (mask & 1ull << bit ) return bit;
}
#elif 0
for (bit =0; bit < BITSPERTHING; bit++ ) {
if (mask & 1ull <<bit) return bit;
}
#else
mask &= (mask-1); // Kernighan-trick
for (bit =0; bit < BITSPERTHING; bit++ ) {
mask >>=1;
if (!mask) return bit;
}
#endif
return 0xffffffff;
}
struct node * nodes_read( unsigned *sizp, char *filename)
{
struct node *ptr;
unsigned size,used;
FILE *fp;
if (!filename) {
size = (WANT_RANDOM+0) ? WANT_RANDOM : 9;
ptr = malloc (size * sizeof *ptr);
#if (!WANT_RANDOM)
ptr[0].value = 0x0c;
ptr[1].value = 0x0a;
ptr[2].value = 0x08;
ptr[3].value = 0x04;
ptr[4].value = 0x02;
ptr[5].value = 0x01;
ptr[6].value = 0x10;
ptr[7].value = 0x20;
ptr[8].value = 0x00;
#else
for (used=0; used < size; used++) {
ptr[used].value = rand_mask(WANT_BITS);
}
#endif /* WANT_RANDOM */
*sizp = size;
return ptr;
}
fp = fopen( filename, "r" );
if (!fp) return NULL;
fscanf(fp,"%u\n", &size );
fprintf(stderr, "Size=%u\n", size);
ptr = malloc (size * sizeof *ptr);
for (used = 0; used < size; used++) {
fscanf(fp,"%llu\n", &ptr[used].value );
}
fclose( fp );
*sizp = used;
return ptr;
}
UPDATE:
I experimented a bit with the pivot-selection, favouring bits with the highest discriminatory value ("information content"). This involves:
making a histogram of the usage of bits (can be done while initialising)
while building the tree: choosing the one with frequency closest to 1/2 in the remaining subtrees.
The result: the random pivot selection performed better.
Construct a a binary tree as follows:
Every level corresponds to a bit
It corresponding bit is on go right, otherwise left
This way insert every number in the database.
Now, for searching: if the corresponding bit in the mask is 1, traverse both children. If it is 0, traverse only the left node. Essentially keep traversing the tree until you hit the leaf node (BTW, 0 is a hit for every mask!).
This tree will have O(N) space requirements.
Eg of tree for 1 (001), 2(010) and 5 (101)
root
/ \
0 1
/ \ |
0 1 0
| | |
1 0 1
(1) (2) (5)
With precomputed bitmasks. Formally is is still O(N), since the and-mask operations are O(N). The final pass is also O(N), because it needs to find the lowest bit set, but that could be sped up, too.
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* For demonstration purposes.
** In reality, this should be an unsigned long long */
typedef unsigned char Thing;
#define BITSPERTHING (CHAR_BIT*sizeof (Thing))
#define COUNTOF(a) (sizeof a / sizeof a[0])
Thing data[] =
/****** index abcdef */
{ 0x0c /* 0 001100 */
, 0x0a /* 1 001010 */
, 0x08 /* 2 001000 */
, 0x04 /* 3 000100 */
, 0x02 /* 4 000010 */
, 0x01 /* 5 000001 */
, 0x10 /* 6 010000 */
, 0x20 /* 7 100000 */
, 0x00 /* 8 000000 */
};
/* Note: this is for demonstration purposes.
** Normally, one should choose a machine wide unsigned int
** for bitmask arrays.
*/
struct bitmap {
char data[ 1+COUNTOF (data)/ CHAR_BIT ];
} nulmaps [ BITSPERTHING ];
#define BITSET(a,i) (a)[(i) / CHAR_BIT ] |= (1u << ((i)%CHAR_BIT) )
#define BITTEST(a,i) ((a)[(i) / CHAR_BIT ] & (1u << ((i)%CHAR_BIT) ))
void init_tabs(void);
void map_empty(struct bitmap *dst);
void map_full(struct bitmap *dst);
void map_and2(struct bitmap *dst, struct bitmap *src);
int main (void)
{
Thing mask;
struct bitmap result;
unsigned ibit;
mask = 0x38;
init_tabs();
map_full(&result);
for (ibit = 0; ibit < BITSPERTHING; ibit++) {
/* bit in mask is 1, so bit at this position is in fact a don't care */
if (mask & (1u <<ibit)) continue;
/* bit in mask is 0, so we can only select items with a 0 at this bitpos */
map_and2(&result, &nulmaps[ibit] );
}
/* This is not the fastest way to find the lowest 1 bit */
for (ibit = 0; ibit < COUNTOF (data); ibit++) {
if (!BITTEST(result.data, ibit) ) continue;
fprintf(stdout, " %u", ibit);
}
fprintf( stdout, "\n" );
return 0;
}
void init_tabs(void)
{
unsigned ibit, ithing;
/* 1 bits in data that dont overlap with 1 bits in the searchmask are showstoppers.
** So, for each bitpos, we precompute a bitmask of all *entrynumbers* from data[], that contain 0 in bitpos.
*/
memset(nulmaps, 0 , sizeof nulmaps);
for (ithing=0; ithing < COUNTOF(data); ithing++) {
for (ibit=0; ibit < BITSPERTHING; ibit++) {
if ( data[ithing] & (1u << ibit) ) continue;
BITSET(nulmaps[ibit].data, ithing);
}
}
}
/* Logical And of two bitmask arrays; simular to dst &= src */
void map_and2(struct bitmap *dst, struct bitmap *src)
{
unsigned idx;
for (idx = 0; idx < COUNTOF(dst->data); idx++) {
dst->data[idx] &= src->data[idx] ;
}
}
void map_empty(struct bitmap *dst)
{
memset(dst->data, 0 , sizeof dst->data);
}
void map_full(struct bitmap *dst)
{
unsigned idx;
/* NOTE this loop sets too many bits to the left of COUNTOF(data) */
for (idx = 0; idx < COUNTOF(dst->data); idx++) {
dst->data[idx] = ~0;
}
}