mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-26 21:30:55 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
7b689f9089
133
published/20190114 Remote Working Survival Guide.md
Normal file
133
published/20190114 Remote Working Survival Guide.md
Normal file
@ -0,0 +1,133 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (beamrolling)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-10518-1.html)
|
||||
[#]: subject: (Remote Working Survival Guide)
|
||||
[#]: via: (https://www.jonobacon.com/2019/01/14/remote-working-survival/)
|
||||
[#]: author: (Jono Bacon https://www.jonobacon.com/author/admin/)
|
||||
|
||||
远程工作生存指南
|
||||
======
|
||||
|
||||
![](https://www.jonobacon.com/wp-content/uploads/2019/01/5b5471d7eadb585ec8b8a0c3_featureimage-remotejob-1080x675.jpg)
|
||||
|
||||
远程工作似乎是最近的一个热门话题。CNBC 报道称,[70% 的专业人士至少每周在家工作一次][1]。同样地,CoSo Cloud 调查发现, [77% 的人在远程工作时效率更高][2] ,而 aftercollege 的一份调查显示,[8% 的千禧一代会更多地考虑提供远程工作的公司][3]。 这看起来很合理:技术、网络以及文化似乎越来越推动了远程工作的发展。哦,自制咖啡也比以前任何时候更好喝了。
|
||||
|
||||
目前,我准备写另一篇关于公司如何优化远程工作的文章(所以请确保你加入我们的会员以持续关注——这是免费的)。
|
||||
|
||||
但今天,我想 **分享一些个人如何做好远程工作的建议**。不管你是全职远程工作者,或者是可以选择一周某几天在家工作的人,希望这篇文章对你有用。
|
||||
|
||||
眼下,你需要明白,**远程工作不是万能药**。当然,穿着睡衣满屋子乱逛,听听反社会音乐,喝一大杯咖啡看起来似乎挺完美的,但这不适合每个人。
|
||||
|
||||
有的人需要办公室的空间。有的人需要办公室的社会元素。有的人需要从家里走出来。有的人在家里缺乏保持专注的自律。有的人因为好几年未缴退税而怕政府工作人员来住处敲门。
|
||||
|
||||
**远程工作就好像一块肌肉:如果你锻炼并且保持它,那么它能带来极大的力量和能力**。如果不这么做,结果就不一样了。
|
||||
|
||||
在我职业生涯的大多数时间里,我在家工作。我喜欢这么做。当我在家工作的时候,我更有效率,更开心,更有能力。我并非不喜欢在办公室工作,我享受办公室的社会元素,但我更喜欢在家工作时我的“空间”。我喜欢听重金属音乐,但当整个办公室的人不想听到 [After The Burial][5] 的时候,这会引起一些问题。
|
||||
|
||||
![][6]
|
||||
|
||||
*“Squirrel.” [图片来源][7]*
|
||||
|
||||
我已经学会了如何正确平衡工作、旅行以及其他元素来管理我的远程工作,以下是我的一些建议。请务必**在评论中分享一些你的建议**。
|
||||
|
||||
### 1、你需要纪律和习惯(以及了解你的“波动”)
|
||||
|
||||
远程工作确实是需要训练的一块肌肉。就像练出真正的肌肉一样,它需要一个明确的习惯混以健康的纪律。
|
||||
|
||||
永远保持穿戴整齐(不要穿睡衣)。设置你一天工作的开始和结束时间(大多时候我从早上 9 点工作到下午 6 点)。选好你的午餐休息时间(我的是中午 12 点)。选好你的早晨仪式(我的是电子邮件,紧接着是全面审查客户需求)。决定你的主工作场所在哪(我的主工作场所是我家庭办公室)。决定好每天你什么时候运动(大多数时候我在下午 5 点运动)。
|
||||
|
||||
**设计一个实际的习惯并坚持 66 天**。建立一个习惯需要很长时间,尽量不要偏离你的习惯。你越坚持这个习惯,做下去所花费的功夫越少。在这 66 天的末尾,你想都不会想,自然而然地就按习惯去做了。
|
||||
|
||||
话虽这么说,我们又不住在真空里 ([更干净,或者别的什么][8])。我们都有自己的“波动”。
|
||||
|
||||
“波动”是你为了改变做事的方法时,对日常做出的一些改变。举个例子,夏天的时候我通常需要更多的阳光。那时我经常会在室外的花园工作。临近假期的时候我更容易分心,所以我在上班时间会更需要呆在室内。有时候我只想要多点人际接触,因此我会在咖啡馆里工作几周。有时候我就是喜欢在厨房或者长椅上工作。你需要认识你的“波动”并倾听你的身体。 **首先养成习惯,然后在你认识到自己的“波动”的时候再对它进行适当的调整**。
|
||||
|
||||
### 2、与你的上司及同事一起设立预期目标
|
||||
|
||||
不是每个人都知道怎么远程工作,如果你的公司对远程工作没那么熟悉,你尤其需要和同事一起设立预期目标。
|
||||
|
||||
这件事十分简单:**当你要设计自己的日常工作的时候,清楚地跟你的上司和团队进行交流。**让他们知道如何找到你,紧急情况下如何联系你,以及你在家的时候如何保持合作。
|
||||
|
||||
在这里通信方式至关重要。有些远程工作者很怕离开他们的电脑,因为害怕当他们不在的时候有人给他们发消息(他们担心别人会觉得他们在边吃奇多边看 Netflix)。
|
||||
|
||||
你需要离开一会的时间。你需要在吃午餐的时候眼睛不用一直盯着电脑屏幕。你又不是 911 接线员。**设定预期:有时候你可能不能立刻回复,但你会尽快回复**。
|
||||
|
||||
同样地,设定你的通常可响应的时间范围的预期。举个例子,我对客户设立的预期是我一般每天早上 9 点到下午 6 点工作。当然,如果某个客户急需某样东西,我很乐意在这段时间外回应他,但作为一个一般性规则,我通常只在这段时间内工作。这对于生活的平衡是必要的。
|
||||
|
||||
### 3、分心是你的敌人,它们需要管理
|
||||
|
||||
我们都会分心,这是人类的本能。让你分心的事情可能是你的孩子回家了,想玩救援机器人;可能是看看Facebook、Instagram,或者 Twitter 以确保你不会错过任何不受欢迎的政治观点,或者某人的午餐图片;可能是你生活中即将到来的某件事带走了你的注意力(例如,即将举办的婚礼、活动,或者一次大旅行)。
|
||||
|
||||
**你需要明白什么让你分心以及如何管理它**。举个例子,我知道我的电子邮件和 Twitter 会让我分心。我经常查看它们,并且每次查看都会让我脱离我正在工作的空间。拿水或者咖啡的时候我总会分心去吃零食,看 Youtube 的视频。
|
||||
|
||||
![][9]
|
||||
|
||||
*我的分心克星*
|
||||
|
||||
由数字信息造成的分心有一个简单对策:**锁起来**。关闭选项卡,直到你完成了你手头的事情。有一大堆工作的时候我总这么干:我把让我分心的东西锁起来,直到做完手头的工作。这需要控制能力,但所有的一切都需要。
|
||||
|
||||
因为别人影响而分心的元素更难解决。如果你是有家庭的人,你需要明确表示,在你工作的时候常需要独处。这也是为什么家庭办公室这么重要:你需要设一些“爸爸/妈妈正在工作”的界限。如果有急事才能进来,否则让孩子自个儿玩去。
|
||||
|
||||
把让你分心的事锁起来有许多方法:把你的电话静音;把自己的 Facebook 状态设成“离开”;换到一个没有让你分心的事的房间(或建筑物)。再重申一次,了解是什么让你分心并控制好它。如果不这么做,你会永远被分心的事摆布。
|
||||
|
||||
### 4、(良好的)关系需要面对面的关注
|
||||
|
||||
有些角色比其他角色更适合远程工作。例如,我见过工程、质量保证、支持、安全以及其他团队(通常更专注于数字信息协作)的出色工作。其他团队,如设计或营销,往往在远程环境下更难熬(因为它们更注重触觉性)。
|
||||
|
||||
但是,对于任何团队而言,建立牢固的关系至关重要,而现场讨论、协作和社交很有必要。我们的许多感官(例如肢体语言)在数字环境中被剔除,而这些在我们建立信任和关系的方式中发挥着关键作用。
|
||||
|
||||
![][10]
|
||||
|
||||
*火箭也很有帮助*
|
||||
|
||||
这尤为重要,如果(a)你初来这家公司,需要建立关系;(b)对某种角色不熟悉,需要和你的团队建立关系;或者(c)你处于领导地位,构建团队融入和参与是你工作的关键部分。
|
||||
|
||||
**解决方法是?合理搭配远程工作与面对面的时间。** 如果你的公司就在附近,可以用一部分的时间在家工作,一部分时间在公司工作。如果你的公司比较远,安排定期前往办公室(并对你的上司设定你需要这么做的预期)。例如,当我在 XPRIZE 工作的时候,我每几周就会飞往洛杉矶几天。当我在 Canonical 工作时(总部在伦敦),我们每三个月来一次冲刺。
|
||||
|
||||
### 5、保持专注,不要松懈
|
||||
|
||||
本文所有内容的关键在于构建一种(远程工作的)能力,并培养远程工作的肌肉。这就像建立你的日常惯例,坚持它,并认识你的“波动”和让你分心的事情以及如何管理它们一样简单。
|
||||
|
||||
我以一种相当具体的方式来看待这个世界:**我们所做的一切都有机会得到改进和完善**。举个例子,我已经公开演讲超过 15 年,但我总是能发现新的改进方法,以及修复新的错误(说到这些,请参阅我的 [提升你公众演讲的10个方法][11])。
|
||||
|
||||
发现新的改善方法,以及把每个绊脚石和错误视为一个开启新的不同的“啊哈!”时刻让人兴奋。远程工作和这没什么不同:寻找有助于解锁方式的模式,让你的远程工作时间更高效,更舒适,更有趣。
|
||||
|
||||
![][12]
|
||||
|
||||
*看看这些书。它们非常适合个人发展。参阅我的 [150 美元个人发展工具包][13] 文章*
|
||||
|
||||
……但别为此狂热。有的人花尽他们每一分钟来寻求如何变得更好,他们经常以“做得还不够好”、“完成度不够高”等为由打击自己,无法达到他们内心关于完美的不切实际的观点。
|
||||
|
||||
我们都是人,我们是有生命的,不是机器人。始终致力于改进,但要明白不是所有东西都是完美的。你应该有一些休息日或休息周。你也会因为压力和倦怠而挣扎。你也会遇到一些在办公室比远程工作更容易的情况。从这些时刻中学习,但不要沉迷于此。生命太短暂了。
|
||||
|
||||
**你有什么提示,技巧和建议吗?你如何管理远程工作?我的建议中还缺少什么吗?在评论区中与我分享!**
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.jonobacon.com/2019/01/14/remote-working-survival/
|
||||
|
||||
作者:[Jono Bacon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[beamrolling](https://github.com/beamrolling)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.jonobacon.com/author/admin/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cnbc.com/2018/05/30/70-percent-of-people-globally-work-remotely-at-least-once-a-week-iwg-study.html
|
||||
[2]: http://www.cosocloud.com/press-release/connectsolutions-survey-shows-working-remotely-benefits-employers-and-employees
|
||||
[3]: https://www.aftercollege.com/cf/2015-annual-survey
|
||||
[4]: https://www.jonobacon.com/join/
|
||||
[5]: https://www.facebook.com/aftertheburial/
|
||||
[6]: https://www.jonobacon.com/wp-content/uploads/2019/01/aftertheburial2.jpg
|
||||
[7]: https://skullsnbones.com/burial-live-photos-vans-warped-tour-denver-co/
|
||||
[8]: https://www.youtube.com/watch?v=wK1PNNEKZBY
|
||||
[9]: https://www.jonobacon.com/wp-content/uploads/2019/01/IMG_20190114_102429-1024x768.jpg
|
||||
[10]: https://www.jonobacon.com/wp-content/uploads/2019/01/15381733956_3325670fda_k-1024x576.jpg
|
||||
[11]: https://www.jonobacon.com/2018/12/11/10-ways-to-up-your-public-speaking-game/
|
||||
[12]: https://www.jonobacon.com/wp-content/uploads/2019/01/DwVBxhjX4AgtJgV-1024x532.jpg
|
||||
[13]: https://www.jonobacon.com/2017/11/13/150-dollar-personal-development-kit/
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (ezio )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
@ -7,6 +7,8 @@
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html)
|
||||
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
|
||||
|
||||
ezio is translating
|
||||
|
||||
Computer Laboratory – Raspberry Pi: Lesson 10 Input01
|
||||
======
|
||||
|
||||
@ -482,7 +484,7 @@ via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input01.html
|
||||
|
||||
作者:[Alex Chadwick][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[ezio](https://github.com/oska874)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,449 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 7 Screen02)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen02.html)
|
||||
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
|
||||
|
||||
Computer Laboratory – Raspberry Pi: Lesson 7 Screen02
|
||||
======
|
||||
|
||||
The Screen02 lesson builds on Screen01, by teaching how to draw lines and also a small feature on generating pseudo random numbers. It is assumed you have the code for the [Lesson 6: Screen01][1] operating system as a basis.
|
||||
|
||||
### 1 Dots
|
||||
|
||||
Now that we've got the screen working, it is only natural to start waiting to create sensible images. It would be very nice indeed if we were able to actually draw something. One of the most basic components in all drawings is a line. If we were able to draw a line between any two points on the screen, we could start creating more complicated drawings just using combinations of these lines.
|
||||
|
||||
```
|
||||
To allow complex drawing, some systems use a colouring function rather than just one colour to draw things. Each pixel calls the colouring function to determine what colour to draw there.
|
||||
```
|
||||
|
||||
We will attempt to implement this in assembly code, but first we could really use some other functions to help. We need a function I will call SetPixel that changes the colour of a particular pixel, supplied as inputs in r0 and r1. It will be helpful for future if we write code that could draw to any memory, not just the screen, so first of all, we need some system to control where we are actually going to draw to. I think that the best way to do this would be to have a piece of memory which stores where we are going to draw to. What we should end up with is a stored address which normally points to the frame buffer structure from last time. We will use this at all times in our drawing method. That way, if we want to draw to a different image in another part of our operating system, we could make this value the address of a different structure, and use the exact same code. For simplicity we will use another piece of data to control the colour of our drawings.
|
||||
|
||||
Copy the following code to a new file called 'drawing.s'.
|
||||
|
||||
```
|
||||
.section .data
|
||||
.align 1
|
||||
foreColour:
|
||||
.hword 0xFFFF
|
||||
|
||||
.align 2
|
||||
graphicsAddress:
|
||||
.int 0
|
||||
|
||||
.section .text
|
||||
.globl SetForeColour
|
||||
SetForeColour:
|
||||
cmp r0,#0x10000
|
||||
movhs pc,lr
|
||||
ldr r1,=foreColour
|
||||
strh r0,[r1]
|
||||
mov pc,lr
|
||||
|
||||
.globl SetGraphicsAddress
|
||||
SetGraphicsAddress:
|
||||
ldr r1,=graphicsAddress
|
||||
str r0,[r1]
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
This is just the pair of functions that I described above, along with their data. We will use them in 'main.s' before drawing anything to control where and what we are drawing.
|
||||
|
||||
```
|
||||
Building generic methods like SetPixel which we can build other methods on top of is a useful idea. We have to make sure the method is fast though, since we will use it a lot.
|
||||
```
|
||||
|
||||
Our next task is to implement a SetPixel method. This needs to take two parameters, the x and y co-ordinate of a pixel, and it should use the graphicsAddress and foreColour we have just defined to control exactly what and where it is drawing. If you think you can implement this immediately, do, if not I shall outline the steps to be taken, and then give an example implementation.
|
||||
|
||||
1. Load in the graphicsAddress.
|
||||
2. Check that the x and y co-ordinates of the pixel are less than the width and height.
|
||||
3. Compute the address of the pixel to write. (hint: frameBufferAddress + (x + y core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated width) * pixel size)
|
||||
4. Load in the foreColour.
|
||||
5. Store it at the address.
|
||||
|
||||
|
||||
|
||||
An implementation of the above follows.
|
||||
|
||||
1.
|
||||
```
|
||||
.globl DrawPixel
|
||||
DrawPixel:
|
||||
px .req r0
|
||||
py .req r1
|
||||
addr .req r2
|
||||
ldr addr,=graphicsAddress
|
||||
ldr addr,[addr]
|
||||
```
|
||||
|
||||
2.
|
||||
```
|
||||
height .req r3
|
||||
ldr height,[addr,#4]
|
||||
sub height,#1
|
||||
cmp py,height
|
||||
movhi pc,lr
|
||||
.unreq height
|
||||
|
||||
width .req r3
|
||||
ldr width,[addr,#0]
|
||||
sub width,#1
|
||||
cmp px,width
|
||||
movhi pc,lr
|
||||
```
|
||||
|
||||
Remember that the width and height are stored at offsets of 0 and 4 into the frame buffer description respectively. You can refer back to 'frameBuffer.s' if necessary.
|
||||
|
||||
3.
|
||||
```
|
||||
ldr addr,[addr,#32]
|
||||
add width,#1
|
||||
mla px,py,width,px
|
||||
.unreq width
|
||||
.unreq py
|
||||
add addr, px,lsl #1
|
||||
.unreq px
|
||||
```
|
||||
|
||||
```
|
||||
mla dst,reg1,reg2,reg3 multiplies the values from reg1 and reg2, adds the value from reg3 and places the least significant 32 bits of the result in dst.
|
||||
```
|
||||
|
||||
Admittedly, this code is specific to high colour frame buffers, as I use a bit shift directly to compute this address. You may wish to code a version of this function without the specific requirement to use high colour frame buffers, remembering to update the SetForeColour code. It may be significantly more complicated to implement.
|
||||
|
||||
4.
|
||||
```
|
||||
fore .req r3
|
||||
ldr fore,=foreColour
|
||||
ldrh fore,[fore]
|
||||
```
|
||||
|
||||
As above, this is high colour specific.
|
||||
|
||||
5.
|
||||
```
|
||||
strh fore,[addr]
|
||||
.unreq fore
|
||||
.unreq addr
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
As above, this is high colour specific.
|
||||
|
||||
|
||||
|
||||
|
||||
### 2 Lines
|
||||
|
||||
The trouble is, line drawing isn't quite as simple as you may expect. By now you must realise that when making operating system, we have to do almost everything ourselves, and line drawing is no exception. I suggest for a few minutes you have a think about how you would draw a line between any two points.
|
||||
|
||||
```
|
||||
When programming normally, we tend to be lazy with things like division. Operating Systems must be incredibly efficient, and so we must focus on doing things as best as possible.
|
||||
```
|
||||
|
||||
I expect the central idea of most strategies will involve computing the gradient of the line, and stepping along it. This sounds perfectly reasonable, but is actually a terrible idea. The problem with it is it involves division, which is something that we know can't easily be done in assembly, and also keeping track of decimal numbers, which is again difficult. There is, in fact, an algorithm called Bresenham's Algorithm, which is perfect for assembly code because it only involves addition, subtraction and bit shifts.
|
||||
```
|
||||
Let's start off by defining a reasonably straightforward line drawing algorithm as follows:
|
||||
|
||||
if x1 > x0 then
|
||||
|
||||
set deltax to x1 - x0
|
||||
set stepx to +1
|
||||
|
||||
otherwise
|
||||
|
||||
set deltax to x0 - x1
|
||||
set stepx to -1
|
||||
|
||||
end if
|
||||
|
||||
if y1 > y0 then
|
||||
|
||||
set deltay to y1 - y0
|
||||
set stepy to +1
|
||||
|
||||
otherwise
|
||||
|
||||
set deltay to y0 - y1
|
||||
set stepy to -1
|
||||
|
||||
end if
|
||||
|
||||
if deltax > deltay then
|
||||
|
||||
set error to 0
|
||||
until x0 = x1 + stepx
|
||||
|
||||
setPixel(x0, y0)
|
||||
set error to error + deltax ÷ deltay
|
||||
if error ≥ 0.5 then
|
||||
|
||||
set y0 to y0 + stepy
|
||||
set error to error - 1
|
||||
|
||||
end if
|
||||
set x0 to x0 + stepx
|
||||
|
||||
repeat
|
||||
|
||||
otherwise
|
||||
|
||||
end if
|
||||
|
||||
This algorithm is a representation of the sort of thing you may have imagined. The variable error keeps track of how far away from the actual line we are. Every step we take along the x axis increases this error, and every time we move down the y axis, the error decreases by 1 unit again. The error is measured as a distance along the y axis.
|
||||
|
||||
While this algorithm works, it suffers a major problem in that we clearly have to use decimal numbers to store error, and also we have to do a division. An immediate optimisation would therefore be to change the units of error. There is no need to store it in any particular units, as long as we scale every use of it by the same amount. Therefore, we could rewrite the algorithm simply by multiplying all equations involving error by deltay, and simplifying the result. Just showing the main loop:
|
||||
|
||||
set error to 0 × deltay
|
||||
until x0 = x1 + stepx
|
||||
|
||||
setPixel(x0, y0)
|
||||
set error to error + deltax ÷ deltay × deltay
|
||||
if error ≥ 0.5 × deltay then
|
||||
|
||||
set y0 to y0 + stepy
|
||||
set error to error - 1 × deltay
|
||||
|
||||
end if
|
||||
set x0 to x0 + stepx
|
||||
|
||||
repeat
|
||||
|
||||
Which simplifies to:
|
||||
|
||||
set error to 0
|
||||
until x0 = x1 + stepx
|
||||
|
||||
setPixel(x0, y0)
|
||||
set error to error + deltax
|
||||
if error × 2 ≥ deltay then
|
||||
|
||||
set y0 to y0 + stepy
|
||||
set error to error - deltay
|
||||
|
||||
end if
|
||||
set x0 to x0 + stepx
|
||||
|
||||
repeat
|
||||
|
||||
Suddenly we have a much better algorithm. We see now that we've eliminated the need for division altogether. Better still, the only multiplication is by 2, which we know is just a bit shift left by 1! This is now very close to Bresenham's Algorithm, but one further optimisation can be made. At the moment, we have an if statement which leads to two very similar blocks of code, one for lines with larger x differences, and one for lines with larger y differences. It is worth checking if the code could be converted to a single statement for both types of line.
|
||||
|
||||
The difficulty arises somewhat in that in the first case, error is to do with y, and in the second case error is to do with x. The solution is to track the error in both variables simultaneously, using negative error to represent an error in x, and positive error in y.
|
||||
|
||||
set error to deltax - deltay
|
||||
until x0 = x1 + stepx or y0 = y1 + stepy
|
||||
|
||||
setPixel(x0, y0)
|
||||
if error × 2 > -deltay then
|
||||
|
||||
set x0 to x0 + stepx
|
||||
set error to error - deltay
|
||||
|
||||
end if
|
||||
if error × 2 < deltax then
|
||||
|
||||
set y0 to y0 + stepy
|
||||
set error to error + deltax
|
||||
|
||||
end if
|
||||
|
||||
repeat
|
||||
|
||||
It may take some time to convince yourself that this actually works. At each step, we consider if it would be correct to move in x or y. We do this by checking if the magnitude of the error would be lower if we moved in the x or y co-ordinates, and then moving if so.
|
||||
```
|
||||
|
||||
```
|
||||
Bresenham's Line Algorithm was developed in 1962 by Jack Elton Bresenham, 24 at the time, whilst studying for a PhD.
|
||||
```
|
||||
|
||||
Bresenham's Algorithm for drawing a line can be described by the following pseudo code. Pseudo code is just text which looks like computer instructions, but is actually intended for programmers to understand algorithms, rather than being machine readable.
|
||||
|
||||
```
|
||||
/* We wish to draw a line from (x0,y0) to (x1,y1), using only a function setPixel(x,y) which draws a dot in the pixel given by (x,y). */
|
||||
if x1 > x0 then
|
||||
set deltax to x1 - x0
|
||||
set stepx to +1
|
||||
otherwise
|
||||
set deltax to x0 - x1
|
||||
set stepx to -1
|
||||
end if
|
||||
|
||||
set error to deltax - deltay
|
||||
until x0 = x1 + stepx or y0 = y1 + stepy
|
||||
setPixel(x0, y0)
|
||||
if error × 2 ≥ -deltay then
|
||||
set x0 to x0 + stepx
|
||||
set error to error - deltay
|
||||
end if
|
||||
if error × 2 ≤ deltax then
|
||||
set y0 to y0 + stepy
|
||||
set error to error + deltax
|
||||
end if
|
||||
repeat
|
||||
```
|
||||
|
||||
Rather than numbered lists as I have used so far, this representation of an algorithm is far more common. See if you can implement this yourself. For reference, I have provided my implementation below.
|
||||
|
||||
```
|
||||
.globl DrawLine
|
||||
DrawLine:
|
||||
push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
|
||||
x0 .req r9
|
||||
x1 .req r10
|
||||
y0 .req r11
|
||||
y1 .req r12
|
||||
|
||||
mov x0,r0
|
||||
mov x1,r2
|
||||
mov y0,r1
|
||||
mov y1,r3
|
||||
|
||||
dx .req r4
|
||||
dyn .req r5 /* Note that we only ever use -deltay, so I store its negative for speed. (hence dyn) */
|
||||
sx .req r6
|
||||
sy .req r7
|
||||
err .req r8
|
||||
|
||||
cmp x0,x1
|
||||
subgt dx,x0,x1
|
||||
movgt sx,#-1
|
||||
suble dx,x1,x0
|
||||
movle sx,#1
|
||||
|
||||
cmp y0,y1
|
||||
subgt dyn,y1,y0
|
||||
movgt sy,#-1
|
||||
suble dyn,y0,y1
|
||||
movle sy,#1
|
||||
|
||||
add err,dx,dyn
|
||||
add x1,sx
|
||||
add y1,sy
|
||||
|
||||
pixelLoop$:
|
||||
|
||||
teq x0,x1
|
||||
teqne y0,y1
|
||||
popeq {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
|
||||
|
||||
mov r0,x0
|
||||
mov r1,y0
|
||||
bl DrawPixel
|
||||
|
||||
cmp dyn, err,lsl #1
|
||||
addle err,dyn
|
||||
addle x0,sx
|
||||
|
||||
cmp dx, err,lsl #1
|
||||
addge err,dx
|
||||
addge y0,sy
|
||||
|
||||
b pixelLoop$
|
||||
|
||||
.unreq x0
|
||||
.unreq x1
|
||||
.unreq y0
|
||||
.unreq y1
|
||||
.unreq dx
|
||||
.unreq dyn
|
||||
.unreq sx
|
||||
.unreq sy
|
||||
.unreq err
|
||||
```
|
||||
|
||||
### 3 Randomness
|
||||
|
||||
So, now we can draw lines. Although we could use this to draw pictures and whatnot (feel free to do so!), I thought I would take the opportunity to introduce the idea of computer randomness. What we will do is select a pair of random co-ordinates, and then draw a line from the last pair to that point in steadily incrementing colours. I do this purely because it looks quite pretty.
|
||||
|
||||
```
|
||||
Hardware random number generators are occasionally used in security, where the predictability sequence of random numbers may affect the security of some encryption.
|
||||
```
|
||||
|
||||
So, now it comes down to it, how do we be random? Unfortunately for us there isn't some device which generates random numbers (such devices are very rare). So somehow using only the operations we've learned so far we need to invent 'random numbers'. It shouldn't take you long to realise this is impossible. The operations always have well defined results, executing the same sequence of instructions with the same registers yields the same answer. What we instead do is deduce a sequence that is pseudo random. This means numbers that, to the outside observer, look random, but in fact were completely determined. So, we need a formula to generate random numbers. One might be tempted to just spam mathematical operators out for example: 4x2! / 64, but in actuality this generally produces low quality random numbers. In this case for example, if x were 0, the answer would be 0. Stupid though it sounds, we need a very careful choice of equation to produce high quality random numbers.
|
||||
|
||||
```
|
||||
This sort of discussion often begs the question what do we mean by a random number? We generally mean statistical randomness: A sequence of numbers that has no obvious patterns or properties that could be used to generalise it.
|
||||
```
|
||||
|
||||
The method I'm going to teach you is called the quadratic congruence generator. This is a good choice because it can be implemented in 5 instructions, and yet generates a seemingly random order of the numbers from 0 to 232-1.
|
||||
|
||||
The reason why the generator can create such long sequence with so few instructions is unfortunately a little beyond the scope of this course, but I encourage the interested to research it. It all centralises on the following quadratic formula, where xn is the nth random number generated.
|
||||
|
||||
x_(n+1) = ax_(n)^2 + bx_(n) + c mod 2^32
|
||||
|
||||
Subject to the following constraints:
|
||||
|
||||
1. a is even
|
||||
|
||||
2. b = a + 1 mod 4
|
||||
|
||||
3. c is odd
|
||||
|
||||
|
||||
|
||||
|
||||
If you've not seen mod before, it means the remainder of a division by the number after it. For example b = a + 1 mod 4 means that b is the remainder of dividing a + 1 by 4, so if a were 12 say, b would be 1 as a + 1 is 13, and 13 divided by 4 is 3 remainder 1.
|
||||
|
||||
Copy the following code into a file called 'random.s'.
|
||||
|
||||
```
|
||||
.globl Random
|
||||
Random:
|
||||
xnm .req r0
|
||||
a .req r1
|
||||
|
||||
mov a,#0xef00
|
||||
mul a,xnm
|
||||
mul a,xnm
|
||||
add a,xnm
|
||||
.unreq xnm
|
||||
add r0,a,#73
|
||||
|
||||
.unreq a
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
This is an implementation of the random function, with an input of the last value generated in r0, and an output of the next number. In my case, I've used a = EF0016, b = 1, c = 73. This choice was arbitrary but meets the requirements above. Feel free to use any numbers you wish instead, as long as they obey the rules.
|
||||
|
||||
### 4 Pi-casso
|
||||
|
||||
OK, now we have all the functions we're going to need, let's try it out. Alter main to do the following, after getting the frame buffer info address:
|
||||
|
||||
1. Call SetGraphicsAddress with r0 containing the frame buffer info address.
|
||||
2. Set four registers to 0. One will be the last random number, one will be the colour, one will be the last x co-ordinate and one will be the last y co-ordinate.
|
||||
3. Call random to generate the next x-coordinate, using the last random number as the input.
|
||||
4. Call random again to generate the next y-coordinate, using the x-coordinate you generated as an input.
|
||||
5. Update the last random number to contain the y-coordinate.
|
||||
6. Call SetForeColour with the colour, then increment the colour. If it goes above FFFF16, make sure it goes back to 0.
|
||||
7. The x and y coordinates we have generated are between 0 and FFFFFFFF16. Convert them to a number between 0 and 102310 by using a logical shift right of 22.
|
||||
8. Check the y coordinate is on the screen. Valid y coordinates are between 0 and 76710. If not, go back to 3.
|
||||
9. Draw a line from the last x and y coordinates to the current x and y coordinates.
|
||||
10. Update the last x and y coordinates to contain the current ones.
|
||||
11. Go back to 3.
|
||||
|
||||
|
||||
|
||||
As always, a solution for this can be found on the downloads page.
|
||||
|
||||
Once you've finished, test it on the Raspberry Pi. You should see a very fast sequence of random lines being drawn on the screen, in steadily incrementing colours. This should never stop. If it doesn't work, please see our troubleshooting page.
|
||||
|
||||
When you have it working, congratulations! We've now learned about meaningful graphics, and also about random numbers. I encourage you to play with line drawing, as it can be used to render almost anything you want. You may also want to explore more complicated shapes. Most can be made out of lines, but is this necessarily the best strategy? If you like the line program, try experimenting with the SetPixel function. What happens if instead of just setting the value of the pixel, you increase it by a small amount? What other patterns can you make? In the next lesson, [Lesson 8: Screen 03][2], we will look at the invaluable skill of drawing text.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen02.html
|
||||
|
||||
作者:[Alex Chadwick][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.cl.cam.ac.uk
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen03.html
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,129 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (beamrolling)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Remote Working Survival Guide)
|
||||
[#]: via: (https://www.jonobacon.com/2019/01/14/remote-working-survival/)
|
||||
[#]: author: (Jono Bacon https://www.jonobacon.com/author/admin/)
|
||||
|
||||
远程工作生存指南
|
||||
======
|
||||
![](https://www.jonobacon.com/wp-content/uploads/2019/01/5b5471d7eadb585ec8b8a0c3_featureimage-remotejob-1080x675.jpg)
|
||||
|
||||
远程工作似乎是最近的一个热门话题。CNBC 报道称, [70% 的专业人士至少每周在家工作一次][1]。同样地,CoSo Cloud 调查发现, [77% 的人在远程工作时效率更高][2] ,而 aftercollege 的一份调查显示, [8% 的千禧一代会更多地考虑提供远程工作的公司][3]。 这看起来很合理:技术,网络以及文化似乎越来越推动远程工作的发展。哦,自制咖啡也比以前任何时候更好喝了。
|
||||
|
||||
目前,我准备写另一篇关于公司如何优化远程工作的文章(所以请确保你加入我们的会员以持续关注——这是免费的)。
|
||||
|
||||
但今天,我想 **分享一些个人如何做好远程工作的建议**。 不管你是全职远程工作者,或者是可以选择一周某几天在家工作的人,希望这篇文章对你有用。
|
||||
|
||||
眼下,你需要明白, **远程工作不是万能药**。当然,穿着睡衣满屋子乱逛,听听反社会音乐,喝一大杯咖啡看起来似乎挺完美的,但这不适合每个人。
|
||||
|
||||
有的人需要办公室的结构。有的人需要办公室的社会元素。有的人需要从家里走出来。有的人在家里缺乏保持关注的纪律。有的人因为好几年未缴退税而避免政府工作人员来住处敲门。
|
||||
|
||||
**远程工作就好像一块肌肉:如果你锻炼并且保持它,那么它能带来极大的力量和能力**。 如果不这么做,结果就不一样了。
|
||||
|
||||
在我职业生涯的大多数时间里,我在家工作。我喜欢这么做。当我在家工作的时候,我更有效率,更开心,更有能力。我并非不喜欢在办公室工作,我享受办公室的社会元素,但我更喜欢在家工作时我的“空间”。 我喜欢听重金属音乐,但当整个办公室的人不想听到 [After The Burial][5] 的时候,这会引起一些问题。
|
||||
![][6]
|
||||
“Squirrel.”
|
||||
[图片来源][7]
|
||||
|
||||
已经学会了如何正确平衡工作,旅行以及其他元素来管理我的远程工作,以下是我的一些建议。 请务必**在评论中分享一些你的建议**。
|
||||
|
||||
### 1\.你需要训练和习惯(以及了解你的“波浪”)
|
||||
|
||||
远程工作确实是需要训练的一块肌肉。就像构建真正的肌肉一样,它需要一个清楚的惯例和一小块健康的训练混合起来。
|
||||
|
||||
永远保持穿戴整齐(不要穿睡衣)。设置你一天工作的开始和结束时间(大多时候我从早上9点工作到下午6点)。选好你的午餐休息时间(我的是中午12点)。选好你的早晨仪式(我的是电子邮件,紧接着是全面审查客户需求)。决定你的主工作地在哪(我的主工作地是我家里的工作室)。决定好每天你什么时候运动(大多数时候我在下午5点运动)。
|
||||
|
||||
**设计一个实际的习惯并坚持66天**。构建一个习惯需要很长时间,不要尝试着背离你的习惯。你越坚持这个习惯,做下去所花费的功夫越少。在这66天的末尾,你想都不会想,自然而然地就按习惯去做了。
|
||||
|
||||
话虽这么说,我们又不住在真空里 ([更干净,或者别的什么][8])。我们都有自己的“波浪”。
|
||||
|
||||
“波浪”是你为了改变做事的方法时,对日常做出的一些改变。举个例子,夏天的时候我通常需要更多的阳光。那时我经常会在室外的花园工作。临近假期的时候我更容易分心,所以我在上班时间会更需要呆在室内。有时候我只想要多点人际接触,因此我会在咖啡馆工作几周。有时候我就是喜欢在厨房或者长椅上工作。你需要学习你的“波浪”并倾听你的身体。 **首先构建你自己的兴趣,然后在你认识到自己的“波浪”的时候再对它进行适当的修改**。
|
||||
|
||||
### 2\. 和你的同事以及上司一起设立预期
|
||||
|
||||
不是每个人都知道怎么远程工作,如果你的公司对远程工作没那么熟悉,你尤其需要和同事一起设立预期。
|
||||
|
||||
这件事十分简单:**当你要设计自己的工作日常的时候,清楚地跟你的上司和团队进行交流。**让他们知道如何找到你,紧急情况下如何联系你,以及你在家的时候如何保持合作。
|
||||
|
||||
这里的通信构件至关重要。有些远程工作者很怕离开他们的电脑,因为害怕当他们不在的时候有人给他们发消息(他们担心别人会觉得他们在边吃奇多边看 Netflix)。
|
||||
|
||||
你需要离开一会的时间。你需要吃午餐的时候眼睛不用一直盯着电脑屏幕。你又不是911接线员。 **设定预期以后,有时候你可能不能立刻回复,但你会尽快回复**。
|
||||
|
||||
同样地,设定你的一般可用性的预期。举个例子,我对客户设立的预期是我一般每天早上9点到下午6点工作。当然,如果某个客户急需某样东西,我很乐意在这段时间外回应他,但作为一个一般性规则,我通常只在这段时间内工作。这对于生活的平衡是必要的。
|
||||
|
||||
### 3\. 分心是你的敌人,它们需要管理
|
||||
|
||||
我们都会分心,这是人类的本能。让你分心的事情可能是你的孩子回家了,想玩变形金刚:救援机器人;可能是看看Facebook,Instagram,或者 Twitter 以确保你不会错过任何不受欢迎的政治观点,或者某人的午餐图片;可能是你生活中即将到来的某件事带走了你的注意力(例如,即将举办的婚礼,活动,或者一次大旅行)。
|
||||
|
||||
**你需要明白什么让你分心以及如何管理它**。举个例子,我知道我的电子邮件和 Twitter 会让我分心。我经常查看它们,并且每次查看都会让我脱离我正在工作的空间。拿水或者咖啡的时候我总会分心去吃零食,看 Youtube 的视频。
|
||||
|
||||
![][9]
|
||||
我的分心克星
|
||||
|
||||
由电子产品造成的分心有一个简单对策:**锁起来**。直到你完成你手头的事情再关闭选项卡。有繁重的工作的时候我总这么干:我把让我分心的东西锁起来,直到做完手头的工作。这需要控制能力,但所有的一切都需要。
|
||||
|
||||
因为别人影响而分心的元素更难解决。如果你是有家庭的人,你需要在你工作的时候不被打扰,你通常需要独处。这也是为什么家庭办公室这么重要:你需要设一些“爸爸/妈妈正在工作”的界限。如果有急事才能进来,否则让孩子自个儿玩去。
|
||||
|
||||
把让你分心的事分开有许多方法:把你的电话静音;把自己的状态设成“离开”;换到一个没有让你分心的事的房间(或建筑物)。再重申一次,了解是什么让你分心并控制好它。如果不这么做,你会永远被分心的事摆布。
|
||||
|
||||
### 4\. (良好的)关系需要面对面的关注
|
||||
|
||||
有的角色比其他角色与远程工作更合拍。例如,我见过工程、质量保证、支持、安全以及其他团队(通常更专注于数字协作)的出色工作。其他团队,如设计或营销,往往在远程环境下更难熬(因为它们更注重触觉)。
|
||||
|
||||
但是,对于任何团队而言,建立牢固的关系至关重要,而现场讨论,协作和社交很有必要。我们的许多感官(例如肢体语言)在数字环境中被删除,这些在我们建立信任和关系的方式中发挥着关键作用。
|
||||
|
||||
![][10]
|
||||
火箭也很有帮助
|
||||
|
||||
这尤为重要,如果(a)你初来这家公司,需要建立关系;(b)你是一个新角色,需要和你的团队建立关系;或者(c)你处于领导地位,建立买入和参与是你工作的关键部分。
|
||||
|
||||
**解决方法是?合理搭配远程工作与面对面的时间。** 如果你的公司就在附近,可以用一部分的时间在家工作,一部分时间在公司工作。如果你的公司比较远,安排定期前往办公室(并对你的上司设定你需要这么做的预期)。例如,当我在 XPRIZE 工作的时候,我每几周就会飞往洛杉矶几天。当我在 Canonical 工作时(总部在伦敦),我们每三个月来一次冲刺。
|
||||
|
||||
### 5\. 保持专注,不要松懈
|
||||
|
||||
本文所有内容的关键在于构建能力,并培养远程工作的肌肉。这就像建立你的日常,坚持它,并明白你的“波浪”和让你分心的事情以及如何管理它们一样简单。
|
||||
|
||||
我以一种相当具体的方式来看待这个世界:**我们所做的一切都有机会得到改进和完善**。举个例子,我已经公开演讲超过 15 年,但我总是能发现新的改进方法,以及修复新的错误(说到这些,请参阅我的 [提升你公众演讲的10个方法][11])。
|
||||
|
||||
发现新的改善方法,以及把每个绊脚石和错误视为一个开启新的不同的“啊哈!”时刻让人兴奋。远程工作和这没什么不同:寻找有助于解锁方式的模式,让你的远程工作时间更高效,更舒适,更有趣。
|
||||
|
||||
![][12]
|
||||
看看这些书。它们非常适合个人发展。
|
||||
参阅我的 [150 美元个人发展工具包][13] 文章
|
||||
|
||||
...但别为此狂热。有的人花尽他们每一分钟来关注如何变得更好,他们经常以“做得还不够好”,“完成度不够高”等为由打击自己,无法达到他们内心关于完美的不切实际的观点。
|
||||
|
||||
我们都是人,我们是有生命的,不是机器人。始终致力于改进,但要明白不是所有东西都是完美的。你将会有一些休息日或休息周。你将会因为压力和倦怠而挣扎。你将会处理一些在办公室比远程工作更容易的情况。从这些时刻中学习,但不要沉迷于此。生命太短暂了。
|
||||
|
||||
**你有什么提示,技巧和建议吗?你如何管理远程工作?我的建议中还缺少什么吗?在评论区中与我分享!**
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.jonobacon.com/2019/01/14/remote-working-survival/
|
||||
|
||||
作者:[Jono Bacon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[beamrolling](https://github.com/beamrolling)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.jonobacon.com/author/admin/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cnbc.com/2018/05/30/70-percent-of-people-globally-work-remotely-at-least-once-a-week-iwg-study.html
|
||||
[2]: http://www.cosocloud.com/press-release/connectsolutions-survey-shows-working-remotely-benefits-employers-and-employees
|
||||
[3]: https://www.aftercollege.com/cf/2015-annual-survey
|
||||
[4]: https://www.jonobacon.com/join/
|
||||
[5]: https://www.facebook.com/aftertheburial/
|
||||
[6]: https://www.jonobacon.com/wp-content/uploads/2019/01/aftertheburial2.jpg
|
||||
[7]: https://skullsnbones.com/burial-live-photos-vans-warped-tour-denver-co/
|
||||
[8]: https://www.youtube.com/watch?v=wK1PNNEKZBY
|
||||
[9]: https://www.jonobacon.com/wp-content/uploads/2019/01/IMG_20190114_102429-1024x768.jpg
|
||||
[10]: https://www.jonobacon.com/wp-content/uploads/2019/01/15381733956_3325670fda_k-1024x576.jpg
|
||||
[11]: https://www.jonobacon.com/2018/12/11/10-ways-to-up-your-public-speaking-game/
|
||||
[12]: https://www.jonobacon.com/wp-content/uploads/2019/01/DwVBxhjX4AgtJgV-1024x532.jpg
|
||||
[13]: https://www.jonobacon.com/2017/11/13/150-dollar-personal-development-kit/
|
@ -0,0 +1,463 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (qhwdw)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Computer Laboratory – Raspberry Pi: Lesson 7 Screen02)
|
||||
[#]: via: (https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen02.html)
|
||||
[#]: author: (Alex Chadwick https://www.cl.cam.ac.uk)
|
||||
|
||||
计算机实验室 – 树莓派:课程 7 屏幕02
|
||||
======
|
||||
|
||||
屏幕02 课程在屏幕01 的基础上构建,它教你如何绘制线和一个生成伪随机数的小特性。假设你已经有了 [课程6:屏幕01][1] 的操作系统代码,我们将以它为基础来构建。
|
||||
|
||||
### 1、点
|
||||
|
||||
现在,我们的屏幕已经正常工作了,现在开始去创建一个更实用的图像,是水到渠成的事。如果我们能够绘制出更实用的图形那就更好了。如果我们能够在屏幕上的两点之间绘制一条线,那我们就能够组合这些线绘制出更复杂的图形了。
|
||||
|
||||
```
|
||||
为了绘制出更复杂的图形,一些方法使用一个着色函数而不是一个颜色去绘制。每个点都能够调用着色函数来确定在那里用什么颜色去绘制。
|
||||
```
|
||||
|
||||
我们将尝试用汇编代码去实现它,但在开始时,我们确实需要使用一些其它的函数去帮助它。我们需要一个函数,我将调用 `SetPixel` 去修改指定像素的颜色,在寄存器 `r0` 和 `r1` 中提供输入。如果我们写出的代码可以在任意内存中而不仅仅是屏幕上绘制图形,这将在以后非常有用,因此,我们首先需要一些控制真实绘制位置的方法。我认为实现上述目标的最好方法是,能够有一个内存片段用于保存将要绘制的图形。我应该最终使用它来保存地址,这个地址就是指向到自上次以来的帧缓存结构上。我们将在后面的代码中使用这个绘制方法。这样,如果我们想在我们的操作系统的另一部分绘制一个不同的图像,我们就可以生成一个不同结构的地址值,而使用的是完全相同的代码。为简单起见,我们将使用另一个数据片段去控制我们绘制的颜色。
|
||||
|
||||
复制下列代码到一个名为 `drawing.s` 的新文件中。
|
||||
|
||||
```assembly
|
||||
.section .data
|
||||
.align 1
|
||||
foreColour:
|
||||
.hword 0xFFFF
|
||||
|
||||
.align 2
|
||||
graphicsAddress:
|
||||
.int 0
|
||||
|
||||
.section .text
|
||||
.globl SetForeColour
|
||||
SetForeColour:
|
||||
cmp r0,#0x10000
|
||||
movhs pc,lr
|
||||
ldr r1,=foreColour
|
||||
strh r0,[r1]
|
||||
mov pc,lr
|
||||
|
||||
.globl SetGraphicsAddress
|
||||
SetGraphicsAddress:
|
||||
ldr r1,=graphicsAddress
|
||||
str r0,[r1]
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
这段代码就是我上面所说的一对函数以及它们的数据。我们将在 `main.s` 中使用它们,在绘制图像之前去控制在何处绘制什么内容。
|
||||
|
||||
```
|
||||
构建一个通用方法,比如 `SetPixel`,我们将在它之上构建另一个方法是一个很好的创意。但我们必须要确保这个方法很快,因为我们要经常使用它。
|
||||
```
|
||||
|
||||
我们的下一个任务是去实现一个 `SetPixel` 方法。它需要带两个参数,像素的 x 和 y 轴,并且它应该会使用 `graphicsAddress` 和 `foreColour`,我们只定义精确控制在哪里绘制什么图像即可。如果你认为你能立即实现这些,那么去动手实现吧,如果不能,按照我们提供的步骤,按示例去实现它。
|
||||
|
||||
1. 加载 `graphicsAddress`。
|
||||
2. 检查像素的 x 和 y 轴是否小于宽度和高度。
|
||||
3. 计算要写入的像素地址(提示:`frameBufferAddress +(x + y * 宽度)* 像素大小`)
|
||||
4. 加载 `foreColour`。
|
||||
5. 保存到地址。
|
||||
|
||||
|
||||
|
||||
上述步骤实现如下:
|
||||
|
||||
1.
|
||||
```assembly
|
||||
.globl DrawPixel
|
||||
DrawPixel:
|
||||
px .req r0
|
||||
py .req r1
|
||||
addr .req r2
|
||||
ldr addr,=graphicsAddress
|
||||
ldr addr,[addr]
|
||||
```
|
||||
|
||||
2.
|
||||
```assembly
|
||||
height .req r3
|
||||
ldr height,[addr,#4]
|
||||
sub height,#1
|
||||
cmp py,height
|
||||
movhi pc,lr
|
||||
.unreq height
|
||||
|
||||
width .req r3
|
||||
ldr width,[addr,#0]
|
||||
sub width,#1
|
||||
cmp px,width
|
||||
movhi pc,lr
|
||||
```
|
||||
|
||||
记住,宽度和高度被各自保存在帧缓冲偏移量的 0 和 4 处。如有必要可以参考 `frameBuffer.s`。
|
||||
|
||||
3.
|
||||
```assembly
|
||||
ldr addr,[addr,#32]
|
||||
add width,#1
|
||||
mla px,py,width,px
|
||||
.unreq width
|
||||
.unreq py
|
||||
add addr, px,lsl #1
|
||||
.unreq px
|
||||
```
|
||||
|
||||
```assembly
|
||||
mla dst,reg1,reg2,reg3 将寄存器 `reg1` 和 `reg2` 中的值相乘,然后将结果与寄存器 `reg3` 中的值相加,并将结果的低 32 位保存到 dst 中。
|
||||
```
|
||||
|
||||
确实,这段代码是专用于高色值帧缓存的,因为我使用一个逻辑左移操作去计算地址。你可能希望去编写一个不需要专用的高色值帧缓冲的函数版本,记得去更新 `SetForeColour` 的代码。它实现起来可能更复杂一些。
|
||||
|
||||
4.
|
||||
```assembly
|
||||
fore .req r3
|
||||
ldr fore,=foreColour
|
||||
ldrh fore,[fore]
|
||||
```
|
||||
|
||||
以上是专用于高色值的。
|
||||
|
||||
5.
|
||||
```assembly
|
||||
strh fore,[addr]
|
||||
.unreq fore
|
||||
.unreq addr
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
以上是专用于高色值的。
|
||||
|
||||
|
||||
|
||||
|
||||
### 2、线
|
||||
|
||||
问题是,线的绘制并不是你所想像的那么简单。到目前为止,你必须认识到,编写一个操作系统时,几乎所有的事情都必须我们自己去做,绘制线条也不例外。我建议你们花点时间想想如何在任意两点之间绘制一条线。
|
||||
|
||||
```
|
||||
在我们日常编程中,我们对像除法这样的运算通常懒得去优化。但是操作系统不同,它必须高效,因此我们要始终专注于如何让事情做的尽可能更好。
|
||||
```
|
||||
|
||||
我估计大多数的策略可能是去计算线的梯度,并沿着它来绘制。这看上去似乎很完美,但它事实上是个很糟糕的主意。主要问题是它涉及到除法,我们知道在汇编中,做除法很不容易,并且还要始终记录小数,这也很困难。事实上,在这里,有一个叫布鲁塞姆的算法,它非常适合汇编代码,因为它只使用加法、减法和位移运算。
|
||||
|
||||
|
||||
|
||||
> 我们从定义一个简单的直线绘制算法开始,代码如下:
|
||||
>
|
||||
> ```matlab
|
||||
> /* 我们希望从 (x0,y0) 到 (x1,y1) 去绘制一条线,只使用一个函数 setPixel(x,y),它的功能是在给定的 (x,y) 上绘制一个点。 */
|
||||
>
|
||||
> if x1 > x0 then
|
||||
>
|
||||
> set deltax to x1 - x0
|
||||
> set stepx to +1
|
||||
>
|
||||
> otherwise
|
||||
>
|
||||
> set deltax to x0 - x1
|
||||
> set stepx to -1
|
||||
>
|
||||
> end if
|
||||
>
|
||||
> if y1 > y0 then
|
||||
>
|
||||
> set deltay to y1 - y0
|
||||
> set stepy to +1
|
||||
>
|
||||
> otherwise
|
||||
>
|
||||
> set deltay to y0 - y1
|
||||
> set stepy to -1
|
||||
>
|
||||
> end if
|
||||
>
|
||||
> if deltax > deltay then
|
||||
>
|
||||
> set error to 0
|
||||
> until x0 = x1 + stepx
|
||||
>
|
||||
> setPixel(x0, y0)
|
||||
> set error to error + deltax ÷ deltay
|
||||
> if error ≥ 0.5 then
|
||||
>
|
||||
> set y0 to y0 + stepy
|
||||
> set error to error - 1
|
||||
>
|
||||
> end if
|
||||
> set x0 to x0 + stepx
|
||||
>
|
||||
> repeat
|
||||
>
|
||||
> otherwise
|
||||
>
|
||||
> end if
|
||||
> ```
|
||||
>
|
||||
> 这个算法用来表示你可能想像到的那些东西。变量 `error` 用来记录你离实线的距离。沿着 x 轴每走一步,这个 `error` 的值都会增加,而沿着 y 轴每走一步,这个 `error` 值就会减 1 个单位。`error` 是用于测量距离 y 轴的距离。
|
||||
>
|
||||
> 虽然这个算法是有效的,但它存在一个重要的问题,很明显,我们使用了小数去保存 `error`,并且也使用了除法。所以,一个立即要做的优化将是去改变 `error` 的单位。这里并不需要用特定的单位去保存它,只要我们每次使用它时都按相同数量去伸缩即可。所以,我们可以重写这个算法,通过在所有涉及 `error` 的等式上都简单地乘以 `deltay`,从面让它简化。下面只展示主要的循环:
|
||||
>
|
||||
> ```matlab
|
||||
> set error to 0 × deltay
|
||||
> until x0 = x1 + stepx
|
||||
>
|
||||
> setPixel(x0, y0)
|
||||
> set error to error + deltax ÷ deltay × deltay
|
||||
> if error ≥ 0.5 × deltay then
|
||||
>
|
||||
> set y0 to y0 + stepy
|
||||
> set error to error - 1 × deltay
|
||||
>
|
||||
> end if
|
||||
> set x0 to x0 + stepx
|
||||
>
|
||||
> repeat
|
||||
> ```
|
||||
>
|
||||
> 它将简化为:
|
||||
>
|
||||
> ```matlab
|
||||
> cset error to 0
|
||||
> until x0 = x1 + stepx
|
||||
>
|
||||
> setPixel(x0, y0)
|
||||
> set error to error + deltax
|
||||
> if error × 2 ≥ deltay then
|
||||
>
|
||||
> set y0 to y0 + stepy
|
||||
> set error to error - deltay
|
||||
>
|
||||
> end if
|
||||
> set x0 to x0 + stepx
|
||||
>
|
||||
> repeat
|
||||
> ```
|
||||
>
|
||||
> 突然,我们有了一个更好的算法。现在,我们看一下如何完全去除所需要的除法运算。最好保留唯一的被 2 相乘的乘法运算,我们知道它可以通过左移 1 位来实现!现在,这是非常接近布鲁塞姆算法的,但还可以进一步优化它。现在,我们有一个 `if` 语句,它将导致产生两个代码块,其中一个用于 x 差异较大的线,另一个用于 y 差异较大的线。对于这两种类型的线,如果审查代码能够将它们转换成一个单语句,还是很值得去做的。
|
||||
>
|
||||
> 困难之处在于,在第一种情况下,`error` 是与 y 一起变化,而第二种情况下 `error` 是与 x 一起变化。解决方案是在一个变量中同时记录它们,使用负的 `error` 去表示 x 中的一个 `error`,而用正的 `error` 表示它是 y 中的。
|
||||
>
|
||||
> ```matlab
|
||||
> set error to deltax - deltay
|
||||
> until x0 = x1 + stepx or y0 = y1 + stepy
|
||||
>
|
||||
> setPixel(x0, y0)
|
||||
> if error × 2 > -deltay then
|
||||
>
|
||||
> set x0 to x0 + stepx
|
||||
> set error to error - deltay
|
||||
>
|
||||
> end if
|
||||
> if error × 2 < deltax then
|
||||
>
|
||||
> set y0 to y0 + stepy
|
||||
> set error to error + deltax
|
||||
>
|
||||
> end if
|
||||
>
|
||||
> repeat
|
||||
> ```
|
||||
>
|
||||
> 你可能需要一些时间来搞明白它。在每一步中,我们都认为它正确地在 x 和 y 中移动。我们通过检查来做到这一点,如果我们在 x 或 y 轴上移动,`error` 的数量会变低,那么我们就继续这样移动。
|
||||
>
|
||||
|
||||
|
||||
```
|
||||
布鲁塞姆算法是在 1962 年由 Jack Elton Bresenham 开发,当时他 24 岁,正在攻读博士学位。
|
||||
```
|
||||
|
||||
用于画线的布鲁塞姆算法可以通过以下的伪代码来描述。以下伪代码是文本,它只是看起来有点像是计算机指令而已,但它却能让程序员实实在在地理解算法,而不是为机器可读。
|
||||
|
||||
```matlab
|
||||
/* 我们希望从 (x0,y0) 到 (x1,y1) 去绘制一条线,只使用一个函数 setPixel(x,y),它的功能是在给定的 (x,y) 上绘制一个点。 */
|
||||
|
||||
if x1 > x0 then
|
||||
set deltax to x1 - x0
|
||||
set stepx to +1
|
||||
otherwise
|
||||
set deltax to x0 - x1
|
||||
set stepx to -1
|
||||
end if
|
||||
|
||||
set error to deltax - deltay
|
||||
until x0 = x1 + stepx or y0 = y1 + stepy
|
||||
setPixel(x0, y0)
|
||||
if error × 2 ≥ -deltay then
|
||||
set x0 to x0 + stepx
|
||||
set error to error - deltay
|
||||
end if
|
||||
if error × 2 ≤ deltax then
|
||||
set y0 to y0 + stepy
|
||||
set error to error + deltax
|
||||
end if
|
||||
repeat
|
||||
```
|
||||
|
||||
与我们目前所使用的编号列表不同,这个算法的表示方式更常用。看看你能否自己实现它。我在下面提供了我的实现作为参考。
|
||||
|
||||
```assembly
|
||||
.globl DrawLine
|
||||
DrawLine:
|
||||
push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
|
||||
x0 .req r9
|
||||
x1 .req r10
|
||||
y0 .req r11
|
||||
y1 .req r12
|
||||
|
||||
mov x0,r0
|
||||
mov x1,r2
|
||||
mov y0,r1
|
||||
mov y1,r3
|
||||
|
||||
dx .req r4
|
||||
dyn .req r5 /* 注意,我们只使用 -deltay,因此为了速度,我保存它的负值。(因此命名为 dyn)*/
|
||||
sx .req r6
|
||||
sy .req r7
|
||||
err .req r8
|
||||
|
||||
cmp x0,x1
|
||||
subgt dx,x0,x1
|
||||
movgt sx,#-1
|
||||
suble dx,x1,x0
|
||||
movle sx,#1
|
||||
|
||||
cmp y0,y1
|
||||
subgt dyn,y1,y0
|
||||
movgt sy,#-1
|
||||
suble dyn,y0,y1
|
||||
movle sy,#1
|
||||
|
||||
add err,dx,dyn
|
||||
add x1,sx
|
||||
add y1,sy
|
||||
|
||||
pixelLoop$:
|
||||
|
||||
teq x0,x1
|
||||
teqne y0,y1
|
||||
popeq {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
|
||||
|
||||
mov r0,x0
|
||||
mov r1,y0
|
||||
bl DrawPixel
|
||||
|
||||
cmp dyn, err,lsl #1
|
||||
addle err,dyn
|
||||
addle x0,sx
|
||||
|
||||
cmp dx, err,lsl #1
|
||||
addge err,dx
|
||||
addge y0,sy
|
||||
|
||||
b pixelLoop$
|
||||
|
||||
.unreq x0
|
||||
.unreq x1
|
||||
.unreq y0
|
||||
.unreq y1
|
||||
.unreq dx
|
||||
.unreq dyn
|
||||
.unreq sx
|
||||
.unreq sy
|
||||
.unreq err
|
||||
```
|
||||
|
||||
### 3、随机性
|
||||
|
||||
到目前,我们可以绘制线条了。虽然我们可以使用它来绘制图片及诸如此类的东西(你可以随意去做!),我想应该借此机会引入计算机中随机性的概念。我将这样去做,选择一对随机的坐标,然后从最后一对坐标用渐变色绘制一条线到那个点。我这样做纯粹是认为它看起来很漂亮。
|
||||
|
||||
```
|
||||
硬件随机数生成器是在安全中使用很少,可预测的随机数序列可能影响某些加密的安全。
|
||||
```
|
||||
|
||||
那么,总结一下,我们如何才能产生随机数呢?不幸的是,我们并没有产生随机数的一些设备(这种设备很罕见)。因此只能利用我们目前所学过的操作,需要我们以某种方式来发明`随机数`。你很快就会意识到这是不可能的。操作总是给出定义好的结果,用相同的寄存器运行相同的指令序列总是给出相同的答案。而我们要做的是推导出一个伪随机序列。这意味着数字在外人看来是随机的,但实际上它是完全确定的。因此,我们需要一个生成随机数的公式。其中有人可能会想到很垃圾的数学运算,比如:4x2! / 64,而事实上它产生的是一个低质量的随机数。在这个示例中,如果 x 是 0,那么答案将是 0。看起来很愚蠢,我们需要非常谨慎地选择一个能够产生高质量随机数的方程式。
|
||||
|
||||
```
|
||||
这类讨论经常寻求一个问题,那就是我们所谓的随机数到底是什么?通常从统计学的角度来说的随机性是:一组没有明显模式或属性能够概括它的数的序列。
|
||||
```
|
||||
|
||||
我将要教给你的方法叫“二次同余发生器”。这是一个非常好的选择,因为它能够在 5 个指令中实现,并且能够产生一个从 0 到 232-1 之间的看似很随机的数字序列。
|
||||
|
||||
不幸的是,对为什么使用如此少的指令能够产生如此长的序列的原因的研究,已经远超出了本课程的教学范围。但我还是鼓励有兴趣的人去研究它。它的全部核心所在就是下面的二次方程,其中 `xn` 是产生的第 `n` 个随机数。
|
||||
|
||||
x_(n+1) = ax_(n)^2 + bx_(n) + c mod 2^32
|
||||
|
||||
这个方程受到以下的限制:
|
||||
|
||||
1. a 是偶数
|
||||
|
||||
2. b = a + 1 mod 4
|
||||
|
||||
3. c 是奇数
|
||||
|
||||
|
||||
|
||||
|
||||
如果你之前没有见到过 `mod` 运算,我来解释一下,它的意思是被它后面的数相除之后的余数。比如 `b = a + 1 mod 4` 的意思是 `b` 是 `a + 1` 除以 `4` 的余数,因此,如果 `a` 是 12,那么 `b` 将是 `1`,因为 `a + 1` 是 13,而 `13` 除以 4 的结果是 3 余 1。
|
||||
|
||||
复制下列代码到名为 `random.s` 的文件中。
|
||||
|
||||
```assembly
|
||||
.globl Random
|
||||
Random:
|
||||
xnm .req r0
|
||||
a .req r1
|
||||
|
||||
mov a,#0xef00
|
||||
mul a,xnm
|
||||
mul a,xnm
|
||||
add a,xnm
|
||||
.unreq xnm
|
||||
add r0,a,#73
|
||||
|
||||
.unreq a
|
||||
mov pc,lr
|
||||
```
|
||||
|
||||
这是随机函数的一个实现,使用一个在寄存器 `r0` 中最后生成的值作为输入,而接下来的数字则是输出。在我的案例中,我使用 a = EF00<sub>16</sub>,b = 1, c = 73。这个选择是随意的,但是需要满足上述的限制。你可以使用任何数字代替它们,只要符合上述的规则就行。
|
||||
|
||||
### 4、Pi-casso
|
||||
|
||||
OK,现在我们有了所有我们需要的函数,我们来试用一下它们。获取帧缓冲信息的地址之后,按如下的要求修改 `main`:
|
||||
|
||||
1. 使用包含了帧缓冲信息地址的寄存器 `r0` 调用 `SetGraphicsAddress`。
|
||||
2. 设置四个寄存器为 0。一个将是最后的随机数,一个将是颜色,一个将是最后的 x 坐标,而最后一个将是最后的 y 坐标。
|
||||
3. 调用 `random` 去产生下一个 x 坐标,使用最后一个随机数作为输入。
|
||||
4. 调用 `random` 再次去生成下一个 y 坐标,使用你生成的 x 坐标作为输入。
|
||||
5. 更新最后的随机数为 y 坐标。
|
||||
6. 使用 `colour` 值调用 `SetForeColour`,接着增加 `colour` 值。如果它大于 FFFF~16~,确保它返回为 0。
|
||||
7. 我们生成的 x 和 y 坐标将介于 0 到 FFFFFFFF~16~。通过将它们逻辑右移 22 位,将它们转换为介于 0 到 1023~10~ 之间的数。
|
||||
8. 检查 y 坐标是否在屏幕上。验证 y 坐标是否介于 0 到 767~10~ 之间。如果不在这个区间,返回到第 3 步。
|
||||
9. 从最后的 x 坐标和 y 坐标到当前的 x 坐标和 y 坐标之间绘制一条线。
|
||||
10. 更新最后的 x 和 y 坐标去为当前的坐标。
|
||||
11. 返回到第 3 步。
|
||||
|
||||
|
||||
|
||||
一如既往,你可以在下载页面上找到这个解决方案。
|
||||
|
||||
在你完成之后,在树莓派上做测试。你应该会看到一系列颜色递增的随机线条以非常快的速度出现在屏幕上。它一直持续下去。如果你的代码不能正常工作,请查看我们的排错页面。
|
||||
|
||||
如果一切顺利,恭喜你!我们现在已经学习了有意义的图形和随机数。我鼓励你去使用它绘制线条,因为它能够用于渲染你想要的任何东西,你可以去探索更复杂的图案了。它们中的大多数都可以由线条生成,但这需要更好的策略?如果你愿意写一个画线程序,尝试使用 `SetPixel` 函数。如果不是去设置像素值而是一点点地增加它,会发生什么情况?你可以用它产生什么样的图案?在下一节课 [课程 8:屏幕 03][2] 中,我们将学习绘制文本的宝贵技能。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen02.html
|
||||
|
||||
作者:[Alex Chadwick][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[qhwdw](https://github.com/qhwdw)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.cl.cam.ac.uk
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html
|
||||
[2]: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen03.html
|
Loading…
Reference in New Issue
Block a user