Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 25, 2024, 10:48:10 10:48


Login with username, password and session length


Pages: [1]
Print
Author Topic: MC145170 Source C  (Read 12275 times)
0 Members and 1 Guest are viewing this topic.
folkeu
Active Member
***
Offline Offline

Posts: 220

Thank You
-Given: 126
-Receive: 308


« 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 !
@+
Logged
ipek
Junior Member
**
Offline Offline

Posts: 95

Thank You
-Given: 60
-Receive: 79


« Reply #1 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]...
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 -----
« Last Edit: November 26, 2017, 08:33:49 08:33 by metal » Logged
folkeu
Active Member
***
Offline Offline

Posts: 220

Thank You
-Given: 126
-Receive: 308


« Reply #2 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
Logged
zuisti
Senior Member
****
Offline Offline

Posts: 409

Thank You
-Given: 242
-Receive: 780


« Reply #3 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:
Code:
/* 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
Logged
folkeu
Active Member
***
Offline Offline

Posts: 220

Thank You
-Given: 126
-Receive: 308


« Reply #4 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
Logged
folkeu
Active Member
***
Offline Offline

Posts: 220

Thank You
-Given: 126
-Receive: 308


« Reply #5 on: November 26, 2017, 03:47:40 15:47 »

Hi all,
I add another routine proposed on another forum. It works too.

Code:
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;
  };
Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC