300 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * The user interface of the ubitx consists of the encoder, the push-button on top of it
 | 
						|
 * and the 16x2 LCD display.
 | 
						|
 * The upper line of the display is constantly used to display frequency and status
 | 
						|
 * of the radio. Occasionally, it is used to provide a two-line information that is 
 | 
						|
 * quickly cleared up.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
const PROGMEM uint8_t meters_bitmap[] = {
 | 
						|
  B10000,  B10000,  B10000,  B10000,  B10000,  B10000,  B10000,  B10000 ,   //custom 1
 | 
						|
  B11000,  B11000,  B11000,  B11000,  B11000,  B11000,  B11000,  B11000 ,   //custom 2
 | 
						|
  B11100,  B11100,  B11100,  B11100,  B11100,  B11100,  B11100,  B11100 ,   //custom 3
 | 
						|
  B11110,  B11110,  B11110,  B11110,  B11110,  B11110,  B11110,  B11110 ,   //custom 4
 | 
						|
  B11111,  B11111,  B11111,  B11111,  B11111,  B11111,  B11111,  B11111 ,   //custom 5
 | 
						|
  B01000,  B11100,  B01000,  B00000,  B10111,  B10101,  B10101,  B10111     //custom 6
 | 
						|
};
 | 
						|
*/
 | 
						|
 | 
						|
//SWR GRAPH,  DrawMeter and drawingMeter Logic function by VK2ETA 
 | 
						|
 | 
						|
#ifdef OPTION_SKINNYBARS //We want skninny bars with more text
 | 
						|
//VK2ETA modded "Skinny" bitmaps
 | 
						|
const PROGMEM uint8_t meters_bitmap[] = {
 | 
						|
  //  B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000, //Padlock Symbol, for merging. Not working, see below
 | 
						|
  B00000, B00000, B00000, B00000, B00000, B00000, B00000, B10000, //shortest bar
 | 
						|
  B00000, B00000, B00000, B00000, B00000, B00000, B00100, B10100,
 | 
						|
  B00000, B00000, B00000, B00000, B00000, B00001, B00101, B10101,
 | 
						|
  B00000, B00000, B00000, B00000, B10000, B10000, B10000, B10000,
 | 
						|
  B00000, B00000, B00000, B00100, B10100, B10100, B10100, B10100,
 | 
						|
  B00000, B00000, B00001, B00101, B10101, B10101, B10101, B10101, //tallest bar
 | 
						|
  B00000, B00010, B00111, B00010, B01000, B11100, B01000, B00000, // ++ sign
 | 
						|
};
 | 
						|
#else
 | 
						|
//VK2ETA "Fat" bars, easy to read, with less text
 | 
						|
const PROGMEM uint8_t meters_bitmap[] = {
 | 
						|
  //  B01110, B10001, B10001, B11111, B11011, B11011, B11111, B00000, //Padlock Symbol, for merging. Not working, see below
 | 
						|
  B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111, //shortest bar
 | 
						|
  B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111,
 | 
						|
  B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111,
 | 
						|
  B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111,
 | 
						|
  B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111,
 | 
						|
  B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111, //tallest bar
 | 
						|
  B00000, B00010, B00111, B00010, B01000, B11100, B01000, B00000, // ++ sign
 | 
						|
};
 | 
						|
#endif //OPTION_SKINNYBARS
 | 
						|
PGM_P p_metes_bitmap = reinterpret_cast<PGM_P>(meters_bitmap);
 | 
						|
 | 
						|
const PROGMEM uint8_t lock_bitmap[8] = {
 | 
						|
  0b01110,
 | 
						|
  0b10001,
 | 
						|
  0b10001,
 | 
						|
  0b11111,
 | 
						|
  0b11011,
 | 
						|
  0b11011,
 | 
						|
  0b11111,
 | 
						|
  0b00000};
 | 
						|
PGM_P plock_bitmap = reinterpret_cast<PGM_P>(lock_bitmap);
 | 
						|
 | 
						|
 | 
						|
// initializes the custom characters
 | 
						|
// we start from char 1 as char 0 terminates the string!
 | 
						|
void initMeter(){
 | 
						|
  uint8_t tmpbytes[8];
 | 
						|
  byte i;
 | 
						|
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(plock_bitmap + i);
 | 
						|
  LCD_CreateChar(0, tmpbytes);
 | 
						|
  
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i);
 | 
						|
  LCD_CreateChar(1, tmpbytes);
 | 
						|
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8);
 | 
						|
  LCD_CreateChar(2, tmpbytes);
 | 
						|
  
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16);
 | 
						|
  LCD_CreateChar(3, tmpbytes);
 | 
						|
  
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24);
 | 
						|
  LCD_CreateChar(4, tmpbytes);
 | 
						|
  
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32);
 | 
						|
  LCD_CreateChar(5, tmpbytes);
 | 
						|
  
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40);
 | 
						|
  LCD_CreateChar(6, tmpbytes);
 | 
						|
 | 
						|
  for (i = 0; i < 8; i++)
 | 
						|
    tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 48);
 | 
						|
  LCD_CreateChar(7, tmpbytes);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//by KD8CEC
 | 
						|
//0 ~ 25 : 30 over : + 10
 | 
						|
/*
 | 
						|
void drawMeter(int needle) {
 | 
						|
  //5Char + O over
 | 
						|
  int i;
 | 
						|
 | 
						|
  for (i = 0; i < 5; i++) {
 | 
						|
    if (needle >= 5)
 | 
						|
      lcdMeter[i] = 5; //full
 | 
						|
    else if (needle > 0)
 | 
						|
      lcdMeter[i] = needle; //full
 | 
						|
    else  //0
 | 
						|
      lcdMeter[i] = 0x20;
 | 
						|
    
 | 
						|
    needle -= 5;
 | 
						|
  }
 | 
						|
 | 
						|
  if (needle > 0)
 | 
						|
    lcdMeter[5] = 6;
 | 
						|
  else
 | 
						|
    lcdMeter[5] = 0x20;
 | 
						|
}
 | 
						|
*/
 | 
						|
//VK2ETA meter for S.Meter, power and SWR
 | 
						|
void drawMeter(int needle) 
 | 
						|
{
 | 
						|
#ifdef OPTION_SKINNYBARS
 | 
						|
  //Fill buffer with growing set of bars, up to needle value
 | 
						|
  lcdMeter[0] = 0x20;
 | 
						|
  lcdMeter[1] = 0x20;
 | 
						|
  for (int i = 0; i < 6; i++) {
 | 
						|
    if (needle > i)
 | 
						|
      lcdMeter[i / 3] = byte(i + 1); //Custom characters above
 | 
						|
    //else if (i == 1 || i == 4) {
 | 
						|
    //  lcdMeter[i / 3] = 0x20; //blank
 | 
						|
    //}
 | 
						|
  }
 | 
						|
 | 
						|
  if (needle > 7) {
 | 
						|
    lcdMeter[2] = byte(7); //Custom character "++"
 | 
						|
  } else if (needle > 6) {
 | 
						|
    lcdMeter[2] = '+'; //"+"
 | 
						|
  } else lcdMeter[2] = 0x20;
 | 
						|
  
 | 
						|
  
 | 
						|
#else //Must be "fat" bars
 | 
						|
  //Fill buffer with growing set of bars, up to needle value
 | 
						|
  for (int i = 0; i < 6; i++) {
 | 
						|
    if (needle > i)
 | 
						|
      lcdMeter[i] = byte(i + 1); //Custom characters above
 | 
						|
    else
 | 
						|
      lcdMeter[i] = 0x20; //blank
 | 
						|
  }
 | 
						|
 | 
						|
  if (needle > 7) {
 | 
						|
    lcdMeter[6] = byte(7); //Custom character "++"
 | 
						|
  } else if (needle > 6) {
 | 
						|
    lcdMeter[6] = '+'; //"+"
 | 
						|
  } else lcdMeter[6] = 0x20;
 | 
						|
  
 | 
						|
#endif //OPTION_FATBARS
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 char byteToChar(byte srcByte){
 | 
						|
  if (srcByte < 10)
 | 
						|
    return 0x30 + srcByte;
 | 
						|
 else
 | 
						|
    return 'A' + srcByte - 10;
 | 
						|
}
 | 
						|
 | 
						|
//returns true if the button is pressed
 | 
						|
int btnDown(void){
 | 
						|
#ifdef EXTEND_KEY_GROUP1  
 | 
						|
  if (analogRead(FBUTTON) > FUNCTION_KEY_ADC)
 | 
						|
    return 0;
 | 
						|
  else
 | 
						|
    return 1;
 | 
						|
 | 
						|
#else
 | 
						|
  if (digitalRead(FBUTTON) == HIGH)
 | 
						|
    return 0;
 | 
						|
  else
 | 
						|
    return 1;
 | 
						|
#endif    
 | 
						|
}
 | 
						|
 | 
						|
#ifdef EXTEND_KEY_GROUP1  
 | 
						|
int getBtnStatus(void){
 | 
						|
  int readButtonValue = analogRead(FBUTTON);
 | 
						|
 | 
						|
  if (analogRead(FBUTTON) < FUNCTION_KEY_ADC)
 | 
						|
    return FKEY_PRESS;
 | 
						|
  else
 | 
						|
  {
 | 
						|
    readButtonValue = readButtonValue / 4;
 | 
						|
    //return FKEY_VFOCHANGE;
 | 
						|
    for (int i = 0; i < 16; i++)
 | 
						|
      if (KeyValues[i][2] != 0 && KeyValues[i][0] <= readButtonValue && KeyValues[i][1] >= readButtonValue)
 | 
						|
        return KeyValues[i][2];
 | 
						|
        //return i;
 | 
						|
  }
 | 
						|
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
int enc_prev_state = 3;
 | 
						|
 | 
						|
/**
 | 
						|
 * The A7 And A6 are purely analog lines on the Arduino Nano
 | 
						|
 * These need to be pulled up externally using two 10 K resistors
 | 
						|
 * 
 | 
						|
 * There are excellent pages on the Internet about how these encoders work
 | 
						|
 * and how they should be used. We have elected to use the simplest way
 | 
						|
 * to use these encoders without the complexity of interrupts etc to 
 | 
						|
 * keep it understandable.
 | 
						|
 * 
 | 
						|
 * The enc_state returns a two-bit number such that each bit reflects the current
 | 
						|
 * value of each of the two phases of the encoder
 | 
						|
 * 
 | 
						|
 * The enc_read returns the number of net pulses counted over 50 msecs. 
 | 
						|
 * If the puluses are -ve, they were anti-clockwise, if they are +ve, the
 | 
						|
 * were in the clockwise directions. Higher the pulses, greater the speed
 | 
						|
 * at which the enccoder was spun
 | 
						|
 */
 | 
						|
 | 
						|
byte enc_state (void) {
 | 
						|
    return (analogRead(ENC_A) > 500 ? 1 : 0) + (analogRead(ENC_B) > 500 ? 2: 0);
 | 
						|
}
 | 
						|
 | 
						|
int enc_read(void) {
 | 
						|
  int result = 0; 
 | 
						|
  byte newState;
 | 
						|
  int enc_speed = 0;
 | 
						|
  
 | 
						|
  unsigned long start_at = millis();
 | 
						|
  
 | 
						|
  while (millis() - start_at < 50) { // check if the previous state was stable
 | 
						|
    newState = enc_state(); // Get current state  
 | 
						|
    
 | 
						|
    if (newState != enc_prev_state)
 | 
						|
      delay (1);
 | 
						|
    
 | 
						|
    if (enc_state() != newState || newState == enc_prev_state)
 | 
						|
      continue; 
 | 
						|
    //these transitions point to the encoder being rotated anti-clockwise
 | 
						|
    if ((enc_prev_state == 0 && newState == 2) || 
 | 
						|
      (enc_prev_state == 2 && newState == 3) || 
 | 
						|
      (enc_prev_state == 3 && newState == 1) || 
 | 
						|
      (enc_prev_state == 1 && newState == 0)){
 | 
						|
        result--;
 | 
						|
      }
 | 
						|
    //these transitions point o the enccoder being rotated clockwise
 | 
						|
    if ((enc_prev_state == 0 && newState == 1) || 
 | 
						|
      (enc_prev_state == 1 && newState == 3) || 
 | 
						|
      (enc_prev_state == 3 && newState == 2) || 
 | 
						|
      (enc_prev_state == 2 && newState == 0)){
 | 
						|
        result++;
 | 
						|
      }
 | 
						|
    enc_prev_state = newState; // Record state for next pulse interpretation
 | 
						|
    enc_speed++;
 | 
						|
    delay(1);
 | 
						|
  }
 | 
						|
  return(result);
 | 
						|
}
 | 
						|
 | 
						|
//===================================================================
 | 
						|
//I2C Signal Meter, Version 1.097
 | 
						|
//===================================================================
 | 
						|
 | 
						|
// 0xA0 ~ 0xCF : CW Decode Mode + 100Hz ~
 | 
						|
// 0xD0 ~ 0xF3 : RTTY Decode Mode + 100Hz ~
 | 
						|
// 0x10 ~ 0x30 : Spectrum Mode
 | 
						|
int GetI2CSmeterValue(int valueType)
 | 
						|
{
 | 
						|
  if (valueType > 0)
 | 
						|
  {
 | 
						|
    Wire.beginTransmission(I2CMETER_ADDR);  //j : S-Meter
 | 
						|
    Wire.write(valueType);                  //Y : Get Value Type
 | 
						|
    Wire.endTransmission();
 | 
						|
  }
 | 
						|
  
 | 
						|
  Wire.requestFrom(I2CMETER_ADDR, 1);
 | 
						|
 | 
						|
  if (Wire.available() > 0)
 | 
						|
  {
 | 
						|
    return Wire.read();
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 |