-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
416 lines (386 loc) · 23.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
<!DOCTYPE html>
<html lang="en" dir="auto">
<head>
<meta name="generator" content="Hugo 0.96.0" /><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="index, follow">
<title>TinyX</title>
<meta name="keywords" content="Blog, Portfolio, PaperMod">
<meta name="description" content="ExampleSite description">
<meta name="author" content="X">
<link rel="canonical" href="https://tinyx.me/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.min.48a18943c2fc15c38a372b8dde1f5e5dc0bc64fa6cb90f5a817d2f8c76b7f3ae.css" integrity="sha256-SKGJQ8L8FcOKNyuN3h9eXcC8ZPpsuQ9agX0vjHa3864=" rel="preload stylesheet" as="style">
<link rel="icon" href="https://tinyx.me/%3Clink%20/%20abs%20url%3E">
<link rel="icon" type="image/png" sizes="16x16" href="https://tinyx.me/%3Clink%20/%20abs%20url%3E">
<link rel="icon" type="image/png" sizes="32x32" href="https://tinyx.me/%3Clink%20/%20abs%20url%3E">
<link rel="apple-touch-icon" href="https://tinyx.me/%3Clink%20/%20abs%20url%3E">
<link rel="mask-icon" href="https://tinyx.me/%3Clink%20/%20abs%20url%3E">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" type="application/rss+xml" href="https://tinyx.me/index.xml">
<link rel="alternate" type="application/json" href="https://tinyx.me/index.json">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--hljs-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript><meta property="og:title" content="TinyX" />
<meta property="og:description" content="ExampleSite description" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://tinyx.me/" /><meta property="og:image" content="https://tinyx.me/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E"/><meta property="og:site_name" content="ExampleSite" />
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image" content="https://tinyx.me/%3Clink%20or%20path%20of%20image%20for%20opengraph,%20twitter-cards%3E"/>
<meta name="twitter:title" content="TinyX"/>
<meta name="twitter:description" content="ExampleSite description"/>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "TinyX",
"url": "https://tinyx.me",
"description": "ExampleSite description",
"thumbnailUrl": "https://tinyx.me/%3Clink%20/%20abs%20url%3E",
"sameAs": [
"https://twitter.com/", "https://github.com/JesseGuoX"
]
}
</script>
</head>
<body class="list" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="https://tinyx.me" accesskey="h" title="TinyX 👾 (Alt + H)">TinyX 👾</a>
<span class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
</span>
</div>
<ul id="menu">
<li>
<a href="https://tinyx.me/archives" title="Archive">
<span>Archive</span>
</a>
</li>
<li>
<a href="https://tinyx.me/categories/" title="Categories">
<span>Categories</span>
</a>
</li>
<li>
<a href="https://tinyx.me/search/" title="Search (Alt + /)" accesskey=/>
<span>Search</span>
</a>
</li>
<li>
<a href="https://tinyx.me/tags/" title="Tags">
<span>Tags</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="first-entry home-info">
<header class="entry-header">
<h1>Hi there 👋</h1>
</header>
<section class="entry-content">
<p>Welcome to my blog</p>
</section>
<footer class="entry-footer">
<div class="social-icons">
<a href="https://twitter.com/" target="_blank" rel="noopener noreferrer me" title="Twitter">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path
d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z">
</path>
</svg>
</a>
<a href="https://github.com/JesseGuoX" target="_blank" rel="noopener noreferrer me" title="Github">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path
d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22">
</path>
</svg>
</a>
</div>
</footer>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>Linux设备使用aplay无法播放声音
</h2>
</header>
<section class="entry-content">
<p>最近公司有个现场设备在使用过程中没有声音输出,单独排查了硬件和软件,发现都没有问题,而且只有应用软件内部播放的声音没有,手动播放其他音频文件有声音,排查了很久终于解决,记录如下。
现象描述 应用程序使用aplay播放音频,代码如下:
system("aplay /tmp/audio.wav"); 其中audio.wav已经由tts程序生成;
应用会在一些情况下无法播放音频,并且通过应用程序调用的aplay进程一直存在,但是在shell手动输入命令aplay /tmp/audio.wav 则可以正常播放;
使用strace跟踪该aplay进程如下:
lstat64("/tmp/pulse-PKdhtXMmr18n", 0xbeeae8c8) = -1 ENOENT (No such file or directory) umask(077) = 022 mkdir("/tmp/pulse-uuANIccKO515", 0700) = 0 umask(022) = 077 symlink("/tmp/pulse-uuANIccKO515", "/home/root/.config/pulse/e239376a56f6468e8c604babcc95431d-runtime.tmp") = -1 EEXIST (File exists) rmdir("/tmp/pulse-uuANIccKO515") = 0 clock_nanosleep_time64(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=13180137686533969536}, 0xbeeae878) = 0 readlink("/home/root/.config/pulse/e239376a56f6468e8c604babcc95431d-runtime", "/tmp/pulse-PKdhtXMmr18n", 99) = 23 lstat64("/tmp/pulse-PKdhtXMmr18n", 0xbeeae8c8) = -1 ENOENT (No such file or directory) umask(077) = 022 mkdir("/tmp/pulse-YR6cDgJaYrX3", 0700) = 0 umask(022) = 077 symlink("/tmp/pulse-YR6cDgJaYrX3", "/home/root/....</p>
</section>
<footer class="entry-footer"><span title='2022-10-24 16:25:06 +0800 CST'>October 24, 2022</span> · X</footer>
<a class="entry-link" aria-label="post link to Linux设备使用aplay无法播放声音" href="https://tinyx.me/post/aplay/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>Synology DS216Play 安装 ShadowSocks
</h2>
</header>
<section class="entry-content">
<p>最近一段时间买了个 NAS,用了之后感觉确实很不错,基本上就是一个家用的服务器,什么东西都可以往上扔。唯一后悔的就是买便宜了(毕竟穷),DS216Play 使用的是 STM STiH412 的 32位处理器,既然是 32位,所以一个大杀器-Docker 没法用了,也就是很多基于 Docker 的开箱即用第三方软件没法用。还有就是内置的 VideoStation 是从 IMDb 抓取封面信息,而 IMDb 是被墙了的。于是准备安装个 SS(ShadowSocks),顺便把 Dropbox 里面将近 100G 文件同步回来,之前买的 SSLedge 一个月才 30G 流量,要同步三个月才能完全把 Dropbox 上面文件同步回来,自建的 SS 直接是 1T,相当划算。
安装 ipkg 开始之前需要安装 ipkg 包管理器,这样后面很多软件包就能使用了。因为没有找到适合 STiH412 处理器的安装脚本,所以我们下一个相似的:
$ wget http://ipkg.nslu2-linux.org/feeds/optware/cs08q1armel/cross/unstable/syno-mvkw-bootstrap_1.2-7_arm.xsh $ chmod 700 syno-mvkw-bootstrap_1.2-7_arm.xsh $ sh syno-mvkw-bootstrap_1.2-7_arm.xsh 运行之后会报错,并生成一个 bootstrap 目录,进去 bootstrap 目录并修改 bootstrap.sh 文件
#if ! grep Feroceon-KW /proc/cpuinfo >/dev/null 2>&1; then # echo "Error: CPU not Marvell Kirkwood, probably wrong bootstrap....</p>
</section>
<footer class="entry-footer"><span title='2016-05-15 15:33:01 +0000 UTC'>May 15, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to Synology DS216Play 安装 ShadowSocks" href="https://tinyx.me/post/NAS-Shadowsocks/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>BeagleBone Black 从零到一 (3 Linux 镜像、initramfs、Device Tree及根文件系统)
</h2>
</header>
<section class="entry-content">
<p>基于 Linux 3.8
内核启动 BeagleBone Black 从零到一 (1 MLO、U-Boot) 这篇文章里讲到 U-Boot 启动之后会运行 uEnv.txt 文件里面 uenvcmd 指代的命令,我们也通常把加载镜像文件等命令写在这里。
U-Boot 有很多方法能启动内核,通常使用的是 bootm 或者 bootz 命令:
U-Boot# help bootz bootz - boot Linux zImage image from memory Usage: bootz [addr [initrd[:size]] [fdt]] - boot Linux zImage stored in memory The argument 'initrd' is optional and specifies the address of the initrd in memory. The optional argument ':size' allows specifying the size of RAW initrd....</p>
</section>
<footer class="entry-footer"><span title='2016-04-17 15:06:55 +0000 UTC'>April 17, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to BeagleBone Black 从零到一 (3 Linux 镜像、initramfs、Device Tree及根文件系统)" href="https://tinyx.me/post/BBB-Prepare-booting/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>解析 BeagleBone Black 官方镜像
</h2>
</header>
<section class="entry-content">
<p>BeagleBone 官方镜像: BeagleBoard.org Latest Firmware Images
下载推荐的镜像: bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img.xz
.xz 文件解压:
xz -d bone-debian-7.9-lxde-4gb-armhf-2015-11-12-4gb.img.xz 得到 .img 文件。
挂载镜像 在 Linux 下挂载 .img 文件,
可见直接挂载的话会出现:mount: you must specify the filesystem type。 首先,要说明一下的是,这情况是由于 img 文件的开头包含了 MBR,以致于系统无法识别。img 文件相当于一个包含操作系统的硬盘,而我们只需要挂载它的文件系统部分,所以需要绕过 MBR。
绕过 MBR 挂载文件系统有两种方法。
第一种: 首先使用 fdisk 查看分区信息:
看到第一个分区从第 2048 个扇区开始, Units = sectors of 1 * 512 = 512 bytes,Unit = 2048 * 512 = 1048576,所以我们偏移 1028576 个字节挂载第一个分区; 第二个分区从第 198656 个扇区开始,Unit = 198656 * 512 = 101711872,偏移 101711872 个字节挂载第二个分区;...</p>
</section>
<footer class="entry-footer"><span title='2016-03-26 19:37:17 +0000 UTC'>March 26, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to 解析 BeagleBone Black 官方镜像" href="https://tinyx.me/post/BeagleBone-Image/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>BeagleBone Black 从零到一 (2 MLO、U-Boot)
</h2>
</header>
<section class="entry-content">
<p>更新:2016-04-01
什么是 U-Boot 熟悉嵌入式开发的应该都听过它,U-boot 就是启动系统前的一段引导程序,虽然是引导程序,但是功能非常强大。
这一篇主要讲解如何从无到有运行 U-Boot,关于 U-Boot 引导 Linux 的部分放在另外一篇文章讲解。
U-Boot 之前的版本以版本号命名如:0.1.0, 0.2.0 这几年改为了以时间和日期命名:U-Boot 2016.03。
使用 git 获得 U-Boot 的源码:
git clone git://git.denx.de/u-boot.git 目前我使用的是 2016.02 的版本。
MLO 及其启动过程 上一篇文章,我们了解了 BeagleBone 有个 SPL 过程,就在这个时候读取 MLO 文件,MLO 文件其实是个精简版的 U-Boot,也是由 U-Boot 生成,但是功能有限,只初始化了部分资源如 DDR,然后启动 U-Boot。
MLO 文件是如何编译出来的 分析 MLO 的编译过程之前需要知道编译原理和 Makefile 等相关知识。 我们先找找 Makefile 看看能不能找到什么。建议使用 Sublime 编辑器。用全局查找功能查找 MLO 关键字。
找到 u-boot/scripts/Makefile.spl 文件 117行:
MLO MLO.byteswap: $(obj)/u-boot-spl.bin FORCE $(call if_changed,mkimage) 可以看到 MLO 文件是由 u-boot-spl....</p>
</section>
<footer class="entry-footer"><span title='2016-03-22 20:57:50 +0000 UTC'>March 22, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to BeagleBone Black 从零到一 (2 MLO、U-Boot)" href="https://tinyx.me/post/BBB-Uboot/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>BeagleBone Black 从零到一 (1 启动流程)
</h2>
</header>
<section class="entry-content">
<p>BeagleBone 的核心处理器是 AM3358,理解启动过程需要查看相应的数据手册。
AM335x 有四个不同的启动阶段:
ROM SPL(Secondary Program Loader) U-BOOT Linux Kernel 为什么 AM335x 有多个启动阶段呢?直接从启动源加载 U-Boot 启动不是很方便?
首先,第一步的 ROM Code 不可能太复杂,ROM大小是一个限制,最重要的还是因为其所能获取的系统信息太少,所以处理器只能使用简单的方法去寻找能完成复杂功能的代码,而后将处理器初始化工作交给它来完成。其次,SPL 也不能很复杂,因为 ROM Code 只能将它加载到处理器内部 RAM 中运行,一般处理器的内部 RAM 都要小于128KB,其大小注定其不能完成很复杂的功能,所以 SPL 需要初始化 DDR 再加更复杂的代码加载到 DDR 中运行。到了在 DDR RAM 中执行的 Bootloader(U-Boot算一个),其功能就比较完善了,此时就可以启动操作系统了。
第一阶段:ROM Code ROM Code 是芯片上电复位之后第一块自动运行的代码。ROM Code 固化在芯片中不能被用户修改。 ROM Code 存储在片上地址 0x40000000-0x40040000 处。
ROM Code 有两个主要的功能:
配置设备并初始化主要的外设 建立堆栈 配置开门狗定时器1(设置到三分钟) 配置 PLL 和系统时钟 为下一阶段启动做准备 为下一阶段启动检查启动源(SPL) 把下一启动阶段的 bootloader 代码移动到内存中准备运行 ROM Code 针对不同的启动源有不同的启动过程,但最终还是为了把启动源的代码搬运至内部 RAM 中运行,这里我们主要解析下针对 MMC/SD 卡设备,它的启动过程是怎么样的。...</p>
</section>
<footer class="entry-footer"><span title='2016-03-09 19:56:06 +0000 UTC'>March 9, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to BeagleBone Black 从零到一 (1 启动流程)" href="https://tinyx.me/post/BBB-bootmode/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>BeagleBone Black 从零到一 (0 硬件及环境搭建)
</h2>
</header>
<section class="entry-content">
<p>买了个 BeagleBone Black 准备从底层到应用层把整个 Linux 开发流程过一遍,并写一系列教程。
...</p>
</section>
<footer class="entry-footer"><span title='2016-03-05 20:44:52 +0000 UTC'>March 5, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to BeagleBone Black 从零到一 (0 硬件及环境搭建)" href="https://tinyx.me/post/BBB0-Hardware/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>建立一个便捷高效的嵌入式 Linux 开发环境
</h2>
</header>
<section class="entry-content">
<p>更新:2016-04-15
0 前言 我们经常需要在 Linux 环境下进行嵌入式开发,但是目前又不能完全抛弃 Windows 或者 OS X,所以我们经常需要用虚拟机来搭建开发环境,但是虚拟机又很臃肿,而且如果配置不高的电脑会运行的很慢。有没有一种方便在各电脑间拷贝运行速度又很快的解决方案呢?当然是有的。以下是几种解决方案。
...</p>
</section>
<footer class="entry-footer"><span title='2016-01-23 22:16:55 +0000 UTC'>January 23, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to 建立一个便捷高效的嵌入式 Linux 开发环境" href="https://tinyx.me/post/Running-headless-vm/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>EtherCAT 基础知识汇总
</h2>
</header>
<section class="entry-content">
<p>特性 EtherCAT(以太网控制自动化技术)是一个以以太网为基础的开放架构的现场总线系统,EtherCAT名称中的CAT为Control Automation Technology(控制自动化技术)首字母的缩写。最初由德国倍福自动化有限公司(Beckhoff Automation GmbH) 研发。EtherCAT为系统的实时性能和拓扑的灵活性树立了新的标准,同时,它还符合甚至降低了现场总线的使用成本。EtherCAT的特点还包括高精度设备同步,可选线缆冗余,和功能性安全协议(SIL3)。
...</p>
</section>
<footer class="entry-footer"><span title='2016-01-10 14:51:58 +0000 UTC'>January 10, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to EtherCAT 基础知识汇总" href="https://tinyx.me/post/EtherCAT-Note/"></a>
</article>
<article class="post-entry">
<header class="entry-header">
<h2>利用 TwinCAT 3 搭建 EtherCAT 主站环境
</h2>
</header>
<section class="entry-content">
<p>环境 网络上很多都是使用的 TwinCAT 2 和 WireShark 1.4 来建立主站程序并捕捉 EtherCAT 数据,这里做个新版本的教程,新的软件较旧软件使用方便。
软件 TwinCAT 3.1 – eXtended Automation Engineering (XAE) WireShark 2 硬件 PC利用 TwinCAT 作为主站,从站采用的是基于 ET1100 的从站开发板。
...</p>
</section>
<footer class="entry-footer"><span title='2016-01-06 19:28:08 +0000 UTC'>January 6, 2016</span> · X</footer>
<a class="entry-link" aria-label="post link to 利用 TwinCAT 3 搭建 EtherCAT 主站环境" href="https://tinyx.me/post/Setup-TwinCat/"></a>
</article>
<footer class="page-footer">
<nav class="pagination">
<a class="next" href="https://tinyx.me/page/2/">Next Page »</a>
</nav>
</footer>
</main>
<footer class="footer">
<span>© 2023 <a href="https://tinyx.me">TinyX</a></span>
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://git.io/hugopapermod" rel="noopener" target="_blank">PaperMod</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
</body>
</html>