Title: MC145170 Source C
Post by: folkeu on July 15, 2009, 10:51:29 10:51
Hello,
Somebody have a source in C for MCC18, Hi-tech, mikroC for drive a MC145170 (PLL)? Google help me not ! @+
Title: Re: MC145170 Source C
Post by: ipek on July 18, 2009, 02:36:22 14:36
http://www.geocities.com/hagtronics/2_meter.html only CCSC code easy convert any C http://www.geocities.com/hagtronics/2_meter.c use [/code]... for your code in the post. [/color]
[code]//================================================================== //===== ===== //===== 2 Meter Receiver Program ===== //===== By: Steve Hageman 29Mar98 ===== //===== www.sonic.net/~shageman ===== //================================================================== //===== Copyright 1998 by Steven C. Hageman ===== //===== All rights reserved ===== //================================================================== //===== Version: 0.0 - Initial Writing - 29Mar98 ===== //===== Version: 1.0 - First release - 19Sep98 ===== //==================================================================
//-----< Include Files, setup fuses >----- #include <16c73a.h> #include <stdio.h> #fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT
//-----< Compiler use statements >----- // Tell compiler clock speed, baud, and Hardware UART pins #use delay(clock=10000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//-----< Port location defines >----- #pragma byte port_a = 0x05 #pragma byte port_b = 0x06 #pragma byte port_c = 0x07
//-----< Pin defines >----- #pragma bit AUDIO_PIN = port_a.2 // Audio override pin #pragma bit A_SW = port_b.0 // Encoder A switch input #pragma bit B_SW = port_b.1 // Encoder B switch input #pragma bit INC_SW = port_b.2 // Freq increment select switch #pragma bit SCAN_SW = port_b.3 // Scan select switch #pragma bit RS232_PIN = port_c.7 // RS232 input pin
//-----< MC145170 PLL Chip Pins >----- #pragma bit DIN = port_b.5 #pragma bit CLK = port_b.6 #pragma bit EN = port_b.7
//-----< General Program Defines >-----
#define DOOMSDAY 0 // Not here yet! #define AUDIO_OFF 1 // Set AUDIO OFF #define AUDIO_ON 0 // Set AUDIO ON #define PUSHED 0 // For switched closed sense #define RSSI 0 // Analog input for RSSI #define SQUELCH 1 // Analog input for squelch pot #define BAT 3 // Analog input for battery voltage #define EOT 255 // End of RS232 transmission character
//-----< Global Variables >----- unsigned long Channel; // PLL channel number 0 - 799 for 5 kHz steps int Increment; // Frequency increment (in channel units) int Changed; // Frequency changed flag int Rssi_val; // RSSI A/D value int Squelch_val; // Squelch pot setting int Bat_val; // Battery voltage value int Keep_scanning; // Flag used during scanning
//-----< LCD Routines >----------------------------------------------
// LCD is connected to port c, definitions below
// LCD Connections - // C5 C4 C3 C2 C1 C0 - PORT PINS // E R/S D7 D6 D5 D4 - LCD PINS
void blip_e_delay() { // Set enable high for 2 cycles then low // Minimum E cycle time is 450 nS. #asm bsf port_c,5 nop nop bcf port_c,5 #endasm // Wait for longest lcd routine to finish, takes time // but saves code in not checking for the busy flag. delay_ms(5); }
void blip_e() { // Set enable high for 2 cycles then low // Minimum E cycle time is 450 nS. #asm bsf port_c,5 nop nop bcf port_c,5 #endasm // Wait for shortest lcd routine to finish, takes time // but saves code in not checking for the busy flag. delay_us(50); }
void first_line() { // Set the LCD to the first display line // Send 0x80 for first line. port_c = 0x08; blip_e(); port_c = 0x00; blip_e(); }
void second_line() { // Set the LCD to the second display line // Send 0xc0 for second line. port_c = 0x0c; blip_e(); port_c = 0x00; blip_e(); }
void init_lcd() { // Clear and initilize LCD panel to 4 bit mode // two line mode, cursor off, display on. // RS needs to be low for all of these instructions. // -> Takes 60 mS to complete <- // Send 0x03 three times port_c = 0x03; blip_e_delay(); port_c = 0x03; blip_e_delay();
port_c = 0x03; blip_e_delay();
// Send 0x02 port_c = 0x02; blip_e_delay(); // send 0x28 port_c = 0x02; blip_e_delay(); port_c = 0x08; blip_e_delay(); // send 0x01 port_c = 0x00; blip_e_delay(); port_c = 0x01; blip_e_delay();
// send 0x06 port_c = 0x00; blip_e_delay(); port_c = 0x06; blip_e_delay();
// send 0x0c port_c = 0x00; blip_e_delay(); port_c = 0x0c; blip_e_delay();
// Send 0x0f to set cursor on with blink // Send 0x0e to set cursor on w/o blink
// Clean up port on exit port_c = 0x00; }
void write_lcd(byte ch) { // writes the char ch to the lcd. HB then LB. // The OR sets RS high port_c = (ch/0x10) | 0x10; blip_e(); port_c = (ch & 0x0f) | 0x10; blip_e(); // Clean up port on exit port_c = 0x00; }
void display_frequency(void) { unsigned long freq;
// Calculate actual frequency freq = Channel*5 + 4000; // Write frequency to display first_line(); write_lcd("14"); write_lcd((int)(freq / 1000) + '0'); write_lcd('.'); write_lcd((int)((freq / 100) % 10) + '0'); write_lcd((int)((freq / 10) % 10) + '0'); write_lcd((int)(freq % 10) + '0'); write_lcd(" MHz"); // Write increment to display switch(Increment) { case 0: write_lcd(" Lock"); break; case 1: write_lcd(" 5k"); break; case 2: write_lcd(" 10k"); break; case 20: write_lcd(" 100k"); break; case 200: write_lcd(" 1M"); break; } }
//-----< PLL Routines >---------------------------------------------- void setup_pll(void) {
// PLL setup routine, only needs to be done once, at startup. // Note: Until control register is set, the PIC clock will be running at // 1.25 MHz.
//----- Initilize PLL ----- // EN High, Din Low, 4 clocks CLK = 0; DIN = 0; EN = 1;
CLK = 1; CLK = 0;
CLK = 1; CLK = 0;
CLK = 1; CLK = 0;
CLK = 1; CLK = 0;
// EN Low, Din Low (except clock 4 = 1), 5 clocks DIN = 0; EN = 0;
CLK = 1; CLK = 0;
CLK = 1; CLK = 0;
CLK = 1; CLK = 0;
DIN = 1; CLK = 1; CLK = 0; DIN = 0;
CLK = 1; CLK = 0;
EN = 1; // PLL is now reset //----- Setup C Reg with proper bits ----- EN = 0; // Bit 7 - PD Polarity DIN = 0; CLK = 1; CLK = 0; // Bit 6 - PD Output DIN = 1; CLK = 1; CLK = 0; // Bit 5 - Lock Detect Off DIN = 0; CLK = 1; CLK = 0; // Bit 4, 3, 2 - Ref divider output (001 = /1) DIN = 0; CLK = 1; CLK = 0; DIN = 0; CLK = 1; CLK = 0; DIN = 1; CLK = 1; CLK = 0;
// Bit 1 - FV off -- NOTE: Set this bit high to get // the N counter out on pin 10. DIN = 0; CLK = 1; CLK = 0; // Bit 0 - FR off -- NOTE: Set this bit high to get // the PD ref frequency on pin 9. DIN = 0; CLK = 1; CLK = 0; DIN = 0; // EN back high EN = 1;
// Note: The PIC clock will now be 10 MHz //----- Setup Ref Divider ----- // 10 MHz / 2000 = 5 KHz (2000 = 0x07d0) EN = 0;
// BIT 14-12 = 000 CLK = 1; CLK = 0; CLK = 1; CLK = 0; CLK = 1; CLK = 0; // BIT 11-8 = 0111 CLK = 1; CLK = 0; DIN = 1; CLK = 1; CLK = 0; CLK = 1; CLK = 0; CLK = 1; CLK = 0; // BIT 7-4 = 1101 CLK = 1; CLK = 0; CLK = 1; CLK = 0; DIN = 0; CLK = 1; CLK = 0; DIN = 1; CLK = 1; CLK = 0; // BIT 4-0 = 0000 DIN = 0; CLK = 1; CLK = 0; CLK = 1; CLK = 0; CLK = 1; CLK = 0; CLK = 1; CLK = 0; // Enable Back High EN = 1; }
void tune_pll(void) { int ctr; unsigned long n_reg;
// Convert channel number to N counter value n_reg = Channel + 30940;
// Set clock, enable low CLK = 0; EN = 0; // Shift in channel frequency to N reg (MSB first) for( ctr = 0 ; ctr <= 15 ; ctr++) { // Decompose the PLL N value into bits, set data pin DIN = shift_left(&n_reg, 2, 0); // Cycle the clock CLK = 1; CLK = 0; } // Clean up and set enable high which // transfers count to N reg DIN = 0; EN = 1;
}
//-----< Set Analog Globals >---------------------------------------- void update_analog(void) { // Read all the analog channels and set their global variables set_adc_channel(RSSI); delay_us(20); Rssi_val = read_adc(); // Bound the value, so it does not interfere with RS232 'EOT'. // As design was orginaly done, this won't ever hapen. // I put this here just in case something is changed. if( Rssi_val == 255 ) Rssi_val = 254;
set_adc_channel(SQUELCH); // The /4 scales the squelch range delay_us(20); // to match the RSSI range Squelch_val = read_adc()/4; set_adc_channel(BAT); delay_us(20);
Bat_val = read_adc(); // Bound the value, so it does not interfere with RS232 'EOT'. if( Bat_val == 255 ) Bat_val = 254;
}
//-----< RS232 Control loop >----------------------------------------- void rs232_mode(void) { char buf; int hb, lb;
// We just stay in this routine forever! // Update LCD display write_lcd("-- Hagtronics --"); second_line(); write_lcd("-- RS232 Mode --"); while(!DOOMSDAY) { // Get command buf = getc(); // Process command switch(buf) { case 'A': // Set Audio { // Say first char was OK putc(EOT); // Get mode buf = getc(); switch(buf) { case 'N': // Set audio on AUDIO_PIN = AUDIO_ON; putc(EOT); break; case 'F': // Set audio off AUDIO_PIN = AUDIO_OFF; putc(EOT); break; default: // What did they want? putc('?'); putc(EOT); break; } break; } case 'C': // Channel Set { // Say first char was OK putc(EOT); // Get channel bytes HB, LB hb = getc(); // Say HB was OK putc(EOT); // Get LB lb = getc(); // Say it was good! putc(EOT); // Figure channel number Channel = hb * 256 + lb;
// Set N Reg with frequency tune_pll(); break; } case 'D': // Write data valid status out { //Send back current signal levels update_analog(); putc(Rssi_val); putc(Bat_val); putc(EOT); break; }
default: // Say char was not understood { putc('?'); putc(EOT); } } // End of first char switch
} // End of main while }
void update_audio(void) { // Decide if RSSI level is greater than the squelch level // This will determine if the audio needs to be turned on or not // Get current RSSI and squelch value update_analog(); if(Rssi_val >= Squelch_val) { // Set audio on AUDIO_PIN = AUDIO_ON; } else { // Set audio off AUDIO_PIN = AUDIO_OFF; } }
//-----< Scanning routine >------------------------------------------ // Note: Scan is also killed by turning the tune knob void scan(void) { int ctr;
// Turn off audio to start with AUDIO_PIN = AUDIO_OFF; // Initilize variable Keep_scanning = TRUE; // Scan till the cows come home while(Keep_scanning == TRUE) { // Increment channel Channel += Increment; // Bound the channel values -- implements roll over if( Channel > 60000 ) // Catch unsigned underflow Channel = 800; if( Channel > 800 ) // Catch overflow Channel = 0;
// Update PLL & wait a while tune_pll(); delay_ms(20); // Enough time for a full scale step // Update display display_frequency(); // Check if anything is on this channel update_analog(); while((Rssi_val >= Squelch_val) && (Keep_scanning == TRUE)) { // Yup got a signal, turn Audio on AUDIO_PIN = AUDIO_ON; // Delay a while (2 seconds) on signal, but check scan switch // This loop runs at about 10 times a second for(ctr = 0; ctr <= 19 ; ctr++) { // Hurry up and wait! delay_ms(100); // Is the scan switch depressed? if(SCAN_SW == PUSHED) { // Clean up display for the user, giving feedback second_line(); write_lcd(" "); // Wait 'till switch is not pressed while(SCAN_SW == PUSHED); // Exit out of here Keep_scanning = FALSE; } // If audio drops during this time turn it off // but stay in loop (keep resetting loop counter) update_analog(); if(Rssi_val >= Squelch_val) { AUDIO_PIN = AUDIO_ON; ctr = 0; } else AUDIO_PIN = AUDIO_OFF;
// If something has set keep_scanning false, // break out of loop if(keep_scanning == FALSE) break; } // End of signal delay loop } // End of signal capture delay while loop // Check to see if scan is stopped if(SCAN_SW == PUSHED) { // Clean up display for the user, giving feedback second_line(); write_lcd(" "); // wait till switch is not pushed while(SCAN_SW == PUSHED); // Now get outa town Keep_scanning = FALSE; } } // End of main loop // Clean up display for the user, giving feedback second_line(); write_lcd(" "); // Turn the audio back off, it will turn on later is there is // still a signal AUDIO_PIN = AUDIO_OFF; }
void change_increment(void) { // Change to next tuning increment value (Step size)
switch(Increment) { case 0: // 0 Channels = Locked Increment = 1; break; case 1: // 1 Channel = 5 kHz Increment = 2; break; case 2: // 2 Channels = 10 kHz Increment = 20; break; case 20: // 20 Channels = 100 kHz Increment = 200; break; case 200: // 200 Channels = 1 MHz Increment = 0; break;
default: // Just in case, set 1 channel Increment = 1; } }
void update_rssi_display(void) { static int old_rssi; // Note: old_rssi is not initilized int scaled_rssi, char_pos;
// Displays the RSSI level of a signal on the LCD // Note: This one A/D read is used several placed below update_analog(); scaled_rssi = Rssi_val/2; // Divide by 2 to maximize range // Scale RSSI a/d value if(scaled_rssi > 8) { scaled_rssi -= 8; // The 8 offsets the display to zero } else { scaled_rssi = 0; // Floor a/d value } if(scaled_rssi > 16) // Bound scaled a/d value scaled_rssi = 16; // Only update display if RSSI value changed if(scaled_rssi != old_rssi) { second_line(); for(char_pos=1 ; char_pos <= 16 ; char_pos++) { if(char_pos <= scaled_rssi) { write_lcd(255); } else { write_lcd(' '); } } old_rssi = scaled_rssi; } }
//-----< Rotary Encoder routine >------------------------------------ #INT_EXT // Change on falling edge of RB // Note: Must set int reg to get falling edge trigger void encoder(void) { // If here then the A encoder must have had a falling edge... // Read encoder B switch and check direction if( B_SW == 1 ) { // CW Direction Channel += Increment; } else { // CCW Direction Channel -= Increment; } // Bound the channel values -- implements roll over if( Channel > 60000 ) // Catch unsigned underflow Channel = 800;
if( Channel > 800 ) // Catch overflow Channel = 0;
// Set the changed flag, cancel scanning (if we were scanning) Changed = TRUE; Keep_scanning = FALSE;
}
//-----< Main >------------------------------------------------------
// Note: At powerup the PIC clock will be 1.25 MHz. After PLL setup is // done the clock will be 10 MHz. No RS232 can take place untill PLL // is setup.
void main(void) { int ctr; // Local variables
//----- Setup Ports / Unused pins are set to output set_tris_a(0b00001011); //
set_tris_b(0b00001111); //
set_tris_c(0b10000000); // port_b_pullups(TRUE); // ON for the switches
//----- Housekeeping ----- // Initilize Pins EN = 1; AUDIO_PIN = AUDIO_OFF; // Initilize global/local variables Channel = 400; // Set for 146.000 MHz Changed = TRUE; // Update display Increment = 2; // Set for 10 kHz increment // Initilize interrupts disable_interrupts(GLOBAL);
ext_int_edge(H_TO_L); // Initilize A/D setup_port_a(RA0_RA1_RA3_ANALOG); setup_adc(ADC_CLOCK_INTERNAL); // Wait for LCD powerup // Note: Here clock is really 1.25 MHz, so delay is not // accurate (8 times more than value called out) delay_ms(100);
// Initilize LCD init_lcd();
// Display power on banner write_lcd(" Hagtronics "); second_line(); write_lcd("2 Meter Receiver"); // Reset PLL, setup C, R regs setup_pll(); // Setup PLL for initial turn on frequency of 146 MHz tune_pll(); // Clean up display delay_ms(1000); init_lcd();
//----- Determine if RS232 cable is hooked up // Read from RS232 receive pin, if it is high then // RS232 is connected. if(RS232_PIN == 1) { // RS232 is connected, operate in the remote mode rs232_mode(); } //----- Main loop ----- // This outer loop operates about 4 times a second while(!DOOMSDAY) { disable_interrupts(GLOBAL); // Check battery level update_analog(); if( Bat_val <= 141 ) // 141 gives about 1.1 volt per cell { // Low battery second_line(); write_lcd("BAT"); } // Update display / PLL if channel changed if( Changed ) { display_frequency(); // Update PLL tune_pll(); // Reset the changed flag Changed = FALSE; } // Set the encoder interrupt on again enable_interrupts(GLOBAL); // Real time update loop for( ctr = 0 ; ctr <= 24 ; ctr++ ) { // Check if scan switch is pushed if(SCAN_SW == PUSHED) { // Give user feedback that switch was pushed second_line(); write_lcd("----Scanning----"); // Wait till scan is not pushed anymore while(SCAN_SW == PUSHED);
// OK, Let's scan :) scan(); } // Check if Increment switch has been changed if(INC_SW == PUSHED) { // Increment tuning step size change_increment(); // Give user feedback on button being pushed display_frequency(); // Wait till increment switch is not pushed anymore while(INC_SW == PUSHED); } // Update signal strength display update_rssi_display(); // Check squelch level, open audio if needed update_audio(); delay_ms(10); // Update loop about every 10 mSec
} // End of 'real time' loop
} // End of main while loop
} //----- End of main -----
Title: Re: MC145170 Source C
Post by: folkeu on November 25, 2017, 04:18:00 16:18
Hi, Is there a function in MikroC for Pic that will replace the Shft_Left of the CCS compiler? Thanks François
Title: Re: MC145170 Source C
Post by: zuisti on November 25, 2017, 07:38:52 19:38
Is there a function in MikroC for Pic that will replace the Shft_Left of the CCS compiler No such function in mikroC so I tried to write one: /* CCS C shift_left function (as per your pdf):
Syntax: shift_left (address, bytes, value) Parameters: address is a pointer to memory. bytes is a count of the number of bytes to work with value is a 0 to 1 to be shifted in. Returns: 0 or 1 for the bit shifted out
Function: Shifts a bit into an array or structure. The address may be an array identifier or an address to a structure (such as &data). Bit 0 of the lowest byte in RAM is treated as the LSB. -------------
(almost) the same mikroC function, written by me: */ char shift_left(char* address, char bytes, char value) { char oldch, ch, carry = 0, cnt = 0, result = 0; for ( ; cnt < bytes ; ++address, ++cnt ) { // loop 'bytes' times oldch = ch = *address; // read and save the actual byte if (!cnt && value) // lowest (first) byte only carry.B0 = 1; // 1 to be shifted in later if (cnt == (bytes - 1) && ch.b7) // highest (last) byte only result = 1; ch <<= 1; // left shifted one times and ch.B0 = 0 if (carry.B0) ch.b0 = 1; *address = ch; // write it back to the array // set carry for the next byte: carry.B0 = 0; if (oldch.B7) carry.B0 = 1;
} // end for return result; } Not tried yet, sorry :-) zuisti
Title: Re: MC145170 Source C
Post by: folkeu on November 25, 2017, 08:20:15 20:20
Hi Zuisti, I have joint my project files. I am trying to put in Proteus a logical analysis graph to visualize the different states in time of the SPI of the PLL but nothing is displayed. The debugger SPI gives information. I try this conversion François
Posted on: November 25, 2017, 09:01:10 21:01 - Automerged
Hi Zuisti,
Thank you Thank you very much. I just tried the function and in the debugger SPI he told me that he sent 041A which corresponds to 1050 (frequency displayed / 10). Also check your side because I'm not used to debugger SPI. I draw the decks to test in real now because the simulation of a Mc145170 is not possible under Proteus Tanks François
Title: Re: MC145170 Source C
Post by: folkeu on November 26, 2017, 03:47:40 15:47
Hi all, I add another routine proposed on another forum. It works too. Channel=0; n_reg=Channel + 30940; L=n_reg; for( i = 0 ; i < 16 ; i++) { L= n_reg & 0x8000; if (L>0) DIN=1; else DIN=0; n_reg=n_reg<<1; // Cycle the clock CLK = 1; CLK = 0; };
|