McIntosh MX120 or MX136
vining Posts: 4,368
Any one out there got a decent module for one of these AVRs that they are willing to give away, sell, trade, barter or let me steel. This is likely a one time usage and I really, really don't want to start from scratch.
Source selections, surround mode, and volume ramping and are button channels on the touch panel. You specify whether you are controlling zone A or B with channel 201 (on = on the port the McIntosh is connected to (the actual serial port). Passthru, such as it is, is done by setting the string passed to the module with the command you want the Mac to receive; I recently added the ability to use it for discrete volume as well. It's not extensively commented, but you should be able to figure it out. I've also zipped up the original Mac protocol for your reference (or in case you decide to do it properly yourself).
Very much appreciated!
This is how I would write it.
My thoughts on this:
I don't see the point of using DEFINE_CALL ever.
var == FALSE/TRUE is bad form in most languages.
You don't immediately set bMX_Busy = TRUE after entering the if statement, which means if another button event happens before it is set you could get more than one command sent immediately after one another with no wait triggered since this code: could potentially call 'SendMX13X' many times a second if the buffer is full. This is a worry if you are in a multi-threaded environment.
No point in naming a wait you never cancel, and in this case you would never want to cancel it.
Why did you use the chardm command? I wonder if using it cures the possible successive commands sent with no delay but at the expense of response time.
I don't use the chardm but leave 0.5 second wait between commands and ignore all others and volume etc ramp quite quickly.
Did your MX lock up if you didn't use chardm?
One thing I have noticed AMX programmers do is write much more in ALL CAPS which I find so much harder to read. Why is that?
That appears to be the consensus - it is archaic and unnecessary.
I beg to differ - this form of coding makes it absolutely clear what you mean. Anything you type that makes things clearer is a good thing. I go further and specify things like...
...so that you can never be unsure what your code means, especially when 1 means "Off"!
I understand where you are coming from on this, and I have struggled with it many times.
When writing AMX code you need to understand that (to a first approximation) it is NOT multithreaded. You can *always* assume that one line of your code will never interrupt two other consecutive lines of your code. Everything takes its turn. There are some things which happen "in the background" but you can safely disregard them as long as you understand them.
Good practice is to always name a wait because good practice is always to cancel it before you start it. That way you never get bitten later.
chardm controls the interval between bytes, not the interval between commands. I've never used it. I imagine it is historical to allow for controlled gear with old or non-existent UARTS.
The best way to handle command timing is to wait for the ACK before you send the next one. You'll need a queue.
That is historical, going back to Axcess days; if you don't know what that means, be happy. None of my code is CAPS; like you, I use the CaseConventionOfMyTraining.
Likewise the caps thing - in Axcent, everything was in caps - I used to code with the caps lock key on. Nowadays, I use all caps for two things: constants and keywords. It's not necessary at all, but in my mind it makes those things stand out so I know exactly what they are at a glance. Yes, I know the editor color codes key words, but for me the caps registers before the color does.
I name every WAIT, as a matter of policy. It doesn't hurt to do so, and I don't need to worry about collisions. If you do not name your waits, and you call a second one while the first is still active, it won't fire until the first has. You might think this is unlikely, but I have seen it happen, and naming waits solves it.
CHARDM is there because of hardware issues. It controls the pacing of individual bits in the serial port for devices that cannot handle them sent too quickly. It is not the pacing between strings, but between every single character of the string. There is no point at all writing a routine for this when there is a built-in solution. The early McIntosh products required that ... and I have left it in from sheer lack of will to see if they are still needed. Besides, it's presences ensures the code will work on the older units, and doesn't hurt the newer ones.
A quick experiment shows this isn't so.
Won't cancel_all_waits cancel the waits? If what you say is true then how is it that I can have a wait 50 in mainline and it only runs once every 5 seconds rather than 200 times a second? It seems to me that an unnamed wait that gets called before it can do what its waiting to do gets collapsed.
A given unnamed wait will not pile up but will execute one at a time. Don't ask why, just be grateful!
Once a wait is placed in queue keeping in mind that all waits are actually named the system will see that is is already in queue and not overwrite it because if that were not the case a wait in mainline would never execute it would simple be re-written on every pass.
Basically when you call a wait the system checks the wait queue to see if that wait is already pending and if it is it ignores the wait and does nothing until the queued wait executes and expires but if the wait is not already in queue then it gets added.
Too right. How to bite yourself later.
I am starting to think we need a sticky thread concerning waits considering the topic appears so often.
I have never used Cancel_All_Waits, but I can think of a way it might be useful. Consider a Master to Master system where each master is running its own code. There might be a time it could be used in a reset subroutine in order to sync up multiple systems. The trigger for the reset subroutine would come from an Online Data_Event from the remote system.
This description by vining is absolutely correct and not open for dispute.
Could not agree more.
completely contradict this:
From the help file:
This seems to indicate that the NEW wait is thrown away, not the old one, when the system encounters another named wait of the same name. I always do a cancel_wait before calling a wait to avoid this behavior. However, with an unnamed wait, since you cannot explicitly cancel it, the system seems to cancel it for you.
So if you use a named wait in define_program and cancel it what happens?
cancel_wait 'wait for it'
wait 50 'wait for it'
print("'I've waited long enough'")
Will this ever get printed? It shoudn't.
Simply stated, only one instance of any wait, named or unnamed, can be pending in the wait queue at a time. Cancelling a named wait removes it from the wait queue and the underlying code will never execute.