MalachiteN 发表于 2021-5-2 01:30:35

WP 34S RPN 科学计算器上一种函数图象绘制程序的实现方式

本帖最后由 MalachiteN 于 2021-5-3 11:36 编辑

WP 34S RPN 科学计算器上一种函数图象绘制程序的实现方式
计算器爱好者之家[email protected]

      WP 34S RPN 科学计算器是基于惠普 RPN 计算器爱好者社区的一种全新的 RPN 计算器【1】(固件)。设计上,它是 HP 15C 的后代机型【2】,是 HP 34C、HP 15C、HP 16C 的结合体【3】,力求达到 HP 42S 的水准。

      该机在硬件上基于 HP 20b 或 HP 30b 这两种具有刷机接口的 RPN 金融计算器,通过刷机接口刷入自制固件的方式完成改装【4】。

计算器的六个串行端口触点于电池盖下方。它们的间距是 2 毫米。两种计算器型号(HP-20b 和 HP-30b)都是相同的。 电压电平为 0 到 3V。打开机器后盖后可以看到印刷电路板,RESET 按钮位于六个触点的上方(按下此按钮相当于短路 RESET 和 GND 触点)。
——《WP 34S 用户手册》
并且,由于原键位被覆盖,需要在原键盘上贴纸覆盖以实现最佳使用体验【5】。

      作为一台标明为 “Scientific”【6】的计算器,该机仅拥有由一块字符较大的 12 位七段式数码管显示器、一块字符较小的 3 位七段式数码管显示器、11 个标志位指示灯和一块 43*6 的 LCD 方形像素点阵显示器组成的组合式显示器。由于显示器硬件如此羸弱,而且自身的定位是科学计算器,因此该机并没有设计原生的函数图象绘制功能。

      但事实上,有部分用户在将该机作为主力的过程中遇到需要绘制一个大致的函数图象的使用情景【7】。也许这并不是刚性需求,但如果该机能够绘制大致的函数图象,能够进一步地提升用户的使用体验。Mala 经过一段时间的摸索,实现了一种可能并非最优的 WP 34S 函数图象绘制程序。

      WP 34S 具有下列图形处理函数【8】:

gDIM 是用于声明图形块的函数。(可以理解为初始化一片数字寄存器区域用于图形的储存。因为 WP 34S 中储存空间有限,图形是状态压缩之后储存的。)
gSET 是将指定寄存器地址开始的图形块绘制到屏幕上所用的函数。
gPLOT 是用于对某一特定寄存器地址开始的图形块,将其中由堆栈 X 与 Y 指定坐标的像素点点亮的函数。
      应用以上函数,我们已经可以绘制出想要绘制的函数图形。函数图形将被绘制在 LCD 方形像素点阵显示器上。以下将逐块解析实现该功能所用的 WP 34S RPN Keystoke 代码:

LBL 'DRW'
CLSTK
···
END

      这部分在进行程序的初始化。每一个内存中的子程序都有一个自己的标签(LBL),用来在运行时跳转过去。每一个 LBL 都对应一个结束标志(END)。命令 CLSTK 等效于 0 FILL,用 0 填充所有堆栈。gDIM 50 是从第 50 个寄存器开始声明一块图形块。由于 X 和 Y 堆栈被清空(均为 0),其大小将被设置为缺省的 166*8 px。之所以是这个大小,可能是因为该计算器兼容的打印机是这个分辨率。不过由于我们只是为了绘制到屏幕上,我们并不需要将这个图形块全部用上。这样写仅仅是为了减少程序步数,节省将来用于存储该程序的宝贵的闪存(Flash Memory,FM)空间。

LBL 'L11'
···
RCL+ D
x≤? I
GTO 'L11'
      这部分是该程序的主循环,也就是绘图循环。字母寄存器 I 在本程序中用于函数图象横向最长长度的偏好设置(最好与屏幕宽度同步为 43)。字母寄存器 D 在本程序中用作每次绘图递增步长的偏好设置。大于 1 则图像会变成离散函数的图像。不是特殊需求的话,D 的值最好设置为一个小于 1 的数,因为但凡变化稍微剧烈一点点的函数,都会在 x 增加 1 的时候 y 不止增加 1,这样一来图像看起来又在纵向上断开了。而如果一次增加的不到 1,那么我们会算出它更精细的位置,而绘图函数 gSET 会忠实地帮忙无条件舍去小数地将纵向上坐标不同的点绘制到横向上坐标相同的位置,让图象看起来更连贯。

      一次绘图完成后,X 栈将会自增 D 寄存器储存的数值,然后进行检测:当 X 小于等于 I 寄存器储存的数值时,执行下一步 “GTO 'L11'” 进行下一次绘图循环;当 X 大于此值,跳过该步骤。然而该步骤被跳过之后就是前文提到的 END,因而自动结束程序。

STO B
RCL+ A
XEQ 'F'
+/-
RCL* C
RCL+ J
RCL B
gSET 50
gPLOT 50
      这部分为本程序的核心代码,Mala 将进行详细解析。

         “STO B” 将目前的 X 堆栈(第一次循环时从 0 开始,每次循环都是本次绘图的横坐标)存入字母寄存器 B,其原因是 X 堆栈马上要在接下来的计算中遭到占用,需要保护重要的当前横坐标值。

         接下来立刻是一句 “RCL+ A”,把字母寄存器 A 中的值加到 X 堆栈上,X 的原值被改动(目前仍然还有机会还原,等会儿就完全破坏了)。这一步存在的原因是,绘图函数 gSET 将屏幕的最左侧视为 0 坐标,但我们想要观看大致的函数图象必然不可能只看一四象限,因此我们给它加上一个偏好设置用的字母寄存器 A。A 储存着告诉程序 “屏幕的最左侧等于哪个实际 X 轴坐标” 的信息,一般是一个负值,如果想要函数图象位于屏幕正中间就用 -22,当然也可以按需调整。

      再往后就是以当前处理过的横坐标 X 为自变量来计算被绘图的一元函数 F 的函数值。因为这个函数需要经常修改,它应该被储存在 RAM 中。

      例如:
LBL 'F'
SIN
END
      这样的写法让计算器绘制 y = sin x 的函数图象。

      此时的 X 堆栈将因为被作为函数 F 的参数而被消耗,数据完全丢失。而 F 的返回值【9】将会替代到 X 栈中,由此 X 栈被彻底破坏。不过这不会造成不良影响,因为我们之前已经把横坐标备份到字母寄存器 B 中了。

      然后是一个 “+/-”,再 “RCL* C”,“RCL+ J”。

      首先它对 X 堆栈取相反数。之所以这样做,是因为 WP 34S 以最上面的一行像素为 0,往下逐行递增,每次增加 1。如果不做处理而就这样画到屏幕上,我们看到的将是一个上下颠倒的函数图象。因为 WP 34S 并不是颈椎病理疗器械,这显然不合理。

      然后我们给 X 栈乘上字母寄存器 C 的值。这是之前说到的逐行递增的缘故。每增加一行只需要增加 1,如果不做任何处理,这会导致值域为 [-1, 1] 的函数(如三角函数)的图象只占两三行,根本看不清。寄存器 C 就是作为函数图象 y 轴方向的放大倍率而存在的偏好设置。

      最后给 X 加上字母寄存器 J 的值,是因为被反转后的 x 轴位于屏幕最下方,而很明显我们多数时候不止想看第一象限,所以给它加上一个向上平移的偏好设置 J。一般将 J 设置为 3,x 轴就会位于屏幕中间。当然如果用户真的只需要第一象限,而且还想放大了看得更清楚,也完全可以将 J 设为 0。

      这样就完成了对于绘图坐标的加工处理工作,可以着手绘制了。

RCL B
gSET 50
gPLOT 50
      这段就是最后把横纵坐标对应的像素点绘制到屏幕上用的代码了。第一步 “RCL B” 从备份用的字母寄存器 B 中提取出我们的横坐标,并存入 X 堆栈。将要绘制的纵坐标原来在 X 堆栈中,现因自动堆栈提升【10】而被放到了 Y 堆栈里面。正巧 WP 34S 的 gSET 函数要求横坐标在 X 里面,纵坐标在 Y 里面,于是我们立即调用它来绘制图象。再往后,为了现场显示逐步绘制过程,我们将 gPLOT 函数放在了循环内部。当然如果你想要效率更高,完全可以把这一句放在 “GTO 'L11'” 与 “END” 之间,这样就只绘制一次,更快了,但看不见过程。

      以上就是全部代码的解析了。为了方便大家使用,现将该程序的完整代码附于下方:

LBL 'DRW'
CLSTK
gDIM 50
LBL 'L11'
STO B
RCL+ A
XEQ 'F'
+/-
RCL* C
RCL+ J
RCL B
gSET 50
gPLOT 50
RCL+ D
x≤? I
GTO 'L11'
END
      为了尽量少占用比起 FM 更加宝贵的 RAM 空间,也为了断电后不用重新输入程序,读者可以把该程序输入 RAM 之后,将程序指针指向它的 LBL(即按下 (P/R) 进入编程模式,然后通过上下箭头导航键导航到 LBL 程序步),然后利用程序指令菜单( (P.FCN) )中的程序储存( PSTO )命令将该程序储存到 FM 空间中。需要注意的是,FM 的擦写寿命有限,而且每次进行任意一点的更改就需要进行一次全盘擦写,因此请千万确保程序完全没有问题之后再存入 FM。

      另外,WP 34S 的处理速度非常慢【11】。请耐心等待图象绘制完成。

      以上为 Mala 提供的在 WP 34S RPN Scientific 上绘制函数图象的方法。希望能够为各位 WP 34S 用户带来一定用户体验的提升。如果读者有任何问题或发现了更好的解决方案,欢迎联系 Mala。

【1】RPN 是一种特殊的表达式表示法。RPN 计算器采用这种方式进行表达式的输入计算。如果不甚了解,可以到知乎专栏《计算器爱好者之家》的这一篇文章《什么是逆波兰(RPN)计算?》中进行了解。进一步地,可以在该专栏这篇文章《RPN基础知识》中学习如何使用这种表达式表示法。
【2】RPN calculator club 群 群友 scott tang 发言。
【3】RPN calculator club 群 群友 wp34s 发言。
【4】见《WP 34S 用户手册》附录 A “制作和升级 WP 34S” 的 “如何刷机” 部分。
【5】见《WP 34S 用户手册》附录 A “制作和升级 WP 34S” 的 “购买和自制键盘贴” 部分和附录 L “自制临时键盘贴”。
【6】一般而言,Scientific(科学计算器,即“函数计算器”,“函数机”)不会具备绘制函数图象的功能。【7】例如求解学习人教版高中《数学》必修一时的考试中经常出现的“给定函数解析式,选出正确的函数大致图象”选择题。
【8】见《WP 34S 用户手册》第五章 “操作指令目录(IOP)”。
【9】 RPN Keystoke 编程更接近汇编语言,实际上并没有高级语言编程方式中的所谓“传参”和“返回值”概念,只有标签跳转和堆栈操作。此处引入“返回值”是为了帮助理解。事实上内部的运行方式是:X 堆栈被用于计算函数 F 的函数值,然后被弹出,紧接着函数值被重新压入 X 栈。原来 X 栈储存的自变量值被函数值替代。
【10】自动堆栈提升是 RPN 计算器的一种特性。当 X 堆栈未被弹出,而机器想要把一个值压入堆栈时,原来的堆栈将全部自动提升—— T 被丢弃,Z 进入 T,Y 进入 Z,空出 X 来存入新数值。参见《WP 34S 用户手册》第二章 “从这里开始” 的 “堆栈基本机制” 部分第 18 个注释 :“自动堆栈提升”。
【11】如下处理器:Atmel AT91SAM7L128,带 thumb 模式的 ARM 7 内核(32kHz 至 40MHz)。
——《WP 34S 用户手册》附录 H “适合高级用户的额外功能” 的 “HP 20b 和 HP 30b 的基本硬件规格” 部分



think21st 发表于 2021-5-2 14:14:17

看不懂。图在哪里

tangdfx 发表于 2021-5-12 09:42:21

看到我的发言了

zhoudb 发表于 2021-8-26 22:34:47

好像不是汇编

wan 发表于 2021-9-18 06:42:34

不是汇编,就是机器自带的按键编程。这个机器能做到这种绘图,属于附赠的“惊喜”

cpcw 发表于 2021-10-21 09:08:20

赞一个,写得和论文一下{:13_331:}

FreeBlues 发表于 2024-3-14 00:56:18

很有意思的程序!

我在模拟器上跑的结果:

FreeBlues 发表于 2024-3-14 00:57:39

这个是参数,只显示了第一象限的

页: [1]
查看完整版本: WP 34S RPN 科学计算器上一种函数图象绘制程序的实现方式