Created
June 16, 2015 15:57
-
-
Save Kazu-zamasu/2a72c675bb9be726b42e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Platforms | |
Components | |
Handbook | |
Cookbook | |
Code | |
Questions | |
Forum | |
Compiler | |
Dashboard | |
ARM mbed | |
Hi, Profile kazu_zamasu | |
[Beta] | |
Logout Logout | |
Users » andrewcrussell » Code » RC5_AndrewR | |
Andrew R / [This repository is a program] RC5_AndrewR | |
An RC5 decoder and preamp controller. Written on the LPC11U24, Ported to LPC1114, but it seems that version is a bit unstable. | |
Dependencies: mbed | |
Home History Graph API Documentation Wiki Pull Requests | |
file | |
revisions | |
annotate | |
diff | |
raw | |
main.cpp | |
Committer: | |
Andrew R | |
Date: | |
about 5 hours ago | |
Revision: | |
0:83d4a20e7bc7 | |
File content as of revision 0:83d4a20e7bc7: | |
/* **************************** RC5 Decoder and Preamp Controller V1.0 *************************/ | |
/* Andrew C. Russell (c) 2015 */ | |
/* This RC5 decoder works by reading in the RC5 stream from one of the serial port lines */ | |
/* and saving the incoming stream into an array called stream, after which it is decoded and */ | |
/* the command executed. A Marantz RC-68PM R/C was used to develop this program - it */ | |
/* should work with any controller complying with the Philips RC5 standard. */ | |
/* See the rc5codes.h header for the codes used. Note the address is 16 which is for a preamp. */ | |
/* The following audio preamplifier facilities are catered for:- */ | |
/* 1. Manual volume control adjustment via ALPS RK27 motorized potentiometer */ | |
/* 2. Input select via rotary encoder */ | |
/* 3. Output mute via push button actuation */ | |
/* 4. Record loop via push button actuation */ | |
/* 5. Power ON output to drive the /standby input of a system power supply */ | |
/* Facilities 1,2,3 and 5 are supported by an RC5 compliant remote control for preamplifiers */ | |
#include "mbed.h" | |
#include "rc5codes.h" // Philips RC5 code definitions | |
#include "Pindef1114.h" // all microcontroller I/O pin assignments defined here | |
#define TRUE 1 | |
#define FALSE 0 | |
#define HIGH 1 | |
#define LOW 0 | |
#define rc5_bitcount 14 // number of RC5 bits | |
#define tick 444 // quarter bit time in us | |
#define tock 1778 // one bit time in us | |
#define VUP_timeout 10 // defines max number of R/C cycles before the vol ctrl mtr drive stops | |
#define VDWN_timeout 10 // as above but for volume decrease. Needed to ensure the motor is not burnt out | |
//#define PHONO_IN 1 // these are the input assignments - not used in V1.0 of the | |
//#define CD_IN 2 // controller since the input select is just stepped | |
//#define TUN_IN 4 // through from PHONO_IN to REC_IN and back again | |
//#define AUX1_IN 8 | |
//#define MSERV_IN 16 | |
//define REC_IN 32 | |
int startbit; | |
int toggle; | |
int toggle1; | |
int toggle2; | |
int standby; | |
int address; | |
int command; | |
int FLAG1; // this is used in the remote control input processing | |
int FLAG2; // this is used in the select input processing | |
int FLAG3; // this is for the mute pushbutton | |
int FLAG4; // this is for the standby pushbutton | |
int FLAG5; // this is the recloop flag | |
int RCFLAG = FALSE; // used to determine if the select command came via R/C | |
int standbyflag; // used to save the standby condition | |
int relay; | |
int key_press = 1; // keeps track of key presses | |
int toggle_press = 1; //stores value of toggle for key_press routine | |
// delcarations below are all for the input select proceses | |
int select = 0; | |
int select_save = 1; // we save the status of select drive here. Initial value is 1 | |
int select_rot = 1; // rotary encoder pulse counter | |
// declare function prototypes here | |
void select_out (void); | |
void rc5isr(void); | |
void mute_isr(void); | |
void recloop_isr(void); | |
void select_isr(void); | |
void standby_out(void); | |
/****************************** volume increase ***********************************/ | |
void vol_up (void) | |
{ | |
if ((standbyflag == TRUE) && (key_press < VUP_timeout)) { | |
FWD1 = HIGH; | |
// FWD2 = HIGH; | |
wait(.1); //drive the motors for a short while | |
FWD1 = LOW; | |
// FWD2 = LOW; | |
} | |
if (toggle1 != toggle) { | |
key_press = 0; // user released the button, so reset counter | |
} else if (toggle1 == toggle) { | |
key_press++; // button remained depressed, so increment counter | |
} | |
toggle1 = toggle; | |
wait_ms(1); | |
} | |
/******************************* volume decrease **********************************/ | |
void vol_dwn (void) | |
{ | |
if ((standbyflag == TRUE) && (key_press < VDWN_timeout)) { | |
REV1 = HIGH; | |
// REV2 = HIGH; | |
wait(.1); //drive the motors for a short while | |
REV1 = LOW; | |
// REV2 = LOW; | |
} | |
if (toggle1 != toggle) { | |
key_press = 0; // user released the button, so reset counter | |
} else if (toggle1 == toggle) { | |
key_press++; // button remained depressed, so increment counter | |
} | |
toggle1 = toggle; | |
wait_ms(1); | |
} | |
/********************************** stdby_isr *************************************/ | |
void stdby_isr (void) | |
{ | |
FLAG4 = TRUE; | |
} | |
/*********************************** standby **************************************/ | |
/* this will require supporting hardware functionality to power down the */ | |
/* analog board, LED's etc. Best option here is to use regulators with a */ | |
/* shutdown option */ | |
void standby_out(void) // both p/button and R/C come in here | |
{ | |
stdby_int.fall(NULL); // on first power up cycle NO interuppts are accepted | |
// and neither any while this function is executed in any case | |
wait_ms(20); // a very simple debounce | |
do { // that waits for the depressed button to be released | |
(1); | |
} while (stdby !=1); | |
if (standbyflag == TRUE) { // was ON so we will turn it OFF | |
// turn off all interrupts except the standby and rc5int | |
select_int.fall(NULL); | |
mute_int.fall(NULL); | |
recloop_int.fall(NULL); | |
muteout = LOW; | |
wait(1); | |
recloop_out = LOW; | |
select_save = select_drv; // save the status of select_drv | |
select_drv = 0; // turn all input select realys OFF | |
wait(1); | |
power_ind = LOW; // this is the regulator shutdown control. HIGH = ON | |
standbyflag = FALSE; // set it up for the next power cycle | |
} else if (standbyflag == FALSE) { // was OFF so we will turn it ON | |
power_ind = HIGH; | |
rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat | |
select_int.fall(&select_isr); // input from rotary encoder or input select | |
mute_int.fall(&mute_isr); | |
recloop_int.fall(&recloop_isr); | |
wait(2); | |
select_drv = select_save; // recall the input select setting | |
wait(2); // let things settle a bit | |
muteout = HIGH; | |
standbyflag = TRUE; | |
} | |
wait_ms(5); | |
stdby_int.fall(&stdby_isr); // re-enable the standby interrupt | |
} | |
/********************************** record loop isr *******************************/ | |
void recloop_isr(void) | |
{ | |
FLAG5 = TRUE; | |
} | |
/************************** recloop - just a simple toggle ************************/ | |
void recloop() | |
{ | |
recloop_int.fall(NULL); // to prevent re-entrance when coming here from the R/C | |
wait_ms(20); // simple debounce for when mute is via the f/p p/b switch | |
do { | |
(1); // wait here until the button is released | |
} while (recloop_in!=1); | |
recloop_out = !recloop_out; | |
wait_ms(20); | |
recloop_int.fall(&recloop_isr); | |
} | |
/************************************ mute_isr ************************************/ | |
void mute_isr(void) | |
{ | |
FLAG3 = TRUE; | |
toggle2 = !toggle2; // so the p/button input is recognized in mute_out() | |
} | |
/*************************** mute - just a simple toggle **************************/ | |
void mute_out() | |
{ | |
mute_int.fall(NULL); // to prevent re-entance when coming here from the R/C | |
if ((standbyflag == TRUE) && (toggle != toggle2)) { // only toggle mute if the preamp is ON | |
wait_ms(20); //simple debounce for when mute is via the f/p p/b switch | |
do { | |
(1); //wait here until the button is released | |
} while (mute != 1); | |
muteout = !muteout; | |
wait_ms(20); | |
} | |
toggle2 = toggle; | |
mute_int.fall(&mute_isr); | |
} | |
/************************************ rc5isr **************************************/ | |
/* Interrupt triggered by a rising edge on p21 of the cont which is R/C data in */ | |
void rc5isr(void) | |
{ | |
FLAG1 = TRUE; | |
} | |
/***************** save rc5 bit stream from remote controller *********************/ | |
/* This function reads the input data on pin rc5dat at 1778us ('tock')intervals */ | |
/* and saves the data into an array stream[i]. */ | |
/* This function only looks at the second half of the bit position, since if that */ | |
/* is a 1 then it is assumed the first half of the bit position is a zero. Note */ | |
/* that in Manchester encoding, you cannot (should not) have both the 0 half-bit */ | |
/* position and the 1 half-bit position both HIGH or LOW in the same bit time - */ | |
/* a simplification exploited in this function. */ | |
void save_stream(void) | |
{ | |
bool stream[15];// the array is initialized each time its used and is local only | |
int bitloop; // number of bit positions | |
int i = 0; // counter | |
int k = 0; // temp storage | |
startbit = 0; | |
address = 0; | |
command = 0; | |
toggle = 0; | |
wait_us(tick); // locate read point in middle of 1st half bit time of the 1st start bit | |
for (bitloop = 0; bitloop <15; bitloop++) { | |
stream[bitloop] = rc5dat; //read the data and save it to array position [i] | |
wait_us(tock); //wait here until ready to read the next bit in | |
// now have 14 bits loaded into stream[i] | |
} | |
/* now put data in the array into the start, toggle, address and command variables - array counts from stream[0] */ | |
for (i=0; i<2; i++) { // first 2 bit positions are start bits = 3; will use this later for basic error checking | |
k = stream[i]; | |
startbit = (startbit << 1); | |
startbit = startbit|k; | |
} | |
toggle = stream[2]; // 3rd bit position is the toggle bit - 1 bit | |
for (i = 3; i <8; i++) { // bit positions 3 to 7 are the address (or 'system') - 5 bit positions in total | |
k = stream[i]; | |
address = (address << 1); | |
address = address|k; | |
} | |
for (i = 8; i <14; i++) { // bit positions 8 to 13 are the command - 6 bit positions | |
k = stream[i]; | |
command = (command << 1); | |
command = command|k; | |
} | |
} | |
/********************************* process_stream() *******************************/ | |
/* handles commands coming in from the remote controller only */ | |
void process_stream (void) | |
{ | |
if ((address == PREAMP) && (startbit == 3)) { | |
// basic error checking - must be preamp + startbit ok to get executed otherwise skip completly | |
switch (command) { | |
case VUP: | |
vol_up(); | |
break; | |
case VDOWN: | |
vol_dwn(); | |
break; | |
case MUTE: | |
mute_out(); | |
break; | |
case SELECT_R: | |
select_out(); | |
break; | |
case STANDBY: | |
standby_out(); | |
break; | |
} | |
} | |
} | |
/*********************************** select_isr ***********************************/ | |
void select_isr(void) | |
{ | |
FLAG2 = TRUE; | |
} | |
/********************************* select_process *********************************/ | |
/* used for selecting the input source. This function is used by both the */ | |
/* rotary encoder and the remote control */ | |
void select_process(void) | |
{ | |
if (RCFLAG == FALSE) { // if used R/C skip to select below | |
wait_ms(5); // debounce | |
select = 0; // flush select | |
select = (select | sela) <<1; // read the two port lines associated with the select rotary encoder | |
select = (select | selb); | |
} | |
switch (select) { | |
case 1: // select encoder is being rotated CW | |
select_rot <<= 1; | |
if (select_rot > 32) { | |
select_rot = 1; | |
} | |
break; | |
case 0: | |
select_rot >>= 1; // encoder is being rotated CCW | |
if (select_rot < 1) { | |
select_rot = 32; | |
} | |
break; | |
case 2: | |
{} break; // indeterminate fall through values - ignore | |
case 3: | |
{} break; | |
} | |
select_drv = select_rot; // write the value out to the bus | |
} | |
/********************* input select from remote controller only *******************/ | |
void select_out (void) | |
{ | |
if (toggle != toggle1) { // if the R/C button is held down, skip the increment | |
RCFLAG = TRUE; // this indicates command came in through the remote | |
select = 1; | |
select_process(); | |
RCFLAG = FALSE; | |
} | |
toggle1 = toggle; | |
} | |
/************************************ main() ***************************************/ | |
int main(void) | |
{ | |
__disable_irq(); // just to make sure we can set up correctly without problems | |
muteout = LOW; // mute the output while we go through power-up sequence | |
recloop_out = LOW; // make sure initial recloop condition is delected | |
power_ind = LOW; // power control; HIGH = power up | |
wait(.2); | |
Serial pc(USBTX, USBRX); // for debuging only - comment out on production | |
FLAG1 = FALSE; | |
FLAG2 = FALSE; | |
FWD1=0; | |
// FWD2=0; | |
REV1=0; | |
// REV2=0; //make sure the volume control motor is OFF | |
// set up the ISR's we will be using | |
rc5int.rise(&rc5isr); // trigger int on rising edge - go service it at rc5dat | |
select_int.fall(&select_isr); // input from rotary encoder or input select | |
mute_int.fall(&mute_isr); // mute push button interrupt | |
recloop_int.fall(&recloop_isr); // record loop push button interrupt | |
stdby_int.fall(&stdby_isr); // the system power/standby switch | |
//now disable them, leaving only the stand by p/button and rc5int interrupts active | |
select_int.fall(NULL); | |
mute_int.fall(NULL); | |
recloop_int.fall(NULL); | |
standbyflag = HIGH; // preamp will be set-up first time for OFF | |
standby_out(); // go through standby_out for initial set-up | |
select_save = 1; // phono will be selected when power is first turned on | |
__enable_irq(); | |
// all ready and in standby from this point forward | |
LOOP: // this is the main operating loop | |
__WFI(); // wait here until interrupt | |
if (FLAG1 == TRUE) { // FLAG1 indicates remote control was used | |
__disable_irq(); | |
save_stream(); | |
if (startbit == 3) { | |
process_stream(); | |
} | |
FLAG1 = FALSE; | |
__enable_irq(); | |
} | |
if (FLAG2 == TRUE) { | |
__disable_irq(); | |
select_process(); //select process | |
FLAG2 = FALSE; | |
__enable_irq(); | |
} | |
if (FLAG3 == TRUE) { | |
__disable_irq(); | |
mute_out(); //mute | |
FLAG3 = FALSE; | |
__enable_irq(); | |
} | |
if (FLAG4 == TRUE) { | |
__disable_irq(); | |
standby_out(); // standby | |
FLAG4 = FALSE; | |
__enable_irq(); | |
} | |
if (FLAG5 == TRUE) { | |
__disable_irq(); | |
recloop(); //recloop | |
FLAG5 = FALSE; | |
__enable_irq(); | |
} | |
wait_us(5); | |
goto LOOP; | |
} | |
Ask a question Start a discussion | |
Repository toolbox | |
Embed: | |
Import this program | |
Export to desktop IDE | |
Build repository | |
Follow | |
Clone repository to desktop: | |
Repository details | |
Type: Program | |
Created: about 5 hours ago | |
Imports: 4 | |
Forks: 0 | |
Commits: 1 | |
Dependents: 0 | |
Dependencies: 1 | |
Followers: 1 | |
Software licencing information | |
The code in this repository is Apache licensed. | |
© mbed blog we're hiring! support service status privacy policy terms and conditions Language: en ja es de | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment